12864液晶多级菜单设计
- 格式:pdf
- 大小:123.04 KB
- 文档页数:3
第17卷第1期2003年02月 华 东 船 舶 工 业 学 院 学 报(自然科学版)Journal of East China Shipbuilding Institute (Natural Science Edition ) Vo1117No 11Feb.2003文章编号:1006-1088(2003)01-0086-04单片机系统中液晶显示多级菜单的软硬件设计唐 炜,卢道华,顾金凤(华东船舶工业学院机械系,江苏镇江,212003)摘 要:以8031单片机控制GXM -12864液晶显示器为例,通过建立小字库,结合具体实例介绍了实现多级菜单显示的方法。
当菜单显示内容改变时,只需修改相应参数,而不修改程序。
文中提及的硬件电路和软件设计通用性较强,具有更一般的实际意义。
关键词:单片机;液晶显示器;接口;多级菜单中图分类号:TP311 文献标识码:A0 引 言在单片机系统中,常用的小型显示器有L ED 和LCD 两种,L ED 显示器只能显示数字和少量字符,用户须根据系统设计时所约定的格式来了解系统的运行状况或进行操作,而点阵图形式LCD 不仅体积小、超薄、功耗低,而且能显示汉字、图形、表格及曲线等,其界面友好,它常被用在仪器设备中作为显示终端或人机接口等,特别适合于我国具有自主知识产权产品的开发,应用前景十分广阔。
因此,要采用菜单驱动的工作方式来控制仪器设备的运行,在LCD 上如何实现多级菜单的显示也就成为必须要解决的问题。
本文在建立中、西文小字库的基础上,介绍了单片机与LCD 间的硬件接口电路以及实现多级菜单的软件设计方法,具有较强的通用性。
1 GXM -12864显示模块简介图1 CXM -12864液晶模块电路框图Fig.1 The structure of GXM -12864LCD GXM -12864显示模块是南京国显电子公司推出的一款集控制、驱动、显示于一体的图形点阵式LCD产品,其点阵数为128(列)×64(行),内部使用一片行驱动器HD61203和两片列驱动器HD61202组成驱动控制系统。
目录设计总说明 (I)INTRODUCTION (II)1 绪论 (1)1.1课题背景及研究意义 (1)1.2课题研究的主要内容 (1)1.3国内外发展状况与存在问题 (1)2 总体方案设计与论述 (2)2.1 系统需求分析 (2)2.2 系统总体方案设计 (2)2.2.1 设计方案论证 (2)2.2.2总体结构框图 (3)3系统单元模块设计 (3)3.1系统硬件示意图 (3)3.2主控芯片(STC89C52模块)[5] (4)3.3 时钟控制模块[13] (6)3.3.1 DS1302简介 (6)3.3.2引脚及功能表 (7)3.3.3工作原理 (7)3.3.4 DS1302电路设计图[9] (8)3.4 温度控制模块 (8)3.5 12864接口电路模块 (9)3.6 按键电路模块 (9)3.7 电源电路模块 (10)3.8 印制电路板[9] (10)4系统整体调试与结果分析 (11)4.1 系统总体程序流程介绍 (11)4.2 按键程序设计 (13)4.3 12864驱动程序设计[15] (14)4.3.1 ST7920芯片介绍[14] (14)4.3.2 ST7920驱动程序设计 (17)4.4 12864应用程序设计 (20)4.4.1 文字显示程序设计 (20)4.4.2 点、线显示程序设计 (22)4.4.3 图形、图片显示程序设计 (23)4.5 菜单程序设计 (26)5设计调试及进一步研究 (28)5.1 系统测试 (28)5.1.1 软件调试 (28)5.1.2 硬件调试 (29)5.2 进一步研究的工作 (30)6总结 (30)鸣谢................................................................................................................................ 错误!未定义书签。
#include <msp430x14x.h>#define uchar unsigned char#define uint unsigned int#define LCD_data P5DIR=0XFF //数据口输出#define LCD_CMDOUT P3DIR|=0xe0 //P3口的高三位设置为输出#define LCD_RS_LOW P3OUT &= ~BIT7 //RS=0#define LCD_RS_HIGH P3OUT |=BIT7 //RS=1#define LCD_RW_LOW P3OUT &= ~BIT6 //RW=0#define LCD_RW_HIGH P3OUT |=BIT6 //RW=1#define LCD_EN_LOW P3OUT &= ~BIT5 //EN=0#define LCD_EN_HIGH P3OUT |=BIT5 //EN=1uchar k=0,flag=0,flag1=0;uchar dis1_[] = {"系统初始化. "};uchar dis2_[] = {"系统初始化.. "};uchar dis3_[] = {"系统初始化... "};uchar dis4_[] = {" 按选择键开始! "};uchar dis1[] = {"手1:手机设定"}; //一级菜单1uchar dis2[] = {"机2:管理器"}; //一级菜单2uchar dis3[] = {"菜3:通话"}; //一级菜单3uchar dis4[] = {"单4:信息功能"}; //一级菜单5uchar dis5[] = {"手5:文件管理"}; //一级菜单7uchar dis6[] = {"机6:通讯录"}; //一级菜单8uchar dis7[] = {"菜"}; //一级菜单8uchar dis8[] = {"单"}; //一级菜单8uchar dis1_1[] = {"手1:时间和日期"}; //一级菜单1下的子菜单1 uchar dis2_1[] = {"机2:语言"}; //一级菜单1下的子菜单2 uchar dis3_1[] = {"设3:语音控制"}; //一级菜单1下的子菜单3 uchar dis4_1[] = {"定4:关闭无线电"}; //一级菜单1下的子菜单4uchar dis1_2[] = {"管1:闹铃"}; //一级菜单2下的子菜单1 uchar dis2_2[] = {"理2:视频电话"}; //一级菜单2下的子菜单2 uchar dis3_2[] = {"器3:日历"}; //一级菜单2下的子菜单3 uchar dis4_2[] = {" 4:任务"}; //一级菜单2下的子菜单4uchar dis1_3[] = {"通1:全部"}; //一级菜单3下的子菜单1 uchar dis2_3[] = {"话2:已接来电"}; //一级菜单3下的子菜单2 uchar dis3_3[] = {" 3:未接来电"}; //一级菜单3下的子菜单3 uchar dis4_3[] = {" 4:已拨电话"}; //一级菜单3下的子菜单4uchar dis1_4[] = {"信1:编写新信息"}; //一级菜单4下的子菜单1uchar dis2_4[] = {"息2:收件箱"}; //一级菜单4下的子菜单2uchar dis3_4[] = {"功3:电子邮件"}; //一级菜单4下的子菜单3uchar dis4_4[] = {"能4:草稿箱"}; //一级菜单4下的子菜单4uchar dis1_5[] = {"文1:相册"}; //一级菜单5下的子菜单1uchar dis2_5[] = {"件2:音乐"}; //一级菜单5下的子菜单2uchar dis3_5[] = {"管3:视频"}; //一级菜单5下的子菜单3uchar dis4_5[] = {"理4:图片"}; //一级菜单5下的子菜单4uchar dis1_6[] = {"通1:快速拨号"}; //一级菜单6下的子菜单1uchar dis2_6[] = {"讯2: 我的名片"}; //一级菜单6下的子菜单2uchar dis3_6[] = {"录3: 组群"}; //一级菜单6下的子菜单3uchar dis4_6[] = {" 4:特定号码"}; //一级菜单6下的子菜单4void delay_1ms(uint x){uint i,j;for(j=0;j<x;j++)for(i=0;i<113;i++);}void write_cmd(uchar cmd)//写指令数据到LCD :RS=L,RW=L,E=高脉冲,D0-D7=指令码{LCD_RS_LOW ;LCD_RW_LOW ;LCD_EN_LOW ;P5OUT = cmd;delay_1ms(1);LCD_EN_HIGH;delay_1ms(1);LCD_EN_LOW;}void write_dat(uchar dat)//写显示数据到LCD :RS=H,RW=L,E=高脉冲,D0-D7=数据。
我的lcd12864菜单大致框架2019-07-12 00:24:06| 分类:ELECTRONIC | 标签:|字号大中小订阅lcd12864菜单大致框架算是完成了,主要实现了两个功能----反白,翻页。
原本是想做一个多级---起码也得二级----菜单,但有意外的时间安排,故暂且放下。
个人认为比较费脑筋的是反白功能的制作。
首先12864并没有专门为用户准备单行的反白,要么一三行一块反,要么二四一块。
所以得参照前人的方法,即将字符显示与图像显示结合,在需要反白的部分用绘图功能全写上0xff,有自带的异或逻辑能成功反白。
这部分让我摸索了几小时。
其次是这种反白实现之前,得先给原来的图像全清掉,也正是这一步让89c52耗费了不少时间,选项切换间居然要用1s 的时间。
这是不能忍的啊。
所以自己想了一个办法,让图像整体清除换成部分清除。
思路是在选项光标变量Index_P 外再添一记录变量----Index_P_Pre-----以记录上一次选项所在位置,然后在清除图像的时候专门清除Index_P_Pre 对于的图像痕迹,这样就将清屏所需的时间减少了3/4。
好了,这个菜单模块总共用了6KB。
对于64KB的89C52来说还有很多空间,自己也可以放心弄下去。
以后的工作就是整合了。
/*Index_Num 数组元素最大序号Index 数组元素当前序号Index_P 选中项序号Index_P_Pre 上一选中项序号,用于快速清理上次所画下的图案*/#include <reg52.h>#include <intrins.h>#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};#define LCD_data P0 //数据口#define Index_Num 8typedef unsigned char uchar;typedef unsigned int uint;sbit Key1 = P1^0;sbit Key2 = P1^1;sbit LCD_RS = P2^6; //寄存器选择输入cssbit LCD_RW = P2^5; //液晶读/写控制sidsbit LCD_EN = P2^7; //液晶使能控制clksbit LCD_PSB = P3^2; //串/并方式控制sbit LCD_RST = P3^7; //液晶复位端口bdata uchar DataBuf;uint Index,Index_P_Pre;uint Index_P=0;uchar code Weibo[][16]={"hello","呀咦晗昱","weibo","/maixianyu","blog.163","maixianyu@126","123","456","789"};////////////////////////////////////////////// 200usvoid delay(int ms){uchar t;while(ms--){for(t=0; t<20; t++) ;}}////////////////////////////////////////////////////////////////// void Lcd_Write_8bit(uchar msg){uint i;uchar DataBuffer;DataBuffer=msg;for(i=0;i<8;i++){LCD_RW=(bit)(DataBuffer&0x80);LCD_EN=1;_nop_();_nop_();LCD_EN=0;_nop_();_nop_();DataBuffer<<=1;}}/////////////////////////////////////////uchar Lcd_Rec(uint RS){uint i;uchar Data_H,Data_L;LCD_RS=1;if(RS)Lcd_Write_8bit(0xfe);elseLcd_Write_8bit(0xfc);delayNOP();for(i=0;i<8;i++){LCD_EN=1;Data_H=(Data_H<<1)|LCD_RW;LCD_EN=0;}delayNOP();for(i=0;i<8;i++){LCD_EN=1;Data_L=(Data_L<<1)|LCD_RW;LCD_EN=0;}LCD_RS=0;DataBuf=(Data_H<<4)|Data_L;return DataBuf;}/////////////////////////////////////////bit Lcd_Busy(){return Lcd_Rec(0)&0x80;}/////////////////////////////////////////void Lcd_Write(uchar msg,uint dc){ //if dc equals 0,msg is a kind of cmd.while(Lcd_Busy());if(dc==0)DataBuf=0xf8;elseDataBuf=0xfa;delayNOP();LCD_RS=1;Lcd_Write_8bit(DataBuf);delayNOP();DataBuf=msg&0xf0;Lcd_Write_8bit(DataBuf);delayNOP();DataBuf=(msg<<4)&0xf0;Lcd_Write_8bit(DataBuf);LCD_RS=0;}////////////////////////////////////////////////////void Disp_black() //清理上一次画下的痕迹{uchar i,j;Lcd_Write(0x34,0); //写数据时,关闭图形显示if(Index_P_Pre<2){for(i=0+16*Index_P_Pre; i<16+16*Index_P_Pre; i++){Lcd_Write(0x80+i,0);Lcd_Write(0x80,0);for(j=0;j<16;j++)Lcd_Write(0x00,1);}}else{for(i=0+16*(Index_P_Pre-2);i<16+16*(Index_P_Pre-2);i++){Lcd_Write(0x80+i,0);Lcd_Write(0x88,0);for(j=0;j<16;j++)Lcd_Write(0x00,1);}}Lcd_Write(0x36,0); //写完数据,开图形显示}void convertChar(uchar CX) // 反白函数{uchar halfLineCnt, basicBlock,lcdPosX,lcdPosY;// if(f==1)Disp_black(); //清绘图区lcdPosY = 0x80;if (CX == 0){CX = 0x80;halfLineCnt = 16;}else if (CX == 1){CX = 0x80;halfLineCnt = 32;}else if (CX == 2){CX = 0x88;halfLineCnt = 16;}else if (CX == 3){CX = 0x88;halfLineCnt = 32;}lcdPosX = CX;for (; halfLineCnt != 0; halfLineCnt--){basicBlock = 16;Lcd_Write(0x34,0);Lcd_Write(lcdPosY,0);Lcd_Write(lcdPosX,0);Lcd_Write(0x30,0);for (;basicBlock != 0; basicBlock--){if (halfLineCnt > 16){Lcd_Write(0x00,1);}else{Lcd_Write(0xff,1);}}lcdPosY++;}Lcd_Write(0x36,0);Lcd_Write(0x30,0);}///////////////////////////////////////////////////void Lcd_Pos(uchar x,uchar y){uchar pos;if(x==1){x=0x80;}else if(x==2){x=0x90;}else if(x==3){x=0x88;}else if(x==4){x=0x98;}pos=x+y;Lcd_Write(pos,0);}///////////////////////////////////////////void Lcd_Menu(uint Head){uint j,i;uint Index_End=Head+3;// if(Index_End<=Index_Num){for(j=0;Head<=Index_End;Head++,j++){Lcd_Pos(j+1,0);i=0;while(i<15){if(Weibo[Head][i]!=0)Lcd_Write(Weibo[Head][i++],1);else{Lcd_Write(0x20,1);i++;}}delayNOP();}// }}///////////////////////////////////////////void Lcd_Init(void){LCD_PSB=0;LCD_RST=0;LCD_RS=0;LCD_RW=1;LCD_EN=0;delay(2);LCD_RST=1;delay(2);Lcd_Write(0x30,0); //ordinary cmddelay(2);Lcd_Write(0x0c,0); //how to showdelay(2);Lcd_Write(0x01,0); //cleardelay(2);}/////////////////////////////////////////void main(void){Lcd_Init();Key1=1;Lcd_Menu(Index);convertChar(Index_P);while(1){if(Key1==0&&Index>=0){delay(5);if(Key1==0&&Index>=0){if(Index_P==0&&Index>0)Lcd_Menu(--Index);if(Index_P>0){Index_P_Pre=Index_P;convertChar(--Index_P);}}}if(Key2==0&&Index_P<=3){delay(5);if(Key2==0&&Index_P<=3){if(Index_P==3&&Index<(Index_Num-3)) Lcd_Menu(++Index);if(Index_P<3){Index_P_Pre=Index_P;convertChar(++Index_P);}}}}}。
#include "includes.h"u8 key=0,hua;extern u32 Second;extern u32 minite,hour,day,k,month,year,shan;u8 xingqi[]={"一二三四五六日"};u8 ModeFlag=0,wei=0;//液晶界面选择int main(void){u8 PasswordIndex=0;//密码数组索引u8 Password[4]={" "};//存储密码数组BSP_Init();//初始化外部资源ModeFlag=0;while(1){//////////////////////////////////////// 界面一//////////////////////////////////if(ModeFlag==0){ LCD12864_Waddr(1,3);LCD12864_WPoss(0,"WELCOME!");LCD12864_Waddr(2,2);LCD12864_WPoss(0,"--欢迎使用--");Delay_1ms(8000);LCD12864_Clear();}//////////////////////////////////////// 界面二//////////////////////////////////// ModeFlag=0; ///// 改while(ModeFlag==0) //进入登录界面{LCD12864_Waddr(1,1);LCD12864_WPoss(0,"请输入登陆密码:");LCD12864_Waddr(2,3);//LCD12864_WPoss(0," ");LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码为四位数字");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"删除*");LCD12864_Waddr(4,6);LCD12864_WPoss(0,"确定#");key=Key_Scan();//键盘扫描if(key_check==1)//检测是否有按键按下{if(key<='9'&&key>='0')//密码只能是数字{Password[PasswordIndex]=key;//存储输入的密码// LCD12864_WPoss(0," ");//////////////// 改动过++PasswordIndex; //记录输入密码的次数if(PasswordIndex>4) //如果次数超过4次返回重新输入{PasswordIndex=0;//清空索引Password[0]=0;//清空数组Password[1]=0;Password[2]=0;Password[3]=0;LCD12864_Clear();LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码只能为四位");Delay_1ms(4000);//延时两秒显示LCD12864_Clear(); //延时清空break;}if(PasswordIndex<=4){LCD12864_Waddr(2,3);LCD12864_WPoss(0,Password);//显示输入的密码LCD12864_WPoss(0," ");/// 改}//ModeFlag=10;//进入while(1) 重新开始///// 改}if(key=='#') //确认密码{if(PasswordIndex<4)//密码位数少于4位则返回重新输入{PasswordIndex=0;Password[0]=0;Password[1]=0;Password[2]=0;Password[3]=0;LCD12864_Clear();LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码只能为四位");Delay_1ms(4000);LCD12864_Clear();break;}if(Password[0]=='1'&&Password[1]=='2'&&Password[2]=='3'&&Password[3]=='4'){//如果输入密码正确则进入计数界面//ModeFlag=2;LCD12864_Clear();//// LCD12864_Waddr(1,5);//// LCD12864_WPoss(0,"00:00");// LCD12864_Waddr(2,4);//// LCD12864_WPoss(0,"2013/01/01");// LCD12864_Waddr(3,4);// LCD12864_WPoss(0,"星期一");//// LCD12864_Waddr(4,6);//// LCD12864_WPoss(0,"返回*");////// Second=0;//计数器清零// minite=0;//计数器清零// hour=0;// day=1;// month=1;}else //如果密码错误重新输入{//ModeFlag=10;//进入while(1) 重新开始LCD12864_Clear();LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码错误");Delay_1ms(4000);LCD12864_Clear();PasswordIndex=0;Password[0]=0;Password[1]=0;Password[2]=0;Password[3]=0;break;}}if(key=='*')//删除按键{Password[--PasswordIndex]=' ';//删除一位密码LCD12864_Waddr(2,3);LCD12864_WPoss(0,Password);//显示输入的密码LCD12864_WPoss(0," ");if(PasswordIndex<=0){PasswordIndex=0;break;}}key_check=0;LCD12864_Waddr(2,8);LCD12864_WPoss(0," ");}}//////////////////////////////////界面三///////////////////////////////////////////////////while(ModeFlag==2){LCD12864_Waddr(1,1);LCD12864_WPoss(0,"查看时钟");LCD12864_Waddr(1,6);LCD12864_WPoss(0," B向上");LCD12864_Waddr(2,1);LCD12864_WPoss(0,"查看图片");LCD12864_Waddr(2,6);LCD12864_WPoss(0," C向下");LCD12864_Waddr(3,1);LCD12864_WPoss(0,"空文件");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"返回*");LCD12864_Waddr(4,6);LCD12864_WPoss(0,"确定#");key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='B'){if(hua>0)hua--;}if(key=='C'){if(hua<2)hua++;}if(hua>2)hua=0;switch(hua){case 0:{convertChar(1,1,10);break;}case 1:{ convertChar(2,1,10);break;}case 2:{convertChar(3,1,10);break;}}if(key=='#'){if(hua==0)ModeFlag=3;if(hua==1)ModeFlag=4;if(hua==2)ModeFlag=5;LCD12864_W (LCD12864_COM,0x30);break;}if(key=='*'){LCD12864_Clear();Delay_1ms(1000);ModeFlag=0;LCD12864_Clear();}}}/////////////////////////////////////////// 界面四//////////////////////////if(ModeFlag==3)//计数界面{///////// Password[ ]=" ";// LCD12864_Waddr(1,1);// LCD12864_WPoss(0," ");LCD12864_Clear();//LCD12864_Waddr(1,5);//LCD12864_WPoss(0,"00:00");LCD12864_Waddr(2,4);//LCD12864_WPoss(0,"2013/01/01");LCD12864_Waddr(3,4);LCD12864_WPoss(0,"星期一");//LCD12864_Waddr(4,6);//LCD12864_WPoss(0,"返回*");//Second=0;//计数器清零minite=0;//计数器清零hour=0;day=1;month=1;while(ModeFlag==3){ if(shan==0) // :以秒为单位进行闪烁{LCD12864_Waddr(1,6);LCD12864_WPoss(0," ");}if(shan!=0){LCD12864_Waddr(1,6);LCD12864_WPoss(0,":");}if(minite<10){LCD12864_Wnum(0,0);LCD12864_Wnum(minite,0);LCD12864_WPoss(0," ");}else{LCD12864_Wnum(minite,0);LCD12864_WPoss(0," ");}LCD12864_Waddr(1,5);if(hour<10){LCD12864_Wnum(0,0);LCD12864_Wnum(hour,0);}if(hour>=10){LCD12864_Waddr(1,5);LCD12864_Wnum(hour,0);}LCD12864_Waddr(2,8);if(day<10){LCD12864_Wnum(0,0);LCD12864_Wnum(day,0);}if(day>=10)LCD12864_Wnum(day,0); LCD12864_Waddr(2,6);if(month<10){LCD12864_WPoss(0,"/");LCD12864_Wnum(0,0);LCD12864_Wnum(month,0);LCD12864_WPoss(0,"/");}if(month>=10){LCD12864_WPoss(0,"/");LCD12864_Wnum(month,0);LCD12864_WPoss(0,"/");}LCD12864_Waddr(3,6);LCD12864_W(LCD12864_DAT,xingqi[k]);LCD12864_W(LCD12864_DAT,xingqi[k+1]);if(day>365)year++;LCD12864_Waddr(2,4);LCD12864_Wnum(year,0);key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='A'){ wei++;if(wei==7)wei=1;}switch(wei){case 1:{if(key=='B')hour++;if(hour>0){ if(key=='C')hour--;}convertChar(1,5,2);//写入字节break;}case 2:{if(key=='B')minite++;if(minite>0){ if(key=='C')minite--;}convertChar(1,6,3);break;}case 3:{if(key=='B')year++;if(year>0){ if(key=='C')year--;}convertChar(2,4,4);break;}case 4:{if(key=='B')month++;if(month>1){ if(key=='C')month--;}convertChar(2,6,3);break;}case 5:{if(key=='B')day++;if(day>1){ if(key=='C')day--;}convertChar(2,8,2);break;}case 6:{if(key=='B')k=k+2;convertChar(3,6,2);break;}}if(key=='*'){ModeFlag=2;Delay_1ms(40);LCD12864_Clear();}}}}////////////////////////////////// 界面五////////////////////////////// while(ModeFlag==4){LCD12864_Clear();LCD12864_Waddr(2,3);LCD12864_WPoss(0,"No pictures");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"返回*");key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='*'){LCD12864_Clear();Delay_1ms(1000);ModeFlag=2;LCD12864_Clear();}}}///////////////////////////////// 界面六///////////////////////////////// while(ModeFlag==5){LCD12864_Clear();LCD12864_Waddr(2,3);LCD12864_WPoss(0,"啥也没有");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"返回*");key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='*'){Delay_1ms(100);ModeFlag=2;LCD12864_Clear();}}}}}。
一种易于移植的单片机液晶显示多级菜单设计王勇【摘要】LCD display as a human-computer interaction is very popular in various application situations of embedded microcontroller systems. However, general LCD display menu design is a little bit complicated, and does not have the portability, therefore the complexity in development and system maintenance and the cost are increased. In this paper we introduce the window and message mechanisms of Windows Operating System, and design a multilevel menu. The core of the menu is a universal window engine which does not depend on specific hardware and the content of menu. Research and application show that the menu design has the characters of simple structure, easy to use, little resource consumption, portable and so on. In the end of the paper we present an application example running in the FYD12864 LCD module.%在单片机嵌入式系统的许多应用场合均采用液晶显示器作为人机交互的方式,然而通常的液晶显示菜单设计较为复杂,且基本不具备可移植性,从而增加了开发、维护的复杂性和成本.引入Windows系统下的窗口和消息机制,设计一个多级菜单,该菜单的核心部分是一个不依赖具体硬件和菜单内容的通用的窗口引擎.研究和应用表明,该菜单设计具有结构简单、使用方便、占用资源少以及易于移植等特点.最后给出一个在FYD12864液晶模块上使用此方法的应用案例.【期刊名称】《计算机应用与软件》【年(卷),期】2011(028)012【总页数】6页(P263-268)【关键词】单片机;液晶显示;菜单;窗口引擎【作者】王勇【作者单位】电子科技大学四川成都610054东莞电子科技大学电子信息工程研究院广东东莞523808【正文语种】中文【中图分类】TP3110 引言单片机系统,特别是8位单片机系统通常可用资源较少,速度相对较慢,一般不适合部署操作系统,更谈不上图形引擎了。
LCD 128641.总体设计思路SMG12864一般用于显示汉字,字符,分辨率不高的bmp图像,可用来显示传感器采集到信息,是单片机和人交换信息的窗口,2.方案设计8051Lcd12864单片机3.硬件设计单片机控制12864的管脚来显示想要的字符和图像,P0用来发送必要的指令和数据,P2口协助P1口给12864写数据,1. 指令寄存器(IR)IR 是用于寄存指令码,与数据寄存器数据相对应。
当D/I=0 时,在E 信号下降沿的作用下,指令码写入IR。
2.数据寄存器(DR)DR 是用于寄存数据的,与指令寄存器寄存指令相对应。
当D/I=1 时,在下降沿作用下,图形显示数据写入DR,或在E 信号高电平作用下由DR 读到DB7∽DB0数据总线。
DR 和DDRAM 之间的数据传输是模块内部自动执行的。
3.忙标志:BFBF 标志提供内部工作情况。
BF=1 表示模块在内部操作,此时模块不接受外部指令和数据。
BF=0 时,模块为准备状态,随时可接受外部指令和数据。
利用STATUS READ 指令,可以将BF 读到DB7 总线,从检验模块之工作状态。
4.显示控制触发器DFF此触发器是用于模块屏幕显示开和关的控制。
DFF=1 为开显示(DISPLAY OFF),DDRAM 的内容就显示在屏幕上,DFF=0 为关显示(DISPLAY OFF)。
DDF 的状态是指令DISPLAY ON/OFF 和RST 信号控制的。
5.XY 地址计数器XY 地址计数器是一个9 位计数器。
高3 位是X 地址计数器,低6 位为Y 地址计数器,XY 地址计数器实际上是作为DDRAM 的地址指针,X 地址计数器为DDRAM的页指针,Y 地址计数器为DDRAM 的Y 地址指针。
X 地址计数器是没有记数功能的,只能用指令设置。
Y 地址计数器具有循环记数功能,各显示数据写入后,Y 地址自动加1,Y 地址指针从0 到63。
6.显示数据RAM(DDRAM)DDRAM 是存储图形显示数据的。