单片机技术与项目训练 课件 第7章 液晶显示接口设计_第1页
单片机技术与项目训练 课件 第7章 液晶显示接口设计_第2页
单片机技术与项目训练 课件 第7章 液晶显示接口设计_第3页
单片机技术与项目训练 课件 第7章 液晶显示接口设计_第4页
单片机技术与项目训练 课件 第7章 液晶显示接口设计_第5页
已阅读5页,还剩86页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

液晶显示接口设计第7章液晶显示屏以其功耗低、体积小、显示内容丰富、超薄轻巧的诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。液晶显示屏的种类繁多,本章介绍常用的字符型液晶显示模块SMC1602、图形液晶显示模块OCM12864。引言目录SMC1602的基础应用1SMC1602温度快速显示和忙状态判断2OCM12864使用基础4SMC1602汉字显示与4位数据总线3OCM12864温度显示5行业PPT模板/hangye/本章小结6本章习题77.1SMC1602的基础应用7.1.1SMC1602概述7.1.1SMC1602概述每个字符都有一个固定的代码。例如,大写字母A的代码是01000001B(41H),显示时把地址41H中的字模显示出来,我们就能看到字母A。SMC1602内部的CGRAM能存储8个自定义字符,在SMC1602初始化时,向CGRAM写入字模,写入地址为0x00~0x07(共8个地址)。7.1.2SMC1602与单片机的接口7.1.2SMC1602与单片机的接口SMC1602读操作时序如图7-7所示。当R/W和E引脚均为高电平时,通过从E引脚信号算起的时间tD,即可从SMC1602数据口读出指令或数据。7.1.2SMC1602与单片机的接口SMC1602写操作时序如图7-8所示。当R/W引脚为低电平、E引脚为高电平时,在从E引脚信号算起的时间tPW内,都可将指令或数据向SMC1602的数据口写入。7.1.3SMC1602内部寄存器介绍DDRAM地址映射图如图7-9所示。SMC1602共有2行,每行有16个字符。例如,地址00表示第1行第1个字符的位置,如果要在这个位置显示某个字符,则只要送出地址00和这个字符的ASCII码即可。7.1.3SMC1602内部寄存器介绍SMC1602内部的控制器共有11条控制指令,如表7-4所示。它的读/写操作、屏幕和光标的操作都是通过指令编程来实现的。7.1.4SMC1602基础应用仿真利用前面学到的理论知识设计一个SMC1602的显示电路,编写驱动程序,显示一些简单的字符。7.1.4SMC1602基础应用仿真/**********************************************************************函数功能:写指令到LCD指令寄存器**********************************************************************/voidLcd_WriteCmd(void){LCD_RS=0; //选择LCD指令寄存器LCD_RW=0; //执行写入操作LCD_E=1; //使能LCDDelay_1mS(50);//见"时序参数表"中"E脉宽tpw"要求≥150nSLCD_E=0;Delay_1mS(50);//而"E周期tc"要求≥400nS}7.1.4SMC1602基础应用仿真/**********************************************************************函数功能:写数据到LCD数据寄存器,指针ch指向数据的首地址,n为数据个数**********************************************************************/voidLcd_WriteData(uchar*ch,ucharn){uchari;

for(i=0;i<n;i++){P2=*(ch+i); //送字符数据

LCD_RS=1; //选择LCD数据寄存器LCD_RW=0; //使能写入操作LCD_E=1; //启动LCDDelay_1mS(50);//见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_1mS(50);//而"E周期tc"要求>400nS}}7.1.4SMC1602基础应用仿真/**********************************************************************函数功能:LCD初始化**********************************************************************/voidLcd_Init(void){P2=0x01;//指令1:清屏指令Lcd_WriteCmd();

P2=0x38;//指令6:功能设定指令,8位,2行,5*7点矩阵Lcd_WriteCmd();

P2=0x0F;//指令4:开显示指令,显示屏ON,光标ON,闪烁ONLcd_WriteCmd();

P2=0x06;//指令3:设置字符&光标移动模式,光标右移,整屏显示不移动Lcd_WriteCmd();}7.1.4SMC1602基础应用仿真/**********************************************************************函数功能:主函数,在指定的位置显示指定的字符串**********************************************************************/voidmain(void){while(1){Lcd_Init(); //LCD初始化

P2=0x80; //指令8:DDRAM第1行起始地址Lcd_WriteCmd();Lcd_WriteData(Line1,16);//写入第1行16个字符

P2=0xC0; //指令8:DDRAM第2行起始地址Lcd_WriteCmd();Lcd_WriteData(Line2,16);//写入第2行16个字符P2=0xCF; //指令8:光标停留在第2行最后一个字符的位置Lcd_WriteCmd();

Delay_1mS(3000);//在当前显示处停留3S}}7.1.5SMC1602温度显示的仿真在SMC1602基础应用仿真任务的基础上修改驱动程序,不仅要显示字符,还要显示数值,如温度值。7.1.5SMC1602温度显示的仿真/**********************************************************************函数功能:将数值转换成字符串**********************************************************************/voidValue2Ascii(ucharval,uchar*valAscii){valAscii[0]=val/10+'0';valAscii[1]=val%10+'0';}这里主要增加了Value2Ascii()函数,将温度变量temp转换成字符串tempAscii[],并显示温度字符串。7.1.5SMC1602温度显示的仿真/**********************************************************************函数功能:主函数,在指定的位置显示指定的字符串**********************************************************************/Lcd_Init();//LCD初始化P2=0x80;//指令8:DDRAM第1行起始地址Lcd_WriteCmd();Lcd_WriteData(Line1,16);//写入第1行16个字符P2=0xC0;//指令8:DDRAM第2行起始地址Lcd_WriteCmd();Lcd_WriteData(Line2,13);//写入第2行13个字符Value2Ascii(temp,tempAscii);//将温度变量转换成字符串Lcd_WriteData(tempAscii,2);//显示温度字符串P2=0xCF;//指令8:光标停留在第2行最后一个字符位置Lcd_WriteCmd();Delay_1mS(3000);//在当前显示处停留3s7.2SMC1602温度快速显示和忙状态判断7.2.1任务要求在SMC1602温度显示的仿真任务的基础上修改驱动程序,要求每个字符的显示没有延时,快速显示所有字符。7.2.2任务分析在SMC1602温度显示的仿真任务中,Lcd_WriteCmd()和Lcd_WriteData()函数都用到了延时函数Delay_1mS(50)。在第5章曾介绍过,软件的延时是阻塞式延时,会影响程序的执行速度,特别是毫秒级的延时。因此,本任务通过减少延时时间,采用微秒级延时,或者判断SMC1602忙状态来实现快速显示所有字符。7.2.3原理图设计原理图设计的参考图不变,显示效果如图7-11所示。7.2.4SMC1620温度快速显示的程序设计1.增加延时函数Delay_100uS()增加一个延时100μs的延时函数Delay_100uS(),并在main()函数中调用Delay_100uS(1),修改j的初值,就可以调整Delay_100uS()函数的延时时间。voidDelay_100uS(uintt){uinti,j;

for(i=t;i>0;i--){for(j=10;j>0;j--);}}7.2.4SMC1620温度快速显示的程序设计2.调试Delay_100uS()函数中的参数在Keil中可以查看Delay_100uS()函数的延时时间,如果延时时间不够准确,与100μs相差较大,则可以修改j的初值。单击“Debug”按钮,进入调试状态,同时显示Disassembly汇编代码窗口,如图7-12所示。如果修改了程序,则必须先编译(快捷键F7),再单击“Debug”按钮。7.2.4SMC1620温度快速显示的程序设计如图7-13所示,切换回Main.c汇编代码窗口,箭头所指位置表示将要执行的语句,灰色块表示对应行为可以执行语句(若无灰色块,则表示该行语句不可执行)。7.2.4SMC1620温度快速显示的程序设计(1)增加两个断点。在Delay_100uS(1)所在行任意处双击,增加第一个断点(圆点),在下一个灰色块,即Lcd_Init()所在行任意处双击,增加第二个断点,如图7-14所示。7.2.4SMC1620温度快速显示的程序设计在Keil的菜单栏中选择“View”→“AnalysisWindows”→“PerformanceAnalyzerWindow”选项,打开执行时间分析窗口,其中“totaltime”数值框中的值表示程序已经运行的时间(单位为s),这里为0,表示程序还未运行,如图7-15所示。7.2.4SMC1620温度快速显示的程序设计(2)程序运行到第一个断点处。单击“Run”按钮,程序运行到第一个断点处,如图7-16所示。7.2.4SMC1620温度快速显示的程序设计查看执行时间分析窗口,此时程序运行了0.000391s,如图7-17所示。7.2.4SMC1620温度快速显示的程序设计(3)程序运行到第二个断点处。单击“Run”按钮,程序运行到第一个断点处,如图7-18所示。这里也可以使用“StepOver”单步按钮使程序运行到第二个断点处。7.2.4SMC1620温度快速显示的程序设计查看执行时间分析窗口,此时,程序运行了0.000497s(见图7-19),计算得0.000497s-0.000391s=106μs,表示执行Delay_100uS(1)函数使用了106μs,符合任务要求。7.2.4SMC1620温度快速显示的程序设计3.改写Lcd_WriteCmd()、Lcd_WriteData()函数将程序中的Delay_1mS(50)改为Delay_100uS(9),尽量减少操作LCD所需的时间,即可达到快速显示所有字符的要求。/**********************************************************************函数功能:写指令到LCD指令寄存器**********************************************************************/voidLcd_WriteCmd(void){LCD_RS=0; //选择LCD指令寄存器LCD_RW=0; //执行写入操作LCD_E=1; //使能LCDDelay_100uS(9); //见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(9); //而"E周期tc"要求>400nS}7.2.4SMC1620温度快速显示的程序设计/**********************************************************************函数功能:写数据到LCD数据寄存器,指针ch指向数据的首地址,n为数据个数**********************************************************************/voidLcd_WriteData(uchar*ch,ucharn){uchari;

for(i=0;i<n;i++){P2=*(ch+i); //送字符数据

LCD_RS=1; //选择LCD数据寄存器LCD_RW=0; //使能写入操作LCD_E=1; //启动LCDDelay_100uS(9); //见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(9); //而"E周期tc"要求>400nS}}7.2.5SMC1602忙状态判断1.使用STC-ISP生成Delay_100uS()函数可以使用STC-ISP直接生成Delay_100uS()函数,在“8051指令集”下拉列表中选择“STC-Y1”选项即可,如图7-20所示。7.2.5SMC1602忙状态判断2.忙等待异常将SMC1602温度快速显示源码中的Delay_100uS(9)改为Delay_100uS(8)。此时,SMC1602第2行不能显示,Proteus日志窗口提示“Controllerreceivedcommand

whilstbusy.”(LCD1接收命令时正忙)(单击“Message”按钮可显示),如图7-21所示,说明Delay_100uS(8)这个延时时间太短,即单片机在向SMC1602发送指令或数据时,SMC1602正忙。7.2.5SMC1602忙状态判断3.忙状态的读取voidLcd_BusyWait(void){uchari=0;//LCD_BUSY=1; P2=0xFF; //读取1602的状态时,1602会输出一个字节LCD_RS=0;LCD_RW=1;LCD_E=1;while(LCD_BUSY==1);//忙否:1602模块坏了或被拔下,将在此死循环/*while(i++<255){if(LCD_BUSY==0)break;//忙否:推荐这种写法}//while*/LCD_E=0;}7.2.5SMC1602忙状态判断上述程序说明:在读取SMC1602忙状态时,SMC1602会输出一个字节,只要通过最高位P2.7来判断SMC1602忙否即可。单片机在读引脚前先将引脚置1,只有这样,读取的数据才正确。但如果只将P2.7引脚置1,即LCD_BUSY=1,那么Proteus日志窗口会提示A8等引脚逻辑电平冲突,如图7-22所示。此时,需要将LCD_BUSY=1改为P2=0xFF,以接收SMC1602一字节的状态字。7.2.5SMC1602忙状态判断4.改写Lcd_WriteCmd和Lcd_WriteData()函数在前面调用忙等待函数Lcd_BusyWait(),表示在每次写指令、读/写数据之前检测忙状态信号,并将Delay_100uS(9)改为最小的Delay_100uS(1)。voidLcd_WriteCmd(ucharcmd){Lcd_BusyWait();//忙等待

P2=cmd;

LCD_RS=0;//选择LCD指令寄存器LCD_RW=0;//执行写入操作LCD_E=1;//使能LCDDelay_100uS(1);//见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1);//而"E周期tc"要求>400nS}7.2.5SMC1602忙状态判断5.改写main()和Lcd_Init()函数voidmain(void){

while(1){Lcd_WriteCmd(0x80);//指令8:DDRAM第1行起始地址Lcd_WriteData(Line1,16);//写入第1行16个字符

Lcd_WriteCmd(0xC0);//指令8:DDRAM第2行起始地址Lcd_WriteData(Line2,13);//写入第2行13个字符Value2Ascii(temp,tempAscii);//将温度变量转换成字符串Lcd_WriteData(tempAscii,2);//显示温度字符串

Lcd_WriteCmd(0xCF);//指令8:光标停留在第2行最后一个字符的位置Delay_1mS(3000);//在当前显示处停留3S}}7.2.5SMC1602忙状态判断上述程序在Lcd_Init()函数中调用了Lcd_WriteCmd_NoChk()函数,该函数较Lcd_WriteCmd()函数只少了忙等待函数Lcd_BusyWait(),因为上电后,SMC1602默认为忙状态,所以需要向SMC1602中写入一个指令并等待一小段时间,只有这样,SMC1602才会变成空闲状态。/**********************************************************************函数功能:LCD初始化**********************************************************************/voidLcd_Init(void){Lcd_WriteCmd_NoChk(0x01);//指令1:清屏指令Delay_1mS(2);Lcd_WriteCmd(0x38);//指令6:功能设定指令,8位,2行,5*7点矩阵Lcd_WriteCmd(0x0F);//指令4:开显示指令,显示屏ON,光标ON,闪烁ONLcd_WriteCmd(0x06);//指令3:设置字符&光标移动模式,光标右移,整屏显示不移动}7.2.5SMC1602忙状态判断/**********************************************************************函数功能:写指令到LCD指令寄存器**********************************************************************/voidLcd_WriteCmd_NoChk(ucharcmd){P2=cmd;

LCD_RS=0; //选择LCD指令寄存器LCD_RW=0; //执行写入操作LCD_E=1; //使能LCDDelay_100uS(1);//见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1);//而"E周期tc"要求>400nS}7.3SMC1602汉字显示与4位数据总线7.3.1SMC1602汉字显示1.任务要求在SMC1602忙状态判断任务的基础上修改驱动程序,要求第1行显示一些简单常用的汉字,如年月日时分秒;第2行显示的温度值后面带符号“℃”。2.原理图设计原理图设计的参考图不变,显示效果如图7-23所示。7.3.1SMC1602汉字显示3.汉字显示的原理前面已经介绍过CGRAM的相关知识,这里不再赘述。CGRAM中第一个字符的存储空间如图7-24所示。需要注意的是,由于CGROM地址中包含了CGRAM地址(高4位为0000的地址),在设置CGROM地址的指令中,命令字节D6的值为1。因此,在写命令到CGRAM中时,写入值为0x40~0x47,对应的CGRAM地址为0x00~0x07。7.3.1SMC1602汉字显示在取模软件PCtoLCD中选择“模式”→“图形模式”选项,如图7-25所示。新建点阵大小为8×8,如图7-26所示。7.3.1SMC1602汉字显示单击选出“℃”的形状,如图7-27所示。打开“字模选项”对话框,具体设置如图7-28所示。设置好后单击“生成字模”按钮,得到“℃”的字模{0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00},如图7-29所示。7.3.1SMC1602汉字显示其余6个汉字“年月日时分秒”的形状如下图7-30所示,制作字模的过程与符号℃类似。7.3.1SMC1602汉字显示4.汉字的写入将7个自定义字符生成的字模保存到一维数组g_ucFont[]中,该数组位于51单片机的ROM空间。/**********************************************************************1602要显示7个自定义字符,其字模由取模软件生成有6个汉字和1个℃,分别为年月日,时分秒,℃**********************************************************************/ucharcodeg_ucFont[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02,

0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00,

0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F,0x00,

0x02,0x1F,0x1A,0x1E,0x1A,0x12,0x04,0x00,

0x04,0x0A,0x11,0x0E,0x06,0x1A,0x04,0x00,

0x0A,0x12,0x0F,0x1C,0x09,0x1A,0x0C,0x00,

0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00,

};7.3.1SMC1602汉字显示在SMC1602初始化Lcd_Init()函数中,将7个自定义字符的字模写入CGRAM。/**********************************************************************函数功能:LCD初始化**********************************************************************/voidLcd_Init(void){Lcd_WriteCmd_NoChk(0x01);//指令1:清屏指令Delay_1mS(2);Lcd_WriteCmd(0x38);//指令6:功能设定指令,8位,2行,5*7点矩阵Lcd_WriteCmd(0x0F);//指令4:开显示指令,显示屏ON,光标ON,闪烁ONLcd_WriteCmd(0x06);//指令3:设置字符&光标移动模式,光标右移,整屏显示不移动Lcd_WriteCmd(0x40);//指令7:CGRAM的开始地址Lcd_WriteData(g_ucFont,8*7);//将7个自定义字符的字模写入CGRAM}7.3.1SMC1602汉字显示5.汉字的显示在主函数main()中,在显示温度字符串后紧接着显示符号“℃”。数组UserChar[]中保存着这7个自定义字符在DDRAM中的值,分别为0~6。为了显示汉字,Line2[]数组的内容改为:voidmain(void){uchartemp=28;//温度变量uchartempAscii[2];ucharUserChar[]={0,1,2,3,4,5,6};//7个自定义字符在数据存贮器DDRAM中的值

//Delay_100uS(1); //调试Delay_100uS()函数中的参数

Lcd_Init();//LCD初始化函数只需执行一次,将其放到while(1)循环外面7.3.1SMC1602汉字显示

while(1){

Lcd_WriteCmd(0x80);

//指令8:DDRAM第1行起始地址

Lcd_WriteData(Line1,16);

//写入第1行16个字符

Lcd_WriteCmd(0xC0);

//指令8:DDRAM第2行起始地址

Lcd_WriteData(Line2,13);

//写入第2行13个字符

Lcd_WriteCmd(0xC0+4);

Lcd_WriteData(&UserChar[0],1);

//年在DDRAM中的值为0

Lcd_WriteCmd(0xC0+7);

Lcd_WriteData(&UserChar[1],1);

//月在DDRAM中的值为1

Lcd_WriteCmd(0xC0+10);

Lcd_WriteData(&UserChar[2],1);

//日在DDRAM中的值为2

Value2Ascii(temp,tempAscii);

//将温度变量转换成字符串

Lcd_WriteCmd(0xC0+13);

Lcd_WriteData(tempAscii,2);

//显示温度字符串

Lcd_WriteData(&UserChar[6],1);

//℃在DDRAM中的值为6

Lcd_WriteCmd(0xCF);

//指令8:光标停留在第2行最后一个字符的位置

Delay_1mS(3000);

//在当前显示处停留3s

}}7.3.2SMC16024位数据总线5.汉字的显示1.4位数据总线的原理当单片机引脚不够用时,SMC1602采用四线接法,可以多留出4个端口,以备单片机连接其他外围电路。四线接法把DB3~DB0(仿真软件中的D3~D0)引脚悬空不接,其他引脚的接法与八线接法一样,显示效果如图7-31所示。7.3.2SMC16024位数据总线2.改写Lcd_WriteCmd_NoChk()、Lcd_WriteCmd()、Lcd_WriteData()函数四线数据传输只需通过DB4~DB7引脚,其程序与八线接法大同小异,只需在写指令或数据时,先传输相应的高4位,再传输低4位即可。7.3.2SMC16024位数据总线/**********************************************************************函数功能:写指令到LCD指令寄存器**********************************************************************/voidLcd_WriteCmd_NoChk(ucharcmd){LCD_RS=0; //选择LCD指令寄存器LCD_RW=0; //执行写入操作

P2=cmd; //先写高4位给P2口高4位LCD_E=1; //使能LCDDelay_100uS(1); //见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1); //而"E周期tc"要求>400nS

P2=cmd<<4;//再写低4位给P2口高4位LCD_E=1; //使能LCDDelay_100uS(1);//见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1);//而"E周期tc"要求>400nS}7.3.2SMC16024位数据总线/**********************************************************************函数功能:写指令到LCD指令寄存器(不使用忙等待)**********************************************************************/voidLcd_WriteCmd(ucharcmd){//Lcd_BusyWait();//使用4位数据总线时不能再使用忙等待函数LCD_RS=0; //选择LCD指令寄存器LCD_RW=0; //执行写入操作P2=cmd; //先写高4位给P2口高4位LCD_E=1; //使能LCDDelay_100uS(1); //见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1);//而"E周期tc"要求>400nS

P2=cmd<<4;//再写低4位给P2口高4位LCD_E=1; //使能LCDDelay_100uS(1);//见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1);//而"E周期tc"要求>400nS}7.3.2SMC16024位数据总线voidLcd_WriteData(uchar*ch,ucharn){uchari;for(i=0;i<n;i++){//Lcd_BusyWait();//忙等待,在4位数据总线不能再使用忙等待函数LCD_RS=1; //选择LCD数据寄存器LCD_RW=0; //使能写入操作P2=*(ch+i); //先写高4位给P2口高4位LCD_E=1; //启动LCDDelay_100uS(1); //见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1); //而"E周期tc"要求>400nS

P2=(*(ch+i))<<4;//再写低4位给P2口高4位LCD_E=1; //启动LCDDelay_100uS(1); //见"时序参数表"中"E脉宽tpw"要求>150nSLCD_E=0;Delay_100uS(1); //而"E周期tc"要求>400nS}}7.3.2SMC16024位数据总线voidLcd_Init(void){Lcd_WriteCmd_NoChk(0x32);//指令6:经试用,0x30~0x3F中只有0x32才能正常显示,还可使用0x02,0x12Delay_1mS(2); //该延时可去掉,上一语句改为Lcd_WriteCmd(0x32)Lcd_WriteCmd(0x28);//指令6:功能设定指令,4位,2行,5*7点矩阵Lcd_WriteCmd(0x0F);//指令4:开显示指令,显示屏ON,光标ON,闪烁ONLcd_WriteCmd(0x06);//指令3:设置字符&光标移动模式,光标右移,整屏显示不移动Lcd_WriteCmd(0x40);//指令7:CGRAM的地址Lcd_WriteData(g_ucFont,8*7);//将7个自定义字符的字模写入CGRAM}3.改写Lcd_Init()函数将Lcd_WriteCmd(0x38)改为Lcd_WriteCmd(0x28),将SMC1602设为4位数据总线,并在这条语句前面增加Lcd_WriteCmd_NoChk(0x32)。需要注意的是,这个说明在SMC1602的数据手册中并没有提到。7.4OCM12864使用基础7.4.1OCM12864概述7.4.2OCM12864与单片机的接口OCM12864采用模拟端口线连接方式,如图7-33所示。7.4.2OCM12864与单片机的接口OCM12864读操作时序如图7-34所示。其中,当R/W引脚为高电平、E引脚为高电平时,通过从E引脚信号算起的时间tr,即可从OCM12864数据口读出指令或数据。7.4.2OCM12864与单片机的接口OCM12864写操作时序如图7-35所示。其中,当R/W引脚为低电平、E引脚为高电平时,在从E引脚信号算起的时间PWEH内,都可将指令或数据向OCM12864的数据口写入。7.4.3OCM12864的控制指令OCM12864控制指令相对于SMC1602要简单,其主要指令及引脚数据设置如表7-9所示。7.4.4OCM12864的基础显示1.任务要求利用前面学到的理论知识设计一个OCM12864的显示电路,编写驱动程序,显示一些简单的字符,包括中文、英文、数字、符号等。2.原理图设计原理图设计参考图7-36。7.4.4OCM12864的基础显示3.汉字、英文的字模可以使用取模软件PCtoLCD来取字模,执行“模式”→“字符模式”命令,进入字符模式,如图7-37所示。7.4.4OCM12864的基础显示3.汉字、英文的字模取模方式为“列行式”、取模走向为“逆向(低位在前)”,勾选“自定义格式”复选框,具体设置如图7-38所示。默认选中“阴码”单选按钮,即点亮用“1”表示。而显示屏上的“中文反显显示效果”和“EngReverseDisp”是反显效果,应选中“阳码”单选按钮。7.4.4OCM12864的基础显示OCM12864液晶屏共有128列,分为左区、右区,每一区都有64列。7.4.4OCM12864的基础显示4.图片的模如果要取图片的模,则执行“文件”→“打开”命令,如图7-39所示。先选择bmp图片,该图片应为黑白图片,大小应为128×64(单位为像素)。它的字模选项设置与汉字、英文的字模一样,最终也是单击“生成字模”按钮。7.4.4OCM12864的基础显示5.汉字、英文显示的流程图为了便于理解汉字、英文显示的原理,画出其流程图,如图7-40所示。这里总共要显示4行汉字、英文。其中,汉字为16×16点阵,英文为16×8点阵,因为一页的宽度为8位,所以每个汉字或英文都要占用两页,分别对应汉字、英文的上半部分和下半部分。当显示完汉字上半部分的16字节后,就要显示汉字下半部分的16字节,而英文的上半部分、下半部分都为8字节。当显示完上半部分后,就要定位到OCM12864的下一页来显示下半部分,这是在Lcd_DisOneRow()函数中调用Lcd_SetPageCol()函数来实现的,具体见例程源码。7.4.4OCM12864的基础显示7.4.4OCM12864的基础显示6.OCM12864的基础显示的完整源码/**********************************************************************函数功能:写数据或命令到LCD**********************************************************************/voidLcd_WriteByte(bitbDataType,ucharVal){/*Lcd_BusyWait();//在仿真中,"忙等待&忙状态读取"函数无法通过while(Lcd_BusyRead());*/

LCD_PIN_DI=bDataType;LCD_PIN_RW=0;LCD_PIN_DATA=Val;LCD_PIN_E=1;LCD_PIN_E=0;}7.4.4OCM12864的基础显示/**********************************************************************函数功能:初始化**********************************************************************/voidLcd_Init(void){LCD_PIN_RST=0;//12864复位Delay_uS(50);LCD_PIN_RST=1;

Lcd_WriteByte(LCD_CMD,LCD_DISP_ON);//显示开}7.4.4OCM12864的基础显示//函数功能:设置页地址和列地址voidLcd_SetPageCol(unsignedcharucPage,unsignedcharucCol){ucharucPageScope,ucColScope;ucPageScope=LCD_PAGES-1;ucColScope=LCD_COLS-1;switch(ucCol&0xC0)//只保留低6位{case0://在左区LCD_PIN_LEFT_CS=0;LCD_PIN_RIGHT_CS=1;break;case0x40://在右区(0x40=64)LCD_PIN_LEFT_CS=1;LCD_PIN_RIGHT_CS=0;break;}//switchLcd_WriteByte(LCD_CMD,ucPage|LCD_SETX);//页地址范围为0~7Lcd_WriteByte(LCD_CMD,ucCol|LCD_SETY); //列地址范围为0~63}7.4.4OCM12864的基础显示//函数功能:在指定位置显示一行voidLcd_DisOneRow(ucharucPage,ucharucCol,ucharcode*pt,ucharucLng){uchari,j,ucTmpPage,ucTmpCol,ucFontWidth,ucNum;ucTmpPage=ucPage;ucTmpCol=ucCol;if(ucLng==0){ucFontWidth=32;//一个汉字16x16点阵,字模有32字节ucNum=8; //一行有8个汉字}else{ucFontWidth=16;//一个英文16x8点阵,字模有16字节ucNum=16; //一行有16个英文}for(i=0;i<ucNum;i++){for(j=0;j<ucFontWidth;j++){//显示一个汉字或英文if(j==ucFontWidth/2){//显示字模的上半部分后,接着显示下半部分ucPage++;ucCol=ucTmpCol;}Lcd_SetPageCol(ucPage,ucCol++);Lcd_WriteByte(LCD_DATA,pt[i*ucFontWidth+j]);}ucPage=ucTmpPage; //显示一个汉字或英文后,页不变,列变ucTmpCol=ucCol;}}7.4.4OCM12864的基础显示/**********************************************************************函数功能:在指定位置显示一张图片**********************************************************************/voidLcd_DisImg(ucharcode*pt){ucharucPage,ucCol;

for(ucPage=0;ucPage<8;ucPage++)//总共8页{for(ucCol=0;ucCol<128;ucCol++)//显示一页{AddrConversion(ucPage,ucCol);Lcd_WriteByte(LCD_DATA,*(pt++));}}}7.4.4OCM12864的基础显示/**********************************************************************函数功能:主函数,在指定的位置显示中文,英文,数字,符号,图片等**********************************************************************/voidmain(){Lcd_Init();

while(1){Lcd_DisOneRow(0,0,ucChn,0);//在第0页最前面显示中文效果Lcd_DisOneRow(2,0,ucChnRev,0);//在第2页最前面显示中文反显Lcd_DisOneRow(4,0,ucEng,1);//在第4页最前面显示英文Lcd_DisOneRow(6,0,ucEngRev,1);//在第6页最前面显示英文反显Delay_1mS(3000);

Lcd_DisImg(ucImg);//显示图片Delay_1mS(3000);}}7.5OCM12864温度显示7.5.1任务要求在OCM12864的基础显示任务的基础上修改驱动程序,不仅要显示汉字、英文,还要显示数值,如温度值。7.5.2任务分析本任务要显示温度值,可将温度值中的每个数值拆开,找到对应的字模后送到OCM12864中显示即可。7.5.3原理图设计原理图设计的参考图不变,显示效果如图7-41所示。7.5.4OCM12864温度显示的程序设计与前面的操作一样,使用取模软件生成“Temperature:”和数字0~9的字模。参考Lcd_DisOneRow()函数,编写一个在指定位置显示温度值的函数Lcd_DisTemp(),数字为16×8点阵,所以跟显示英文的代码是一样的。ucharcodeucTemp[]=//"Temperature:"的字模,宋体,高x宽=16x8{//由于这里篇幅所限,省略字模,具体见例程源码};ucharcodeucNumber[]=//数字"0~9"的字模,宋体,高x宽=16x8{//由于这里篇幅所限,省略字模,具体见例程源码};7.5.4OCM12864温度显示的程序设计//函数功能:在指定位置显示温度值voidLcd_DisTemp(ucharucPage,ucharucCol,ucharucTemp){uchari,j,ucTmpPage,ucTmpCol;uchartmp[3];ucTmpPage=ucPage;ucTmpCol=ucCol;tmp[0]=0; //温度值

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论