基于单片机虚拟串口驱动LCD1602的电路仿真

合集下载

LCD1602的电路图和程序

LCD1602的电路图和程序

LCD1602的电路图和程序————————————————————————————————作者:————————————————————————————————日期:MS基于1602字符型液晶显示器的显示系统姓名:杨越班级:电子11-1学号:110400104一、实习目的(1)了解飞思卡尔单片机的基本原理,掌握其基本的工作流程。

(2)了解LCD1602的基本原理及用法。

(3)能够熟练使用CodeWarrior软件编写C语言程序,使用BDM仿真器下载程序。

(4)能够熟练焊接电路板。

二、实验设备与器件CodeWarrior软件,BDM仿真器,万用电路板,飞思卡尔单片机,LCD1602液晶显示器,三、实验内容内容:利用飞思卡尔单片机制作基于1602字符液晶显示器的显示系统要求:用四个按键控制,按下第一个按键显示1,按下第二个按键显示2,以此类推。

(1)LCD1602液晶显示器的原理:1602共16个管脚,但是编程用到的主要管脚不过三个,分别为:RS(数据命令选择端),R/W(读写选择端),E(使能信号);以后编程便主要围绕这三个管脚展开进行初始化,写命令,写数据。

以下具体阐述这三个管脚:RS为寄存器选择,高电平选择数据寄存器,低电平选择指令寄存器。

R/W为读写选择,高电平进行读操作,低电平进行写操作。

E端为使能端,后面和时序联系在一起。

除此外,D0~D7分别为8位双向数据线。

操作时序:RS R/W 操作说明0 0 写入指令码D0~D70 1 读取输出的D0~D7状态字1 0 写入数据D0~D71 1 从D0~D7读取数据注:关于E=H脉冲——开始时初始化E为0,然后置E为1,再清0.读取状态字时,注意D7位,D7=1,禁止读写操作;D7=0,允许读写操作;所以对控制器每次进行读写操作前,必须进行读写检测。

(即后面的读忙子程序)指令集:LCD_1602 初始化指令小结:0x38 设置16*2显示,5*7点阵,8位数据接口0x01 清屏0x0F 开显示,显示光标,光标闪烁0x08 只开显示0x0e 开显示,显示光标,光标不闪烁0x0c 开显示,不显示光标0x06 地址加1,当写入数据的时候光标右移0x02 地址计数器AC=0;(此时地址为0x80)光标归原点,但是DDRAM 中断内容不变0x18 光标和显示一起向左移动(2)飞思卡尔单片机的功能及特点:MC9S12XS128是 16 位单片机,由 16 位中央处理单元(CPU12X)、128KB 程序、Flash(P-lash)、8KB RAM、8KB 数据 Flash(D-lash)组成片内存储器。

51单片机任意2个IO口驱动LCD1602

51单片机任意2个IO口驱动LCD1602

51单片机任意2个IO口驱动LCD1602相信大家对1602显示屏已经十分熟悉,驱动方式有8线制(需要11根线)和4线制(需要7根线),这里为大家推荐一种只需要2根线就能驱动1602的方法。

之前在网上见到Arduino通过IIC驱动1602的实例,本人完全不懂Arduino程序,看了一下驱动电路,发现PCF8574这个关键芯片,它就相当于一个桥梁,将IIC总线转换为8位准双向口。

思路1、单片机通过IIC与PCF8574进行通信。

首先写好IIC通信程序,网上到处都是IIC通信程序,很容易找。

PCF8574 的器件地址为40h,由于硬件地址引脚A0-A2可寻址8 个器件,所以器件地址并不唯一,具体说明大家去查查PCF8574芯片手册。

2、单片机4线制驱动1602网上也有很多相关程序,我就不再多说。

4线制驱动方式需要7个IO口(RS、RW、E 和4条数据线),而PCF8574提供了8位准双向口,所以管脚还有剩余。

3、IIC通信程序和1602的4线制驱动程序相结合4、51单片机任意2个IO口驱动1602成功!!!。

(我只是个业余爱好者,要是各位觉得太低端那就见谅了)驱动电路图效果图实物图Proteus仿真程序#include <reg52.h>#include <intrins.h>sbit SCL = P3^0;sbit SDA = P3^1;bit ack;unsigned char LCD_data;unsigned char code digit[ ]={"0123456789"}; //定义字符数组显示数字//*****************延时************************void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)_nop_();}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i,j;for (i=0;i<n;i++)for (j=0;j<1140;j++);}void nop4(){_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期}//***************************************void Start(){SDA=1;_nop_();SCL=1;nop4();SDA=0;nop4();SCL=0;_nop_();_nop_();}void Stop(){SDA=0;_nop_();SCL=0;nop4();//>4us后SCL跳变SCL=1;nop4();SDA=1;_nop_();_nop_();}//******************************************void Write_A_Byte(unsigned char c){unsigned char BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位{if((c<<BitCnt)&0x80) SDA=1; //判断发送位else SDA=0;_nop_();SCL=1; //置时钟线为高,通知被控器开始接收数据位nop4();_nop_();SCL=0;}_nop_();_nop_();SDA=1; //8位发送完后释放数据线,准备接收应答位_nop_();_nop_();SCL=1;_nop_();_nop_();_nop_();if(SDA==1)ack=0;else ack=1; //判断是否接收到应答信号SCL=0;_nop_();_nop_();}bit Write_Random_Address_Byte(unsigned char add,unsigned char dat){Start(); //启动总线Write_A_Byte(add); //发送器件地址if(ack==0)return(0);Write_A_Byte(dat); //发送数据if(ack==0)return(0);Stop(); //结束总线return(1);}//********************液晶屏使能*********************void Enable_LCD_write(){LCD_data|=(1<<(3-1));//E=1;Write_Random_Address_Byte(0x40,LCD_data);delay_nus(2);LCD_data&=~(1<<(3-1));//E=0;Write_Random_Address_Byte(0x40,LCD_data);}//*************写命令****************************void LCD_write_command(unsigned char command){delay_nus(16);LCD_data&=~(1<<(1-1));//RS=0;LCD_data&=~(1<<(2-1));//RW=0;Write_Random_Address_Byte(0x40,LCD_data);LCD_data&=0X0f; //清高四位LCD_data|=command & 0xf0; //写高四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();command=command<<4; //低四位移到高四位LCD_data&=0x0f; //清高四位LCD_data|=command&0xf0; //写低四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();}//*************写数据****************************void LCD_write_data(unsigned char value){delay_nus(16);LCD_data|=(1<<(1-1));//RS=1;LCD_data&=~(1<<(2-1));//RW=0;Write_Random_Address_Byte(0x40,LCD_data);LCD_data&=0X0f; //清高四位LCD_data|=value&0xf0; //写高四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();value=value<<4; //低四位移到高四位LCD_data&=0x0f; //清高四位LCD_data|=value&0xf0; //写低四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();}//**********************设置显示位置********************************* void set_position(unsigned char x,unsigned char y){unsigned char position;if (y == 0)position = 0x80 + x;elseposition = 0xc0 + x;LCD_write_command(position);}//**********************显示字符串*****************************void display_string(unsigned char x,unsigned char y,unsigned char *s){set_position(x,y);while (*s){LCD_write_data(*s);s++;}}//*************液晶初始化****************************void LCD_init(void){LCD_write_command(0x28);delay_nus(40);LCD_write_command(0x28);delay_nus(40);Enable_LCD_write();delay_nus(40);LCD_write_command(0x28); //4位显示!!!!!!!!!!!!!!!!!!LCD_write_command(0x0c); //显示开LCD_write_command(0x01); //清屏delay_nms(2);}void main(void){LCD_init();display_string(4,0,"imxuheng"); //显示一段文字display_string(2,1,"Hello Today!"); //显示一段文字while(1);}程序还不够完美,自身工作与电学没什么关系,只是业余爱好鼓捣鼓捣,希望各位能够提出修改意见。

基于PROTEUS的LCD1602接口设计与仿真

基于PROTEUS的LCD1602接口设计与仿真
SUI Qing-jiang
摘要: 为 避 免 传 统 单 片 机 教 学 和 设 计 的 诸 多 弊 端 , 寻 求 单 片 机 与 嵌 入 式 系 统 开 发 新 思 路 , 本 文 以 功 能 强 大 的 PROTEUS 为 单
片 机 系 统 设 计 与 仿 真 平 台 , 设 计 了 AT89C51 单 片 机 与 典 型 LCD1602 的 硬 件 接 口 电 路 , 在 Keil 开 发 环 境 下 设 计 了 对 应 的 驱 动
程 序 , 并 在 PROTEUS 中 完 成 了 软 、 硬 件 的 联 合 仿 真 调 试 。 此 设 计 过 程 简 单 、 方 便 , 大 大 提 高 了 设 计 的 效 率 , 降 低 了 设 计 成 本 。 且
设计的电路及驱动程序对相应的实际应用系统具有一定的借鉴作用。
关键词: PROTEUS; AT89C51; LCD1602; 接口设计; 仿真调试
uchar code table[]="AT89C51 and LCD1602";
uchar code table1[]="Interface Desighn";
sbit lcden=P3^4;
sbit lcdrs=P3^5;
uchar num;

void delay(uint z) { //延时函数 uint x,y;
图 1 典型字符液晶模块实物图 隋清江: 教授 《PLC 技术应用 200 例》
图 2 AT89C51 与 LCD1602 的接口电路原理图
邮局订阅号:82-946 360 元 / 年 - 171 -
仿真技术
《微计算机信息》(测控自动化 )2010 年第 26 卷第 7-1 期

LCD1602学习——Proteus仿真(显示操作)

LCD1602学习——Proteus仿真(显示操作)

LCD1602学习——Proteus仿真(显⽰操作)学习关键:先看懂液晶操作时序图(写操作:写命令、写数据)读状态输⼊RS=L,R/W=H,E=H输出D0—D7=状态字写指令输⼊RS=L,R/W=L,D0—D7=指令输出⽆码,E=⾼脉冲读数据输⼊RS=H,R/W=H,E=H输出D0—D7=数据写数据输⼊RS=H,R/W=L,D0—D7=数据,E=输出⽆⾼脉冲由时序图可知,写操作时(包括写指令、写数据),RS=0;RW=0;再进⾏I/O⼝写操作,然后使能端⼝完成⼀次⾼脉冲(——⾼——低),这是液晶就会执⾏写操作的内容;1602液晶模块内部的控制器共有11条控制指令,如表10-14所⽰:序号指令RS R/W D7D6D5D4D3D2D1D01清显⽰00000000012光标返回000000001*3置输⼊模式00000001I/D S4显⽰开/关控制0000001D C B5光标或字符移位000001S/C R/L**6置功能00001DL N F**7置字符发⽣存贮器地址0001字符发⽣存贮器地址8置数据存贮器地址001显⽰数据存贮器地址9读忙标志或地址01BF计数器地址10要写的数据内容10写数到CGRAM或DDRAM)11读出的数据内容11从CGRAM或DDRAM读数思路:1、控制液晶显⽰输出,需要对其进⾏写数据(写数据前,同样需要先告诉液晶你下⼀步要在哪⾥写,因此写数据前,要写命令先设定数据指针)程序设计⽅式:write_com();//写命令函数,write_date();//写数据函数2、由于要先进⾏初始化,(初始化实际就是对液晶写指令,告诉其⼯作⽅式等)因此初始化函数⾥⾯⾃然就需要调⽤写命令函数write_com();程序结构如下:int init(){ EN = 0; write_com(0X38);//设置16*2显⽰,5*7点阵,8位数据接⼝ write_com(0X0C);//设置开显⽰,不显⽰光标 write_com(0X06);//写⼀个字符时,整屏右移 write_com(0X01);//显⽰清零 return 0;} 主函数部分程序结构:int main(){ init();//调⽤初始化函数 write_com(0x80);//调⽤写指令函数,设置写数据开始指针(第⼀⾏) for(x=0;x<6;x++)//数据写⼊循环程序 { write_date(table[x]); delay(150); } write_com(0x80+0x40); ;//调⽤写指令函数,设置写数据开始指针(第⼆⾏) for(x=0;x<17;x++)//数据写⼊循环程序 { write_date(table1[x]); delay(150); } while(1);return 0;}完整程序如下:1 #include<reg52.h>2int init(); //声明初始化函数3int write_com(unsigned char);//声明写命令函数4int write_date(unsigned char);//声明写数据函数5int delay(unsigned char);//声明延迟函数6 unsigned char x;7 sbit RS = P1^0;8 sbit RW = P1^1;9 sbit EN = P1^2;10 unsigned char code table[]="HELLO!";11 unsigned char code table1[]="MY name is Terry!";1213int main(void)//主函数14 {15 init();16 write_com(0x80);17for(x=0;x<6;x++)18 {19 write_date(table[x]);20 delay(150);21 }22 write_com(0x80+0x40);23for(x=0;x<17;x++)24 {25 write_date(table1[x]);26 delay(150);27 }28while(1);29return0;30 }3132int init()//初始化函数体33 {34 EN = 0;35 write_com(0X38);//设置16*2显⽰,5*7点阵,8位数据接⼝36 write_com(0X0C);//设置开显⽰,不显⽰光标37 write_com(0X06);//写⼀个字符时,整屏右移38 write_com(0X01);//显⽰清零39return0;40 }4142int write_com(unsigned char com)//写命令的函数体43 {44 RS = 0;45 RW = 0;46 P0 = com;47 delay(5);48 EN = 1;49 delay(5);50 EN = 0;51return0;52 }5354int write_date(unsigned char date)//写数据的函数体55 {56 RS = 1;57 RW = 0;58 P0 = date;59 delay(5);60 EN = 1;61 delay(5);62 EN = 0;63return0;64 }6566int delay(unsigned char xms)67 {68 unsigned char x,y;69for(x=xms;x>0;x--)70for(y=110;y>0;y--);71return0;72 }显⽰输出如下:。

单片机控制的lcd1602字符液晶滚动电路功能说明

单片机控制的lcd1602字符液晶滚动电路功能说明

单片机控制的lcd1602字符液晶滚动电路功能说明功能说明:单片机控制的LCD1602字符液晶滚动电路该电路是由单片机控制的LCD1602字符液晶显示屏的滚动功能。

通过单片机的程序控制,可以实现字符的滚动显示,从而达到信息展示的目的。

具体功能说明如下:1. 显示屏控制:该电路使用LCD1602字符液晶显示屏作为显示器,通过单片机的控制,可以控制显示屏上的字符显示。

显示屏具有2行16列的字符显示区域。

2. 滚动显示:通过单片机的程序控制,可以实现字符的滚动显示。

滚动显示可以从左向右或者从右向左进行,可以设置滚动速度和滚动内容。

3. 单片机控制:该电路使用单片机作为控制核心,通过单片机的GPIO口控制显示屏的数据和控制信号。

单片机可以根据用户的需求,通过编程实现不同的滚动效果。

4. 滚动速度调节:用户可以通过调节单片机程序中的延时参数,来控制滚动速度。

延时时间越短,滚动速度越快;延时时间越长,滚动速度越慢。

5. 滚动内容设置:用户可以通过编程将需要滚动显示的内容存储在单片机的内存中,然后通过单片机控制,将内容逐个字符地显示在LCD1602字符液晶显示屏上。

6. 滚动方向选择:用户可以通过编程设置滚动的方向,可以选择从左向右滚动或者从右向左滚动。

7. 硬件连接:该电路需要将单片机的GPIO口与LCD1602字符液晶显示屏的数据和控制信号引脚连接起来,通过连接线进行数据传输和控制。

总结:该电路通过单片机控制LCD1602字符液晶显示屏的滚动功能,可以实现字符的滚动显示,从而达到信息展示的目的。

用户可以通过编程设置滚动速度、滚动内容和滚动方向,灵活控制滚动效果。

这种电路在信息展示、广告宣传等领域有着广泛的应用。

单片机开控制液晶显示器LCD1602

单片机开控制液晶显示器LCD1602

计算机科学与工程系实验报告课程名称:单片机原理与应用实验题目:单片机开控制液晶显示器LCD1602班级:姓名:学号:日期:一、实验目的掌握单片机控制字符型液晶显示器LCD1602的接口设计与软件编程二、实验要求1、用单片机控制字符型液晶显示器LCD1602字符信息“Happy New Year”和“Welcome to Hit”;2、上述信息分别从LCD1602右侧第1行、第2行滚动移入,然后从左侧滚动移出,反复循环显示。

三、实验要求提交的实验报告中应包括:电路原理图、实验设计思路、C51源程序(含注释语句)、运行效果(含运行截图与说明)、实验小结三、硬件电路原理图的设计四、编程思路及C51源程序(1)编程思路:首先 1.LCD初始化2.检查忙标志函数3.写命令函数4.写数据函数5.设置延时函数,然后是主函数调用对LCD初始化函数,插入数据。

(2)C51源程序:#include <reg51.h>#include <intrins.h> //包含_nop_( )空函数指令的头文件#define uchar unsigned char#define uint unsigned int#define out P0sbit RS=P2^0; //位变量sbit RW=P2^1; //位变量sbit E=P2^2; //位变量void lcd_initial(void); //LCD初始化函数void check_busy(void); //检查忙标志函数void write_command(uchar com); //写命令函数void write_data(uchar dat); //写数据函数void delay(uint); //延时函数void main(void) //主函数{uchar tab1[]="Happy New Year";uchar tab2[]="Welcome to HIT";uchar i,j,t;lcd_initial( ); //调用对LCD初始化函数for(t=0;t<29;t++) //实现循环移动{for(i=0;i<14;i++) //循环完成14个字符的字符串{write_command(0x8f+1+i); //指针加1write_data(tab1[i]); //显示对应指针的字符}for(j=0;j<14;j++){write_command(0xcf+1+j);write_data(tab2[j]);}write_command(0x18); //外循环,t循环一次,画面左平移一个字符 delay(200);}}void delay(uint a) //1ms延时子程序{uchar b=250;for(;a>0;a--){while(--b);b=249;while(--b);b=250;}}void check_busy(void) //检查忙标志函数{uchar dt;do{dt=0xff;E=0;RS=0;RW=1;E=1;dt=out;}while(dt&0x80);E=0;}void write_command(uchar com) //写命令函数{check_busy();E=0;RS=0;RW=0;out=com;E=1;_nop_( );E=0;delay(1);}void write_data(uchar dat) //写数据函数{check_busy();E=0;RS=1;RW=0;out=dat;E=1;_nop_();E=0;delay(1);}void LCD_initial(void) //液晶显示器初始化函数{write_command(0x38); //写入命令0x38:16*2显示,5×7点阵字符write_command(0x0C); //写入命令0x0C:开整体显示,光标关,无黑块write_command(0x06); //写入命令0x06:光标右移write_command(0x01); //写入命令0x01:清屏delay(1);}五、仿真运行效果展示六、实验小结通过本次实验,我对LCD1602液晶显示屏有了一个初步的认识,并且在这次实验中,自己对软件的操作更加娴熟,希望自己以后能够把理论知识与实践操作能够紧紧的相结合起来。

DS18B20用LCD1602显示Proteus仿真

DS18B20用LCD1602显示Proteus仿真

/******************************DIY-18B20-LCD1602******************************/#include<pic.h>__CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡#define uchar unsigned char //给unsigned char起别名uchar#define uint unsigned int#define DQ RA4 //定义18B20数据端口#define DQ_DIR TRISA4 //定义18B20D口方向寄存器#define DQ_HIGH() DQ_DIR =1 //设置数据口为输入#define DQ_LOW() DQ = 0; DQ_DIR = 0 //设置数据口为输出unsigned char temp1 = 0 ; //采集到的温度高8位unsigned char temp2 = 0; //采集到的温度低8位unsigned char D[]={"DS18B20 TEMP:"};unsigned char T[10];/*********************函数延时部分********************************/void delayms(uint ms){uchar i;while(ms--){for(i=0;i<87;i++);}}/*延时时间为:(10个固定周期2.5US)+(次数*【1.5US(5+1个周期)】=总延时时间)即就是(10+6N)*T=time */void delay(unsigned char t) //跳入这个循环需要3个指令周期{ //跳出这个循环需要3个指令周期while(t>0) //while第一次判断语句要消耗3个指令周期,之后需要5个t--; //t=t-1,消耗1个指令周期} //也就是说t=0时需要10个指令周期void delay10us(void) //4Mhz下一个指令周期NOP为1Us{NOP();NOP();NOP();NOP();NOP();NOP();}void delay40us(void) //延时42us{delay10us();delay10us();delay10us();delay10us();}/*******************18B20部分********************************/void reset(void){char presence = 1;DQ_HIGH();NOP();NOP();while (presence){DQ_LOW() ; //主机拉至低电平delay(100); //延时610usDQ_HIGH(); //释放总线等电阻拉高总线,并保持15~60usdelay40us(); //延时42usif (DQ == 1) presence = 1; //没有接收到应答信号,继续复位else presence = 0; //接收到应答信号delay(100); //延时610us}}void write_byte(uchar data){uchar i;uchar temp;DQ_HIGH();NOP();NOP();for (i = 8;i > 0;i--){temp = data & 0x01; //最低位移出DQ_LOW();NOP();NOP();NOP();NOP();NOP();//从高拉至低电平,产生写时间隙5usif (temp == 1)DQ_HIGH(); //如果写1,拉高电平delay40us(); //延时42usDQ_HIGH();NOP();NOP();data = data >> 1; //右移一位}}uchar read_byte(void){uchar i;uchar data = 0; //读出温度uchar j;for (i = 8;i > 0;i--){data >>= 1;DQ_HIGH();NOP();NOP();DQ_LOW();NOP();NOP();NOP();NOP();NOP();NOP(); //6usDQ_HIGH(); //拉至高电平NOP();NOP();NOP();NOP();NOP(); //4usj = DQ;if (j)data=data |0x80;delay(10); //延时70us}return (data);}void get_temp(void){float temp,m=0,n=0;unsigned char x;// m=0;// unsigned long temper1;unsigned char temper;unsigned char lsb,msb;reset();write_byte(0xCC);write_byte(0x44);delayms(100);reset();write_byte(0xCC);write_byte(0xBE);temp1=read_byte();temp2=read_byte();lsb=temp1&0x0f; //temp1的低4位为小数部分msb=(temp1>>4)|(temp2<<4);//temp1的高4位和temp2拼成整数部分T[0]=msb/10+0x30;T[1]=msb%10+0x30;T[2]='.';// temp=(temp2*256+temp1)*0.0625*10000;// temper=(unsigned char)temp;// T[0]=temper/100000+0x30;;// T[1]=temper%100000/10000+0x30;// T[2]='.';// T[3]=temper%10000/1000+0x30;// T[4]=temper%1000/100+0x30;// T[5]=temper%100/10+0x30;// T[6]=temper%10+0x30;if(lsb&0x08) m=m+0.5;if(lsb&0x04) m=m+0.25;if(lsb&0x02) m=m+0.125;if(lsb&0x01) m=m+0.0625;n=m*10000;x=(unsigned char)n;T[3]=x/1000+0x30;T[4]=x%1000/100+0x30;T[5]=x%100/10+0x30;T[6]=x%10+0x30;T[7]=0xdf;T[8]=0x43;T[9]='\0';}/******************************LCD1602部分**********************************/ #define rs RC0#define rw RC1#define ep RC2#define LCD PORTDvoid Busy_Check(void) //测试忙碌状态{uchar LCD_Status;rs=0;rw=1;ep=1;NOP();NOP();NOP();NOP();while(1){LCD_Status=PORTD;LCD_Status&=0x80;if(LCD_Status==0);break;}ep=0;}void lcd_wcmd(uchar cmd) //写入指令数据到lcd {Busy_Check();TRISD=0x00;rs=0;rw=0;ep=0;NOP();NOP();LCD=cmd;NOP();NOP();NOP();NOP();ep=1;NOP();NOP();NOP();NOP();ep=0;}void lcd_wdat(uchar dat) //写入字符显示数据到lcd {Busy_Check();TRISD=0x00;rs=1;rw=0;ep=0;LCD=dat;NOP();NOP();NOP();NOP();ep=1;NOP();NOP();NOP();NOP();ep=0;}void lcd_pos(uchar pos) //设定显示位置{lcd_wcmd(pos|0x80); //设定lcd当前光标的位置}void LCD_disp(void){uchar i=0;lcd_pos(0x00);while(D[i]!='\0'){lcd_wdat(D[i]);i++;}lcd_pos(0x40); //设置显示位置为第2行的的二个位置i=0;while(T[i]!='\0'){lcd_wdat(T[i]);i++;}}void lcd_init(void) //lcd初始化设定{lcd_wcmd(0x38);delayms(1);lcd_wcmd(0x0F);delayms(1);lcd_wcmd(0x06);delayms(1);lcd_wcmd(0x01);delayms(1);}/****************************主函数部分***********************************/void main(void){TRISA=0xff; //初始化RA5-RA0的输入输出方向PORTA=0x00; //初始化RA5-RA0数值TRISC=0x00;//初始化对RC口的初始方向进行设置设置为输出TRISD=0x00;//初始化RD口的初始方向进行设置,设置为输出PORTC=0xFF; //初始化RC口的数值PORTD=0x00; //初始化RD口的数值lcd_init();delayms(10);while(1){get_temp();LCD_disp();}}。

《STM32单片机开发—基于Proteus虚拟仿真与HAL-LL》课件5.1--LCD1602的应用

《STM32单片机开发—基于Proteus虚拟仿真与HAL-LL》课件5.1--LCD1602的应用

5.1LCD1602显示器的使用能力能力目标:目标:掌握掌握LCD1602LCD1602显示器的驱动方法,能编写简单的显示器的驱动方法,能编写简单的LCD1602LCD1602驱动程序。

驱动程序。

任务要求:仿真电路如图所示,要求在屏幕第一行显示仿真电路如图所示,要求在屏幕第一行显示“Hello “Hello world!”world!”。

5.1.1液晶显示屏与液晶显示屏与LCD1602LCD1602为了能够显示更加丰富的信息,单片机电路设计中往往会使用到液晶显示屏。

这里我们为大家介绍一种极具性价比的单色液晶显示屏的单色液晶显示屏——LCD1602——LCD1602,如图,如图所示。

这种液晶显示屏能够显示所示。

这种液晶显示屏能够显示22行、1616字符字符//行,共计行,共计3232个个5×7或者或者55×1111的的点阵字符,目前市面上大多数点阵字符,目前市面上大多数LCD1602LCD1602显示屏都是采用了显示屏都是采用了HD44780HD44780液晶显示芯液晶显示芯片,当然无论采用了哪种液晶显示芯片,操作方式大同小异。

(1)LCD1602LCD1602的引脚定义的引脚定义LCD1602LCD1602采用标准的采用标准的1616脚接口,详见表。

脚接口,详见表。

引脚编号功能说明1VSS 接电源负极2VDD 电源正极(+5V/+3.3V)3VEE 液晶显示器对比度调节引脚,电压越接近于VDD则对比度越低,相反电压越接近于VSS(0)则对比度越高。

4RS (Register Select)寄存器选择引脚,高电平时选择数据寄存器,低电平时选择指令寄存器。

5RW (Read /Write)读/写信号引脚,高电平时进行读操作,低电平时进行写操作。

6E (Enable)使能引脚,高电平时读取信息,下降沿时执行指令。

7~14D0~D78位数据总线,D0为最低位,D7为最高位。

15A LCD背光源正极16KLCD背光源负极(2)LCD1602LCD1602的存储器的存储器LCD1602LCD1602内置内置DDRAM (Display Data RAM RAM,显示数据随机存储器),显示数据随机存储器)、CGRAM (Character Generator RAM RAM,字符发生随机存储器),字符发生随机存储器)和CGROM (Character Generator ROM ROM,字符发生只读存储器),字符发生只读存储器)。

加个模块,实现IIC方式驱动LCD1602

加个模块,实现IIC方式驱动LCD1602

加个模块,实现IIC驱动LCD1602 PCF8574模块使实现IIC驱动LCD1602成为现实。

下图是PCF8574模块与1602的连接电路图:实物接法如下:想要使用PCF8574模块来实现IIC驱动LCD1602,首先非常必要弄清楚IIC的时序、PCF8574设备地址、四线控制LCD1602方法。

下面是两个重要的h文件。

通过修改这两个h文件中的部分代码(接线有所不同)即可移植到你的程序中去。

PCF8574.h程序:sbit scl=P1^6;sbit sda=P1^7;void delay()//{ ;; }void init()//IIC初始化{sda=1;delay();scl=1;delay();}void start() //IIC开始信号{sda=1;delay();sda=0;delay();}void stop() //IIC停止{sda=0;delay();scl=1;delay();sda=1;delay();}void respons() //IIC应答{uchar i;scl=1;delay();while((sda==1)&&(i<250))i++;}void write_byte(uchar date)//IIC写入数据{uchar i,temp;temp=date;for(i=0;i<8;i++){temp=temp<<1;scl=0;delay();sda=CY;delay();scl=1;delay();}scl=0;delay();sda=1;uchar read_byte()//IIC读取字节{uchar i,k;scl=0;delay();sda=1;delay();for(i=0;i<8;i++){scl=1;delay();k=(k<<1)|sda;scl=0;delay();}return k;}start();write_byte(0x7e); //8574设备地址(写)respons();write_byte(date1);respons();stop();}uchar read_add()//向IO读取数据{uchar date1;start();write_byte(0x71); //8574设备地址(读)respons();date1=read_byte();respons();stop();return date1;}PCF8574+LCD1602_4.h程序:uchar a,b;for(a=x;a>0;a--)for(b=200;b>0;b--);}void write_com(uchar com) //写命令函数{ uchar com1,com2;com1=com|0x0f;write_add(com1&0xfc);delay1(2);write_add(com1&0xf8);com2=com<<4;com2=com2|0x0f;write_add(com2&0xfc);delay1(2);write_add(com2&0xf8);}void write_date(uchar date) //写数据函数{date1=date|0x0f;write_add(date1&0xfd);delay1(2);write_add(date1&0xf9);date2=date<<4;date2=date2|0x0f;write_add(date2&0xfd);delay1(2);write_add(date2&0xf9);}void init_lcd() //初始化函数{write_com(0x33); //显示模式设置delayms(6);write_com(0x32); //显示模式设置delayms(6);write_com(0x28); //4位总线,双行显示,显示5×7的点阵字符delayms(6);write_com(0x01); //清屏write_com(0x06); //字符进入模式:屏幕不动,字符后移delayms(6);write_com(0x0c); //显示开,关光标//write_LCD_Command(0x0f); //显示开,开光标,光标闪烁delayms(6);}//显示字符串:第x行第y列显示什么内容void ShowString(unsigned char x,unsigned char y,unsigned char *str){//设置起始位置if(x == 1){write_com(0x80 | y-1);// |相当于加法}if(x == 2){write_com(0xc0 | y-1);}//输出字符串while(*str!='\0') {write_date(*str);str++;}}。

1602液晶显示工作原理及其在单片机中的应用(基于Proteus仿真)

1602液晶显示工作原理及其在单片机中的应用(基于Proteus仿真)

1602液晶显示原理及其在单片机中的应用基于Proteus仿真前言:本文详细介绍了1602液晶显示器的工作原理,并在后面举例说明了其在单片机中的应用,所举例子包含Proteus仿真电路图,源程序,程序注释详细清楚。

这有助于更好地理解与掌握1602液晶显示器。

1、1602 LCD基本参数:1602 LCD内置HD44780(目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的)专用液晶显示控制器,分为带背光和不带背光两种,带背光的比不带背光的厚,是否带背光在应用中并无差别。

显示容量为16×2个字符,即可以显示2行,每行16个字符。

芯片工作电压:4.5—5.5V;最佳工作电压为5.0V;工作电流:2.0mA(5.0V电压下);(补充说明:在电子工业中,背光是一种照明的形式,常被用于LCD显示上。

背光式和前光式不同之处在于背光是从侧边或是背后照射,而前光顾名思义则从前方照射。

他们被用来增加在低光源环境中的照明度和电脑显示器、液晶荧幕上的亮度,以和CRT显示类似的方式产生出光。

)2、1602 LCD引脚功能:1602芯片(在proteus中名字为LM016L) 采用标准的14脚(无背光)或16脚(带背光)接口,如右图所示,各引脚功能如下:VSS:电源地VDD:电源正极VEE:液晶显示偏压,为对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

(补充说明:整体回路中的某个点,测量它相对某个基准点的电压(是整体回路电压的1/n)就称之为该点的偏压,各段电路的偏压之和就是整体回路电压,相应位置的电流就是偏压电流。

)RS:数据/命令选择信号,高电平时选择数据寄存器、低电平时选择指令寄存器。

RW(read/write,读/写):读/写控制信号,高电平时进行读操作,低电平时进行写操作。

当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

任务四 LCD1602的仿真

任务四 LCD1602的仿真
83\AT89C51\Debug\Debug.OMF”。
(3)调试。
调试方法如下:
1)单击菜单“Debug”(调试)→“Start VSM Debugging”(开始VSM调试),进入调试状态。
2)如果要想查看某个程序段的执行情况,就可以单击选中此程序段,单击右键添加断点。
选择“Toggle(set/Clear)Breakpoint”(设置/清除断点),则可添加断点。
如果想要使用程序能够进行调试,在编译时需要选择“Debug”模式。方法是单击“Compile”编译图标,选择Debug(调试版),Debug版本只会生成一个临时文件,存在C盘,不会产生*.hex文件。
返回ISIS界面,双击单片机属性,就会发现Debug编译后自动加载的编译文件是一个临时文件,存放路径是“C:\DOCUME`1\SXGY\LOCALS`1\Temp\331ee75b20d74c6b910ee3c866d2c7
在编写程序后,调试程序是程序设计人员检查程序正确与否依据的重要手段。调试程序时,编译文件需要调试Debug文件,在调试代码窗口选择“Debug(调试版)”图标 ,之后再单击编译图标 ,则会生成Debug编译文件,但是不会生成*.Debug文件。
本项目中使用的外部显示设备为LCD1602,调试过程需要观察LCD1602的动态显示过程。所以要把LCD1602进行框定,单击暂停图标,就会出现代码行,右侧则会出现LCD1602显示窗口,如图4-62所示。
{
while(*s>0)
{
write_dat(*s);
s++;
}
}
main()
{
csh();
write_com(0x01);//清屏

基于51单片机的液晶LCD1602显示程序源代码(带LCD1602液晶接口电路))

基于51单片机的液晶LCD1602显示程序源代码(带LCD1602液晶接口电路))

液晶LCD1602显示字符和数字程序源代码/***********************液晶LCD1602测试程序源代码*************************单片机型号:STC15W4K56S4,内部晶振:22.1184M。

功能:液晶LCD1602显示功能测试。

操作说明:液晶LCD1602显示字符和倒计时。

**************************************************************************/#include "stc15.h" //包含头文件stc15.h#include <intrins.h> //包含头文件intrins.h#define Busy 0x80 //LCD忙sbit LCD_D0 = P0^0; //LCD_D0对应P0.0sbit LCD_D1 = P0^1; //LCD_D1对应P0.1sbit LCD_D2 = P0^2; //LCD_D2对应P0.2sbit LCD_D3 = P0^3; //LCD_D3对应P0.3sbit LCD_D4 = P0^4; //LCD_D4对应P0.4sbit LCD_D5 = P0^5; //LCD_D5对应P0.5sbit LCD_D6 = P0^6; //LCD_D6对应P0.6sbit LCD_D7 = P0^7; //LCD_D7对应P0.7sbit LCD_RS = P1^0; //LCD_RS对应P1.0sbit LCD_RW = P1^1; //LCD_RW对应P1.1sbit LCD_EN = P3^4; //LCD_EN对应P3.4void delay(unsigned int t); //delay延时函数void delay_us(unsigned int t); //delay_us延时函数void delay_ms(unsigned int t); //delay_ms延时函数void Delay5Ms(void); //5Ms延时函数void GPIO_1602_Configuration(void); //LCD1602液晶IO口初始化void WriteDataLCD(unsigned char WDLCD); //LCD写数据函数void WriteCommandLCD(unsigned char WCLCD,BuysC); //LCD写命令函数unsigned char ReadDataLCD(void); //LCD读数据函数unsigned char ReadStatusLCD(void); //LCD读状态函数void LCDInit(void); //LCD初始化void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);//LCD显示一个字符void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);//LCD显示一个字符串unsigned char code welcome[] = {"Hello My Friends"};//液晶LCD1602显示Hello My Friendsunsigned char code countdown[] = {"CountDown: S"};//液晶LCD1602显示CountDown: Svoid delay(unsigned int t) //delay延时函数{while(t--);}void delay_us(unsigned int t) //delay_us延时函数{unsigned char i;while(t--){i=3;while(i--)delay(1);}}void delay_ms(unsigned int t) //delay_ms延时函数{while(t--){delay_us(t);}}void Delay5Ms(void) //5ms延时函数{unsigned int TempCyc = 3552;while(TempCyc--);}void GPIO_1602_Configuration(void) //LCD1602液晶IO口初始化{P0M1 = P3M1&0x00;P0M0 = P3M0&0x00;P1M1 = P3M1&0xfc;P1M0 = P3M0&0xfc;P3M1 = P4M1&0xef;P3M0 = P4M0&0xef;}unsigned char ReadStatusLCD(void) //测试LCD忙碌状态{LCD_D7 = 1; //LCD的D7置1LCD_RS = 0; //LCD管脚RS设置成低电平LCD_RW = 1; //LCD管脚RW设置成高电平LCD_EN = 0; //LCD管脚E设置成低电平LCD_EN = 0; //LCD管脚E设置成低电平LCD_EN = 1; //LCD管脚E设置成高电平while(LCD_D7); //检测忙信号return(Busy); //表示当前忙}void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测{if(BuysC) ReadStatusLCD(); //根据需要检测忙LCD_EN = 0; //LCD管脚E设置成低电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_RS = 0; //LCD管脚RS设置成低电平LCD_RW = 0; //LCD管脚RW设置成低电平_nop_(); //空操作,延时_nop_(); //空操作,延时P0 = WCLCD; //将数据送入P0口,即写入指令或地址_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 1; //E置高电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 0;//当E由高电平跳变成低电平时,液晶模块开始执行命令}void WriteDataLCD(unsigned char WDLCD) //LCD写数据函数{ReadStatusLCD(); //读取LCD状态LCD_EN = 0; //LCD管脚E设置成低电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_RS = 1; //LCD管脚RS设置成高电平LCD_RW = 0; //LCD管脚RW设置成低电平P0 = WDLCD;//将数据送入P0口,即将数据写入液晶模块_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 1; //E置高电平_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时_nop_(); //空操作,延时LCD_EN = 0;//当E由高电平跳变成低电平时,液晶模块开始执行命令}void LCDInit(void) //LCD初始化{WriteCommandLCD(0x38,0); //三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCD(0x38,0);Delay5Ms();WriteCommandLCD(0x38,0);Delay5Ms();WriteCommandLCD(0x38,0);WriteCommandLCD(0x08,1); //关闭显示WriteCommandLCD(0x01,1); //显示清屏WriteCommandLCD(0x06,1); //显示光标移动设置WriteCommandLCD(0x0C,1); //显示开及光标设置}void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; //算出指令码WriteCommandLCD(X,0); //这里不检测忙信号,发送地址码WriteDataLCD(DData); //发送数据}void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData){unsigned char ListLength;ListLength = 0;Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1 while (DData[ListLength]>=0x20) //若到达字串尾则退出{if (X <= 0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}void main(void){GPIO_1602_Configuration(); //LCD1602液晶IO口初始化delay_ms(10); //延时LCDInit(); //LCD1602初始化delay_ms(10); //延时DisplayListChar(0,0,welcome); //LCD1602显示Hello My Friends delay_ms(10); //延时DisplayListChar(0,1,countdown); //LCD1602显示CountDown: S delay_ms(10); //延时DisplayOneChar(14,1,0x39); //LCD1602显示9delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x38); //LCD1602显示8delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x37); //LCD1602显示7delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x36); //LCD1602显示6delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x35); //LCD1602显示5delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x34); //LCD1602显示4delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x33); //LCD1602显示3delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x32); //LCD1602显示2delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x31); //LCD1602显示1delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时DisplayOneChar(14,1,0x30); //LCD1602显示0delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200);delay_ms(200); //延时while(1){;}}程序源代码是编译通过并在电路板上测试过参考液晶LCD1602接口电路图该程序的实际运行效果。

基于单片机PIC18F87J11串行通信模块驱动LCD1602的设计与实现

基于单片机PIC18F87J11串行通信模块驱动LCD1602的设计与实现

• 145•LCD1602可以显示2行16列共32个字符。

因其具有体积小、重量轻、功耗低、性价比高等优点,目前在各类电子设备及工业仪表中得到广泛应用。

为驱动LCD1602液晶显示模块,一般情况下需要两个8位的数字I/O 口。

但是通常作为电子设备的核心控制芯片单片机而言,其并行I/O 口硬件资源十分有限。

因此使用单片机的串行通信模块,对外扩充并行I/O 口,并继而实现对LCD1602进行驱动的技术具有十分良好的应用价值。

本文以PIC18F87J11单片机为例,利用PIC18F87J11的串行通信模块MSSP 驱动MCP23S17芯片,对外扩展出两个8位并行I/O 口。

然后利用扩展出的并行I/O 口驱动LCD1602模块,实现16*2共32个字符的液晶显示。

实验结果证明该设计方案是可行的。

1.引言在现实工业应用中,指针式仪表及LED 数码显示管已不能完全满足精确显示的要求,不能充分实现人机完美交互的目的。

小型液晶模块LCD1602因为具有重量轻、体积小、功耗低、能够显示多个字符等优点,所以在大量电子设备及工业应用中得到广泛应用。

对于以单片机为核心的智能仪器而言,单片机不但负责整个系统的信号与信息处理,同时也负责控制液晶显示,用于输出信息以达到理想的人机交互目的(马洪芹,吴锡淳,用单片机控制液晶模块显示:电子科技,2008;邓燕妮,常小科,刘辉琴,等.基于51单片机控制的液晶显示技术:工业控制计算机,2007)。

液晶显示模块LCD1602驱动需要2个外接并行数据I/O 口。

但是单片机任务繁重,并行I/O 口硬件资源十分有限。

因此本文考虑利用单片机的串行通信模块对外扩展并行I/O 口,使之用于驱动液晶显示LCD1602。

文中以单片机PIC18F87J11为例,利用其工作于SPI 模式的串行通信模块MSSP ,扩展2个8位并行I/O 口,并进而驱动LCD1602,实现液晶显示相关字符的目的。

其整体设计框图如图1所示。

MEGA8单片机对LCD1602液晶屏的驱动

MEGA8单片机对LCD1602液晶屏的驱动

MEGA8单片机对LCD1602液晶屏的驱动调试过程总结一下:1)由于找不到的1620资料,不知道它的操作时序。

看到一些帖子说1620和1602没区别,还是有点将信将疑。

后面用网友编写的1602程序试验,才知道它们俩没啥区别2)关于是否检测LCD处于空闲,觉得还是最好在写指令和写数据时都加上。

不检测,会导致显示结果不正常。

3)由于连线很多14根(加上背光就是16根),如果有一根除了问题就会影响到显示。

所以我是用万用表一根线一根线量了之后才通电试验的。

4)看到很多帖子都建议在初始化LCD前延时几十毫秒。

本例中并没有延时,显示也正常。

5)总的说来,不是很难。

在遇到问题时只要能够仔细分析,就能找出原因和解决方法。

自己前几天在试程序时就是显示结果不对,一直在检查自己的程序,没想到原来是单片机的Flash到寿命了那个郁闷啊。

头文件中有五个函数:Function1.unsigned char AskBusy(void)询问LCD1620是否空闲,返回值“1”空闲,“0”为忙;FuncTIon2.WritEDAta(char data)写数据到LCD1620;FuncTIon3.WriteCommand(char command)写指令到LCD1620;FuncTIon4.PutOneCharLCD(x,y,*Disp)在LCD1620上显示一个字符,x,y定义位置FuncTIon5.PutStringLCD(a,b,*DispString)在LCD1620上显示一个字符串,a,b定义初始位置。

Function6.LCD_Init()初始化LCD在使用此头文件之前,必须有以下宏定义:#define DataPortPullup PORTx#define DataPortDirection DDRx#define ReadLCDPINPINx#defineCTRlPortPullup PORTx。

基于51单片机的1602液晶频率计设计(Proteus仿真图和程序)

基于51单片机的1602液晶频率计设计(Proteus仿真图和程序)

基于51单片机的1602液晶频率计设计一、Proteus仿真图:二、程序代码//最大测量65536Hz的频率计//原理:T0定时1S,T1计数#include <REG51.H>#include<INTRINS.H>#define uchar unsigned char#define uint unsigned intuint count=0;uint nm=0;uchar Fw,Fq,Fb,Fs,Fg;#define DataPort P0sbit LCM_RS=P2^0;sbit LCM_RW=P2^1;sbit LCM_EN=P2^2;uchar code str0[]={"-Test frequency-"};uchar code str1[]={"F=00000Hz "};//uchar code str2[]={" "};/*******************************/void delay(unsigned int k){unsigned int i,j;for(i=0;i<k;i++){for(j=0;j<121;j++){;}}}//=================================================///* 函数名:void WaitForEnable(void)作用:检测忙碌信号*///================================================//void WaitForEnable(void){DataPort=0xff;LCM_RS=0;LCM_RW=1;_nop_();LCM_EN=1;_nop_();_nop_();//while(DataPort&0x80);delay(5);LCM_EN=0;}//==========================================================// /* 函数名:void WriteCommandLCM(uchar CMD,uchar Attribc)作用:写命令到LCM *///==========================================================// void WriteCommandLCM(uchar CMD,uchar Attribc){if(Attribc)WaitForEnable();LCM_RS=0;LCM_RW=0;_nop_();DataPort=CMD;_nop_();LCM_EN=1;_nop_();_nop_();LCM_EN=0;}//=========================================================///* 函数名:void WriteDataLCM(uchar dataW)作用:写数据*///=========================================================// void WriteDataLCM(uchar dataW){WaitForEnable();LCM_RS=1;LCM_RW=0;_nop_();DataPort=dataW;_nop_();LCM_EN=1;_nop_();_nop_();LCM_EN=0;}//=========================================================///* 函数名:void InitLcd()作用:LCM初始化*///=========================================================// void InitLcd(){WriteCommandLCM(0x38,1);WriteCommandLCM(0x08,1);WriteCommandLCM(0x01,1);WriteCommandLCM(0x06,1);WriteCommandLCM(0x0c,1);}//=========================================================///*函数名:void DisplayOneChar(uchar X,uchar Y,uchar DData)作用:显示指定坐标的一个字符*///=========================================================// void DisplayOneChar(uchar X,uchar Y,uchar DData){Y&=1;X&=15;if(Y)X|=0x40;X|=0x80;WriteCommandLCM(X,0);WriteDataLCM(DData);}//============================================================// /*函数名:void DisplayListChar(uchar X,uchar Y,uchar code *DData作用:显示指定坐标的一串字符*///============================================================// void DisplayListChar(uchar X,uchar Y,uchar code *DData){uchar ListLength=0;Y&=0x1;X&=0xF;while(X<=15){DisplayOneChar(X,Y,DData[ListLength]);ListLength++;X++;}}//============================================================// /* 函数名:void main(void)作用:主函数*///============================================================////============================================================// /* 函数名:void display()作用:显示函数*///============================================================// void display(){Fw=count/10000+0x30;Fq=count/1000%10+0x30;Fb=count/100%10+0x30;Fs=count/10%10+0x30;Fg=count%10+0x30;DisplayOneChar(2,1,Fw);DisplayOneChar(3,1,Fq);DisplayOneChar(4,1,Fb);DisplayOneChar(5,1,Fs);DisplayOneChar(6,1,Fg);}void InitTime(void){TMOD=0x51;//T0为定时器工作于方式1,T1为计数器工作于方式1TH0=0x4C;//定时器50ms赋高8初值, 12M晶振TL0=0x00;//定时器50ms赋低8初值, 12M晶振TR0=1;//开定时器1TH1=0;//计数器赋高8初值初值TL1=0;//计数器赋低8初值TR1=1;//开计数器0ET0=1;EA=1;}void timeo(void) interrupt 1{TH0=0x4C;//定时器50ms赋高8初值TL0=0x00;//定时器50ms赋低8初值nm=nm+1;if(nm==10){TR1=0; //关闭T1定时器,定时1S完成TR0=0;//关闭T0}}//============================================================// /* 函数名:void main(void)作用:主函数*///============================================================// void main(void){char i;uint temp,temp1;delay(500);InitLcd(); //LCM初始化设置InitTime();for(i=15;i>=0;i--){DisplayListChar(i,0,str0);//显示第一行字符DisplayListChar(i,1,str1);//显示第二行字符delay(100);}while(1){if(nm==10)//定时10*50MS=500ms{temp=TL1;temp1=TH1;count=2*(temp1*256+temp);//定时2乘以500ms=1000ms display();TH1=0;//计数器赋高8初值初值TL1=0;//计数器赋低8初值nm=0;TR1=1;TR0=1;}}}。

基于proteus的51单片机仿真lcd1602

基于proteus的51单片机仿真lcd1602

基于proteus的51单片机仿真实例六十三、字符液晶LCD1602显示单个字符实例1、字符液晶LCD1602显示字符的过程:使用1602型液晶显示字符必须解决三个问题:代县字符ASCII标准妈的产生;液晶显示模式的设置;字符显示位置的指定。

1)字符ASCII标准码产生常用字符的标准ASCII码无需人工产生,在程序中定义字符常量或字符串常量时,C语言在编译后会自动产生其标准ASCII码。

职演讲澄澄的标准ASCII码通过单片机的IO口送入数据线使用存储器(DDRAM),部控制线路就会自动将字符传送到显示器上。

2)液晶显示模式的设置要让液晶显示字符,必须对有无光标、光标的移动方向、光标是否闪烁及字符的移动方向等进行设置。

这样才能获得所需的显示效果。

1602液晶显示模式的设置是通过控制指令对部的控制器进行控制而实现的。

常用的控制指令需要查询液晶的数据手册获得。

3)字符显示位置的指定想要在液晶的某一位置显示特定的字符,则必须指定其显示位置,显示位置的地址需要查询1602型LCD部地址获得。

2、1602型LCD的读写操作LCD是一个慢速显示器件,所以在写每一条指令之前一定要先读取LCD的忙碌状态(当然也可以通过加入一个比较长的延时时间来避开液晶的忙状态,但是这种方法并不合理)。

如果LCD正忙于处理其他指令,就需要等待处理结束;如果不忙,再执行写操作。

为此,1602型液晶专门设了一个忙碌标志位BF,该位位于从1602读取的8位数据的最高位,如果BF为0,表示LCD处于空闲状态,反之则处于忙碌状态。

3、1602液晶显示一个字符的操作过程为:读状态--写指令--写数据--自动显示。

1)读状态要将待显字符写入液晶模块,首先就要检测LCD是否忙碌,只有在LCD处于空闲状态的时候,才能够将待显字符写入2)写指令写指令包括写显示模式控制指令和写入地址。

3)写数据写数据实际上是将待显字符的标准ASCII码写入LCD的数据显示存储器(DDRAM)4)自动显示数据写入液晶模块后,字符产生器(CGROM)将自动读出字符的字形点阵数据,并将字符显示在液晶屏上,这个过程由LCD自动完成,无需人工干预4、1602液晶的初始化过程使用1602液晶显示字符之前,需要对其显示模式进行初始化设置,过程如此下:1)延时15ms,给液晶一段反应时间2)写指令0x38H,尚未开始工作,所以这里不需要检测忙信号,将液晶的显示模式设置为“16*2显示,5*7点阵,8位数据接口”3)延时5ms4)写指令,不需要检测忙信号5)延时5ms6)写指令,不需要检测忙信号7)延时5ms(连续设置3次,确保设置成功)8)以后每次写指令,读/写数据操作都要检测忙信号5、在keil c51中新建工程ex51,编写如下程序代码,编译并生成ex51.hex文件//用LCD显示字符'A'#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚/*****************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delay(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2010年3月第1期 河 北 工 程 技 术 高 等 专 科 学 校 学 报JOU RNAL O F H EBE I EN G I N EER I N G AND T ECHN I CAL COLL EGE M ar .2010N o.1 文章编号:1008-3782(2010)01-0049-03基于单片机虚拟串口驱动L CD 1602的电路仿真郑荣杰1,贾新立1,崔海良1,余云霞2,罗海兵1,张艳敏1(1.河北工程技术高等专科学校电气工程系,河北沧州 061001;2.湘潭大学材料与光电物理学院,湖南湘潭 411105)摘要:基于M ultisi m 10仿真软件,设计单片机的虚拟串口驱动L CD 1602液晶电路。

实现了虚拟串口扩展并行输出的功能。

该设计适用单片机UA R T 串口被占用时,以最少的单片机I O 口驱动L CD 1602,满足显示电路中复杂信息的需求。

与传统的设计手段相比,在M ultisi m 10平台支撑下,设计电路更方便快捷,并可通过仿真结果直接观测和验证设计电路是否达到要求,具有省时、低耗、高效的优越性。

关键词:单片机;电路仿真;M ultisi m 10中图分类号:T P 391.9 文献标识码:A在单片机系统中,显示电路是人机交换信息的平台,其驱动程序的设计具有重要的应用意义。

L CD 1602作为字符型液晶显示模块,具有体积小、功耗低、显示内容丰富等特点,弥补了数码管(L ED )只能显示数字信息的不足,已经成为显示电路中最常用的器件之一[1]。

L CD 1602的驱动方式有并口驱动与串口驱动两种。

并口驱动须占用单片机大量宝贵的I O 接口;串口驱动须在单片机的UA R T 接口空闲的基础上。

本文通过虚拟串口技术实现对L CD 1602的驱动,既不占用UA R T 接口,又节省了单片机的I O 接口资源,可以作为单片机系统中显示复杂信息的一种方法。

1 仿真软件目前,为了降低开发成本,提高开发效率,电子电路的设计工作都是通过仿真软件实现。

单片机仿真主要以P ro teu s 和Keil 软件为主,通过两者配合进行程序和硬件电路的联调。

由于涉及到两个软件的联调,使得电路设计工作比较复杂。

在N I 公司发布的电路分析软件最新版本——M u ltisi m 10中,这个问题得到了圆满的解决[2]。

在此版本中,添加的M CU 模块将单片机系统仿真过程中程序编译、测试及电路设计、仿真完美的结合在一起。

本文正是以M u ltisi m 10为平台,设计了基于单片机的虚拟串口驱动L CD 1602的电路。

通过仿真测试,电路的设计合理有效,直观简洁。

2 电路的设计图1 L CD 1602显示电路的原理图 硬件电路如图1所示。

其中单片机80C 51的P 0.5与P 0.7设计为虚拟串口的数据线和时钟线。

P 0.0,P 0.1以及P 0.2用来控制L CD 1602的读写信号线、寄存器选择线与使能端。

L CD 1602的CV 引脚为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高。

使用时,可以通过一个电位器调整对比度。

R S 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

RW 为读写信号线,高电平时进行读操作,低电平时进行写操作。

E 为使能端。

收稿日期:2010201212作者简介:郑荣杰(19802),男,河北沧州人,硕士,河北工程技术高等专科学校实验员。

D 0~D 7为8位双向数据线,输入的数据可以作为数据显示在液晶屏幕,或作为命令对L CD 1602的寄存器和屏幕进行各种操作。

其功能表如表1。

表1 L CD 1602中寄存器的功能表E 为使能端R S 为寄存器选择RW 为读写信号线工作状态 -↑- 00写入指令Ε01读忙信号-↓-10写入数据 74L S 164为8位串入并出移位寄存器,其引脚功能如下:Q 0~Q 7为并行输出端;A 、B 为串行输入端;CR 端为清零端,低电平有效;CL K 为时钟脉冲数输入端,在上升沿脉冲作用下实现移位。

在CL K =0且CR =1时,74L S 164保持原来的数据状态。

3 模拟仿真在M u ltisi m 10工作平台下,按照原理图创建实际电路,具体步骤及说明如下:图2 L CD 1602显示电路的仿真结果1)从M CU M odu le 元件库805X系列中调用单片机80C 51。

将单片机放入电路图中,根据出现的M CU 向导,分别输入工作区路径和工作区名称。

2)从A dvanced Peri pherals 元件库L CD s 系列中调用液晶L CD 1602;从T TL 元件库74L S 系列中调用74L S 164,并将L CD 1602的输出端与74L S 164的输入端相连接。

3)单片机的P 0.0,P 0.1,P 0.2引脚分别与L CD 1602的引脚E ,R S ,RW 相连接。

从B asic 元件库R PA CK系列中选择1X 4S IP 排阻,并将1X 4S IP 作为上拉电阻。

4)将单片机与其他器件的其他引脚正确连接,并接通电源。

完成电路的准备工作后,编写单片机虚拟串口驱动程序。

激活电路进行仿真,可以选择在菜单中执行“Si m u late ” “R un ”命令;或将窗口上的仿真启动开关拨向右边或单击仿真启动图标。

仿真结果如图2。

单片机的P 0.5引脚作为虚拟串行数据发送端,将数据经过74L S 164转换传输到L CD 1602,分别在液晶的上下两行显示。

显然,通过虚拟串口与74L S 164的共同作用,L CD 1602控制总线与数据线完全可以通过一组P 0接口来控制。

这不仅节约了单片机宝贵的I O 口资源,更解决了单片机串口输出信息时对UA R T 口的依赖问题[3]。

4 参考程序主程序流程图如图3所示。

本程序基于M CS 251系列单片机汇编语言编制而成,L CD 1602的虚拟串口驱动程序编写在子程序中。

在液晶屏上显示的信息分别置于TAB 1与TAB 2表中,如:TAB 1:db 20H ,20H ,20H ,′W elcom e to ′,00H ;TAB 2:db ′www .hbgz .edu .cn ′,00H ;其中,“20H ”代表的是在L CD 1602上输入空格;“00H ”作为信息结束的标志。

虚拟串口输出数据时,先将数据输入累加器A ,然后通过子程序W R IT ECY 中带进位左环移指令RL C 实现输出数据。

具体程序如下:05河 北 工 程 技 术 高 等 专 科 学 校 学 报 2010 图3 主程序的流程图 ……AB 1EQU P 0.5; 设置AB 1对应P 0.5CL K EQU P 0.5;设置CL K 对应P 0.7……W R IT ECY :;输出字符子程序 M OV R 4,#8H ;代表输出的位数 LOO PW Y :将8位数据从低位依次输出 RL C A ;带进位循环右移 M OV AB 1,C ;将进位中的数据输出到P 0.5引脚 A CALL CL KCLOCK ;在CL K 引脚上加脉冲 DJN Z R 4,LOO PW Y ; A CALL D ELA YL ;调用延时子程序R ET ;……显然,通过W R IT ECY 子程序,使得单片机的P 0.5与P 0.7引脚具有了串口在方式0的状态下输出数据的功能。

参 考 文 献[1] 赵亮.液晶显示模块L CD 1602应用[J ].电子制作,2007,(3):58259.[2] 吴霞.M ultisi m 2001电路仿真软件在计数器中的分析方法[J ].现代电子技术,2007,(24):1772178.[3] 孙士尉.利用单片机虚拟串口驱动多路L ED 显示[J ],江苏电器,2006,(1):28230.Si m ula tion of LCD 1602D isplay D r ived by Si ngle Ch ipM icrocom puter F ictious Ser i a l PortZH EN G Rong 2jie 1,J I A X in 2li 1,CU I H ai 2liang 1,YU Yun 2x ia 2,LU O H ai 2b ing 1,ZHAN G Yan 2m in1(1.D epartm ent of E lectrical Engineering ,H ebei Engineering and T echnical Co llege ,Cangzhou 061001,Ch ina ;2.Co llege of M aterial Science and Op tical Physics ,X iangtan U niversity ,X iangtan 411105,Ch ina )Abstract :U sing M u ltisi m 10si m u lati on softw are ,w e design a disp lay based on L CD 1602drived by fic 2titi ou s serial po rt of single ch i p m icrocom pu ter .It is realized that the ou tpu t in parallel is rep laced by fic 2ti ou s serial po rt .It can be app lied in driving L CD 1602by the least I O of single ch i p m icrocom p u ter to show com p lex info r m ati on ,as the UA R T serial po rt is occup ied .B ased on M u ltisi m 10,it is easier in de 2sign ing the circu it than by the traditi onal m ethods ,and the circu it can be si m u lated directly on com pu ter to test its p roperties ,w h ich has the advan tages of ti m e saving ,low co st ,and h igh efficiency .Key words :M CU ;circu it si m u lati on ;M u ltisi m 10(责任编辑:路文梅)15 第1期 郑荣杰等:基于单片机虚拟串口驱动L CD 1602的电路仿真。

相关文档
最新文档