12864液晶多级菜单设计
由LCD12864初探嵌入式菜单设计(完全资料)
1、位操作 向 LCD12864 这种二值屏幕,我们习惯于用 1 个字节表示连续的 8 个点,1 对应对应位被点亮,0 表示不
亮,所以对图形的操作最基本的手段就是位操作。 复习下,常用的位操作,假设 Dis 表示某一个现存地址的内容 Dis = Dis~ 黑白颠倒 Dis &= ~(1<<n) 第 n 处被擦去, Dis |= (1<<n) 第 n 处被画了一个点 Dis ^= (1<<n) 如果 n 处是亮的,就变被擦掉;如果 n 处是空白的,就被点亮…… …… 差不多就这些
default: TempData |= (1 << BX);
}
setY(X);
500361 sendDataToLCD(TempData); ll648 } om/ba 特别说明一下,关于贪食蛇范例的问题,这篇文章里面只会简单得提及一下。 idu.c 作为嵌入式系统开发的一个范例,我会另外开一个帖子详细说明开发过程。 i.ba 这个范例将作为介绍嵌入式系统开发方法的一个很好的例子,用于解释一个系统和一段表示您调通了某一 ://h 个功能的代码之间有什么区别,同时也将介绍嵌入式开发系统的几种模式(超级循环、调度器),顺便侃一
PDF 文件使用 "pdfFactory Pro" 试用版本创建
首先,我们从最基本的数学算法说起。 如果我们使用公式 y = kx + b 来作为绘图的依据,那么就需要分 3 种情况:水平直线,斜率为 0;垂直直
硬件平台:AVR Mega8 级 LCD: 不带字库的 12864 软件平台:ICC 规范: 符合基本的 C 编程规范
3、何时开始正文 其实,本文应该算是计算机图形学的一个具体分支,所以,计算机图形学的基本要求就是本文的基本要求, 考虑到各位兄弟的胃口,我就多罗嗦下。
旋转编码器控制12864液晶多级菜单显示
(5)、工作电流:2.0mAmax
5、接口说明
管 管脚 电平 脚 号
1 VSS 0V
2 VDD 5.0V
3 V0
说明
逻辑电源地。 逻辑电源正。 LCD 驱动电压,应用时在 VEE 与 V0 之间加一 10K 可调电阻。
4 D/I H/L
5 R/W H/L
6
E H.H/L
7 DB0 H/L
8 DB1 H/L
Line 0 1/0 1/0 1/0 1/0 …………
1/0 1/0 1/0 DB0
Line 1 1/0 1/0 1/0 1/0 …………
1/0 1/0 1/0 DB1
Line 2 1/0 1/0 1/0 1/0 ………… X=0
1/0 1/0 1/0 DB2
Line 3 1/0 1/0 1/0 1/0 …………
(4)、输入电压:Vee~Vdd
(5)、工作温度
:0~55℃(常温) / -20~70℃(宽温)
(6)、保存温度
:-10~65℃
4、电气特性
(1)、输入高电平
:3.5Vmin
(2)、输入低电平(Vil):0.55Vmax
(3)、输出高电平( ):3.75Vmin
(4)、输出低电平(Vol):1.0Vmax
(1)、显示开/关设置
L
L
L
L
H
H
H
H
H H/L
功能:设置屏幕显示开/关。 DB0=H,开显示;DB0=L,关显示。不影响显示 RAM(DD RAM)中的内容。
(2)、设置显示起始行
L
L
H
H
行地址(0~63)
功能:执行该命令后,所设置的行将显示在屏幕的第一行。显示起始行是由 Z 地址计数 器控制的,该命令自动将 A0-A5 位地址送入 Z 地址计数器,起始地址可以是 0-63 范围 内任意一行。Z 地址计数器具有循环计数功能,用于显示行扫描同步,当扫描完一行后 自动加一。
单片机系统中液晶显示多级菜单的软硬件设计
第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组成驱动控制系统。
电子信息工程专业毕业设计--基于51单片机的12864液晶显示器的设计和研究
目录设计总说明 (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)鸣谢................................................................................................................................ 错误!未定义书签。
msp430单片机12864二级菜单
#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初探嵌入式菜单设计(最完整资料)
PDF 文件使用 "pdfFactory Pro" 试用版本创建
case LCD12864_Graphic_Not: TempData ^= (1 << BX); break;
//计算出属于哪个字节 //属于该字节的哪个位
2、读取 12864 的数据的时候,一定要注意,E 信号要在一个下降延之后持续拉高,然后才能正常独处数据;
假设直接拉高,的确也能读出数据,但是,等着抓头皮,发帖子“[跪求]大侠帮忙关于 12864——请使用明
确的大标题……”^_^
500361 --------------------------------------------ll648 废话少说(说的不少了),看源代码:
default: TempData |= (1 << BX);
}
setY(X);
500361 sendDataToLCD(TempData); ll648 } om/ba 特别说明一下,关于贪食蛇范例的问题,这篇文章里面只会简单得提及一下。 idu.c 作为嵌入式系统开发的一个范例,我会另外开一个帖子详细说明开发过程。 i.ba 这个范例将作为介绍嵌入式系统开发方法的一个很好的例子,用于解释一个系统和一段表示您调通了某一 ://h 个功能的代码之间有什么区别,同时也将介绍嵌入式开发系统的几种模式(超级循环、调度器),顺便侃一
PDF 文件使用 "pdfFactory Pro" 试用版本创建
储器的访问,其速度显然没有对片内 SRAM 的操作速度要快。如果我们使用那种常用的串行方式来作图(所 谓串行方式作图,就是绘图指令的执行和系统的其他操作时串行的,指令不完成,其它操作就不回被执行), 那么对于一些实时性要求高的系统来说就会造成重大隐患——甚至是不符合要求的;如果开辟一段片内存 储空间和 LCD 的存储器一一对应,在相同的时间段内,花费相同的资源来保持着两个存储空间的一致性, 那么就可以保证实时系统的稳定和可靠,保证画面显示的正常(因为允许跳帧嘛^_^)。这就是我们为什么 需要另外在片内选取一个显示缓冲区的原因。
我的lcd12864菜单大致框架7页word文档
我的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);}}}}}。
12864并行多级菜单程序
#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位单片机系统通常可用资源较少,速度相对较慢,一般不适合部署操作系统,更谈不上图形引擎了。
(完整word版)lcd12864 课程设计
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 是存储图形显示数据的。
51单片机实现多级液晶显示中文菜单
51单片机实现多级液晶显示中文菜单【摘要】以at89c51单片机控制使用比较普遍的ym12864液晶显示器为基础,介绍了一种采用分页原理实现多级中文菜单操作的方法。
给出了ym12864主要技术参数、显示特性和核心的程序。
设计的中文菜单具有一定的通用性,只需更改其中的菜单项即可将此设计应用到家电、仪器仪表等设备上,为操作者提供友好方便的中文操作界面。
【关键词】单片机;分页;ym12864液晶;中文菜单一、引言目前小型的显示器主要有lcd和led,led显示器只能显示数字和有限个英文字符,不能显示汉字,显示内容不直观,操作人员只能根据约定格式了解显示内容。
而lcd则可显示各种汉字和图形,尤其能实现中文菜单显示,为操作者提供方便友好的操作界面,并且功耗低,因此lcd得到广泛应用。
而现在市面上带中文字库的lcd比比皆是,价格适中,且大部分具有与mcu统一的标准接口,为使用lcd实现中文菜单操作提供了很大的方便。
相信更多的电子产品在提升性能的同时,设计更加人性化的中文菜单交互界面,将会使产品具有更广阔的前景。
二、ym12864液晶显示模块简介ym12864汉字图形点阵液晶显示模块,可显示汉字及图形,内置8192个中文汉字(16x16点阵)、128个字符(8x16点阵)及64x256点阵显示ram(gdram)。
主要技术参数和显示特性:电源:vdd 3.3v~+5v(内置升压电路,无需负压)显示内容:128列×64行与mcu接口:8位或4位并行/3位串行多种软件功能:光标显示、画面移位、自定义字符、睡眠模式等。
三、原理分析四、硬件设计使用89c51的p1口作为液晶显示器的数据口,使用p0口作为键盘扫描端口,当然这些端口也可以使用扩展口,只需在程序的开头修改端口的值便可。
电路图如图1所示。
五、软件设计重点在于软件的设计,而程序的关键又在于使用了分页的操作方式。
以下为菜单数据,按页的方式存放,不足一页的补空格。
LCD12864菜单程序
一起来学LCD12864菜单程序(包含完整程序)一起来学LCD12864菜单程序(包含完整程序)/*-------------------------------------------项目名:家电中央控制系统工程程序名:显示MCU总体程序编写人:杜洋初写时间:2005年9月5日晚20时程序功能:实现液晶、语音部分的人机对话和总线的通信实现方法:用中断实现总线接收CPU说明:89S5212MHZ晶振接口说明:(详见初定义)信息说明:修改日志:NO.1--------------------------------------------*/;----------------------------------------初定义LCDDAT EQU P2RS EQU P3.5RW EQU P3.6E EQU P3.7REDLED EQU P3.4BACKLED EQU P3.1PLAY EQU P1.7STOPIN EQU P3.0LIN EQU P3.2SPDAT EQU P1XX2 EQU P0.0LT_RAM EQU 30HLR_RAM EQU 40HSP_RAM EQU 20HDIS1_RAM EQU 50HDIS2_RAM EQU 70HDIS3_RAM EQU 60HDIS4_RAM EQU 80HRR1 EQU 26HRR3 EQU 21HRR4 EQU 22HT0_RAM EQU 23HQR3_RAM EQU 24HQR2_RAM EQU 25HLCDDISPLAY EQU 26H ;菜单显示移位寄存器MENU_RAM EQU 27H;菜单位置寄存器ONOFFLCD EQU 28H;-------------------------------------程序入口ORG 0000HJMP LCD_STARTORG 0003HJMP LIN_INT0ORG 000BHJMP LED_T0ORG 0030H;--------------------------------------主程序开始LCD_START br>SETB PLAYMOV T0_RAM,#250MOV TMOD,#01HSETB ET0MOV TL0,#0B0H ;50MS 定时初值(T0计时用)MOV TH0,#3CH ;50MS定时初值CLR IT0SETB EX0SETB TR0SETB EAMOV DPTR,#TAB_0CALL START_LCD;-----自检程序CALL DL1SMOV MENU_RAM,#00HMOV DPTR,#TAB_HCALL START_LCDCLR LCDDISPLAY;--------------------------------------主循环体程序LCD_LOOP br>JB ONOFFLCD,DISPLAY_PROLCD_LOOP_1br>JMP LCD_LOOP;---------------------------- 菜单显示处理DISPLAY_PRO br>MOV A,MENU_RAMMOV DPTR,#MENUTAB_HOSTRLC AJMP @A+DPTRMENUNEXT br>CALL START_LCDCLR LCDDISPLAYCLR ONOFFLCDJMP LCD_LOOP;-------------------------MENUTAB_HOST:JMP HOST_H ;主菜单JMP HOST_1 ; 1,控制JMP HOST_2 ; 2,设置JMP HOST_3 ; 3,智能JMP HOST_4 ; 4,帮助<。
基于12864的菜单设计
编写者:董新凯2011.7.20 仅供交流#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */#include "init.h"#define UINT8 unsigned char#define UINT16 unsigned int#define D_RS PTCD_PTCD4#define D_RW PTFD_PTFD4#define D_E PTCD_PTCD0#define D_L PTCD_PTCD1 //左右半屏选择#define D_R PTCD_PTCD2#define D_REST PTFD_PTFD5 //复位选择#define LED1 PTCD_PTCD5#define LED2 PTCD_PTCD6#define LED3 PTCD_PTCD7#define LED4 PTFD_PTFD6#define LED5 PTFD_PTFD3/******************菜单填充**************/# define FillType_Fill 0x01 //填充黑色# define FillType_Clear 0x00 //填充白色const UINT8 zimo[][32]={/*-- 文字: 菜0 --*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x04,0x04,0x44,0xC4,0x4F,0x44,0x44,0xC4,0x24,0x24,0x2F,0xB4,0x24,0x04,0x04,0x00, 0x40,0x44,0x24,0x24,0x15,0x0C,0x04,0xFE,0x04,0x0C,0x15,0x24,0x24,0x44,0x40,0x00, },/*-- 文字: 单 1 --*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x00,0x00,0xF8,0x49,0x4A,0x4C,0x48,0xF8,0x48,0x4C,0x4A,0x49,0xF8,0x00,0x00,0x00, 0x10,0x10,0x13,0x12,0x12,0x12,0x12,0xFF,0x12,0x12,0x12,0x12,0x13,0x10,0x10,0x00, },/*-- 文字: 一2--*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, },/*-- 文字: 二3--*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, },/*-- 文字: 三4--*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, },/*-- 文字: 四5--*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x00,0xFC,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0xFC,0x00,0x00, 0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x7F,0x00,0x00, },/*-- 文字: 是6--*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x00,0x00,0x00,0x7F,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x7F,0x00,0x00,0x00,0x00, 0x81,0x41,0x21,0x1D,0x21,0x41,0x81,0xFF,0x89,0x89,0x89,0x89,0x89,0x81,0x81,0x00, },/*-- 文字: 否7--*//*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/{0x00,0x02,0x82,0x82,0x42,0x22,0x12,0xFA,0x06,0x22,0x22,0x42,0x42,0x82,0x00,0x00, 0x01,0x01,0x00,0xFC,0x44,0x44,0x44,0x45,0x44,0x44,0x44,0xFC,0x00,0x00,0x01,0x00, }};/******************************************/UINT8 Menu_word[][4]={{0,1,2},{0,1,3},{0,1,4},{0,1,5}} ;struct MenuItem{ //菜单结构UINT8 MenuCount;//菜单项所在层的菜单项数目UINT8 *DisplayString;//显示的名称void (*subs)(void);//所指向的功能函数UINT8 Local_x;UINT8 Local_y;//菜单的横纵起始坐标struct MenuItem *ChildrenMenu;//所指向的子菜单struct MenuItem *ParentMenu;//所指向的父菜单struct MenuItem *This;//This指针指向本项菜单1行地址};/*****************************************/struct MenuItem MainMenu[4];struct MenuItem ChildMenu1[3];struct MenuItem ChildMenu2[3];struct MenuItem ChildMenu3[3];struct MenuItem ChildMenu4[3];struct MenuItem SubChildMenu1;struct MenuItem SubChildMenu2;struct MenuItem SubChildMenu3;/**********************************************************/ struct MenuItem *Menu_point=MainMenu;UINT8 key_number=0;UINT8 key_number_store=0;/**********************************************************/ void _12864_busycheck(void);void _12864_wr_cmd(UINT8 cmd);void _12864_clear_dot(UINT8 x,UINT8 y);void delay(UINT16 time){UINT16 i;for(i=0;i<time;i++);}/****************菜单初始化******************/ void MainMenu_init(void){MainMenu[0].MenuCount=4;MainMenu[0].DisplayString=&Menu_word[0][0];MainMenu[0].subs=NULL;MainMenu[0].Local_x=5;MainMenu[0].Local_y=16;MainMenu[0].ChildrenMenu=ChildMenu1;MainMenu[0].ParentMenu=NULL;MainMenu[0].This=MainMenu;MainMenu[1].MenuCount=4;MainMenu[1].DisplayString=&Menu_word[1][0];MainMenu[1].subs=NULL;MainMenu[1].Local_x=5;MainMenu[1].Local_y=16;MainMenu[1].ChildrenMenu=ChildMenu2;MainMenu[1].ParentMenu=NULL;MainMenu[1].This=MainMenu;MainMenu[2].MenuCount=4;MainMenu[2].DisplayString=&Menu_word[2][0];MainMenu[2].subs=NULL;MainMenu[2].Local_x=5;MainMenu[2].Local_y=16;MainMenu[2].ChildrenMenu=ChildMenu3;MainMenu[2].ParentMenu=NULL;MainMenu[2].This=MainMenu;MainMenu[3].MenuCount=4;MainMenu[3].DisplayString=&Menu_word[3][0];MainMenu[3].subs=NULL;MainMenu[3].Local_x=5;MainMenu[3].Local_y=16;MainMenu[3].ChildrenMenu=ChildMenu4;MainMenu[3].ParentMenu=NULL;MainMenu[3].This=MainMenu;}void ChildMenu1_init(void){ChildMenu1[0].MenuCount=3;ChildMenu1[0].DisplayString=&Menu_word[0][0];ChildMenu1[0].subs=NULL;ChildMenu1[0].Local_x=43;ChildMenu1[0].Local_y=0;ChildMenu1[0].ChildrenMenu=&SubChildMenu1;ChildMenu1[0].ParentMenu=MainMenu;ChildMenu1[0].This=ChildMenu1;ChildMenu1[1].MenuCount=3;ChildMenu1[1].DisplayString=&Menu_word[1][0];ChildMenu1[1].subs=NULL;ChildMenu1[1].Local_x=43;ChildMenu1[1].Local_y=0;ChildMenu1[1].ChildrenMenu=&SubChildMenu2;ChildMenu1[1].ParentMenu=MainMenu;ChildMenu1[1].This=ChildMenu1;ChildMenu1[2].MenuCount=3;ChildMenu1[2].DisplayString=&Menu_word[2][0];ChildMenu1[2].subs=NULL;ChildMenu1[2].Local_x=43;ChildMenu1[2].Local_y=0;ChildMenu1[2].ChildrenMenu=&SubChildMenu3;ChildMenu1[2].ParentMenu=MainMenu;ChildMenu1[2].This=ChildMenu1;}void ChildMenu2_init(void){ChildMenu2[0].MenuCount=3;ChildMenu2[0].DisplayString=&Menu_word[0][0];ChildMenu2[0].subs=NULL;ChildMenu2[0].Local_x=43;ChildMenu2[0].Local_y=16;ChildMenu2[0].ChildrenMenu=&SubChildMenu1;ChildMenu2[0].ParentMenu=MainMenu;ChildMenu2[0].This=ChildMenu2;ChildMenu2[1].MenuCount=3;ChildMenu2[1].DisplayString=&Menu_word[1][0];ChildMenu2[1].subs=NULL;ChildMenu2[1].Local_x=43;ChildMenu2[1].Local_y=16;ChildMenu2[1].ChildrenMenu=&SubChildMenu2;ChildMenu2[1].ParentMenu=MainMenu;ChildMenu2[1].This=ChildMenu2;ChildMenu2[2].MenuCount=3;ChildMenu2[2].DisplayString=&Menu_word[2][0];ChildMenu2[2].subs=NULL;ChildMenu2[2].Local_x=43;ChildMenu2[2].Local_y=16;ChildMenu2[2].ChildrenMenu=&SubChildMenu3;ChildMenu2[2].ParentMenu=MainMenu;ChildMenu2[2].This=ChildMenu2;}void ChildMenu3_init(void){ChildMenu3[0].MenuCount=3;ChildMenu3[0].DisplayString=&Menu_word[0][0];ChildMenu3[0].subs=NULL;ChildMenu3[0].Local_x=43;ChildMenu3[0].Local_y=0;ChildMenu3[0].ChildrenMenu=&SubChildMenu1;ChildMenu3[0].ParentMenu=MainMenu;ChildMenu3[0].This=ChildMenu3;ChildMenu3[1].MenuCount=3;ChildMenu3[1].DisplayString=&Menu_word[1][0];ChildMenu3[1].subs=NULL;ChildMenu3[1].Local_x=43;ChildMenu3[1].Local_y=0;ChildMenu3[1].ChildrenMenu=&SubChildMenu2;ChildMenu3[1].ParentMenu=MainMenu;ChildMenu3[1].This=ChildMenu3;ChildMenu3[2].MenuCount=3;ChildMenu3[2].DisplayString=&Menu_word[2][0];ChildMenu3[2].subs=NULL;ChildMenu3[2].Local_x=43;ChildMenu3[2].Local_y=0;ChildMenu3[2].ChildrenMenu=&SubChildMenu3;ChildMenu3[2].ParentMenu=MainMenu;ChildMenu3[2].This=ChildMenu3;}void ChildMenu4_init(void){ChildMenu4[0].MenuCount=3;ChildMenu4[0].DisplayString=&Menu_word[0][0];ChildMenu4[0].subs=NULL;ChildMenu4[0].Local_x=43;ChildMenu4[0].Local_y=16;ChildMenu4[0].ChildrenMenu=&SubChildMenu1;ChildMenu4[0].ParentMenu=MainMenu;ChildMenu4[0].This=ChildMenu4;ChildMenu4[1].MenuCount=3;ChildMenu4[1].DisplayString=&Menu_word[1][0];ChildMenu4[1].subs=NULL;ChildMenu4[1].Local_x=43;ChildMenu4[1].Local_y=16;ChildMenu4[1].ChildrenMenu=&SubChildMenu2;ChildMenu4[1].ParentMenu=MainMenu;ChildMenu4[1].This=ChildMenu4;ChildMenu4[2].MenuCount=3;ChildMenu4[2].DisplayString=&Menu_word[2][0];ChildMenu4[2].subs=NULL;ChildMenu4[2].Local_x=43;ChildMenu4[2].Local_y=16;ChildMenu4[2].ChildrenMenu=&SubChildMenu3;ChildMenu4[2].ParentMenu=MainMenu;ChildMenu4[2].This=ChildMenu4;}void SubChildMenu1_init(void){SubChildMenu1.MenuCount=1;SubChildMenu1.DisplayString=&Menu_word[0][0];SubChildMenu1.subs=NULL;SubChildMenu1.Local_x=79;SubChildMenu1.Local_y=0;SubChildMenu1.ChildrenMenu=NULL;SubChildMenu1.ParentMenu=ChildMenu1;SubChildMenu1.This=&SubChildMenu1;SubChildMenu2.MenuCount=1;SubChildMenu2.DisplayString=&Menu_word[0][0];SubChildMenu2.subs=NULL;SubChildMenu2.Local_x=79;SubChildMenu2.Local_y=16;SubChildMenu2.ChildrenMenu=NULL;SubChildMenu2.ParentMenu=ChildMenu1;SubChildMenu2.This=&SubChildMenu2;SubChildMenu3.MenuCount=1;SubChildMenu3.DisplayString=&Menu_word[0][0];SubChildMenu3.subs=NULL;SubChildMenu3.Local_x=79;SubChildMenu3.Local_y=32;SubChildMenu3.ChildrenMenu=NULL;SubChildMenu3.ParentMenu=ChildMenu1;SubChildMenu3.This=&SubChildMenu3;}/*****************键盘*******************/ UINT8 keyscan(void){UINT8 i,j,temp;PTFD|=0x07; //PTF xxxx x111for(i=0;i<3;i++){PTFD &= ~(1<<i);temp=0x04;for(j=0;j<3;j++){if(!(PTGD&temp)){delay(10);if(!(PTGD&temp)){return (i*3+j+1);}}temp <<= 1;}PTFD|=0x07;}return 0;}/****************读状态*******************/ UINT8 _12864_rd_stat(void){UINT8 volatile temp;PTBDD=0X00;D_RS=0;D_RW=1;D_E=1;delay(1);temp=PTBD;delay(1);D_E=0;return temp;}/*******************读数据******************/UINT8 _12864_rd_data(UINT8 page,UINT8 colum,UINT8 D_LorR) {UINT8 volatile data;_12864_busycheck();if(D_LorR){D_L=0;D_R=1;}else{D_L=1;D_R=0;}_12864_wr_cmd(0xb8+page);_12864_wr_cmd(0x40+colum);PTBDD=0X00;D_RS=1;D_RW=1;D_E=1;delay(5);data=PTBD;delay(10);D_E=0;return data;}/*******************忙检测**********************/void _12864_busycheck(void){PTBDD=0x00;D_RS=0;D_RW=1;D_E=1;while(_12864_rd_stat()==0x80);D_E=0;}/****************写指令********************/void _12864_wr_cmd(UINT8 cmd){_12864_busycheck();PTBDD=0XFF;D_RS=0;D_RW=0;D_E=1;delay(10);PTBD=cmd;delay(10);D_E=0;}/*****************写数据*****************/void _12864_wr_data(UINT8 page,UINT8 colum,UINT8 D_LorR,UINT8 data) {_12864_busycheck();if(D_LorR){D_L=0;D_R=1;}else{D_L=1;D_R=0;}_12864_wr_cmd(0xb8+page);_12864_wr_cmd(0x40+colum);PTBDD=0XFF;D_RS=1;D_RW=0;D_E=1;delay(5);PTBD=data;delay(10);D_E=0;}void _12864_wr_data_notclear(UINT8 page,UINT8 colum,UINT8 D_LorR,UINT8 data) {UINT8 temp;_12864_busycheck();if(D_LorR){D_L=0;D_R=1;}else{D_L=1;D_R=0;}(void)_12864_rd_data(page,colum,D_LorR);temp=_12864_rd_data(page,colum,D_LorR);data=data|temp;_12864_wr_cmd(0xb8+page);_12864_wr_cmd(0x40+colum);PTBDD=0XFF;D_RS=1;D_RW=0;D_E=1;delay(5);PTBD=data;delay(10);D_E=0;}/*****************清屏********************/void _12864_clear_lcdall(void){UINT8 i,j;for(i=0;i<8;i++){for(j=0;j<64;j++){_12864_wr_data(i,j,0,0x00);_12864_wr_data(i,j,1,0x00);}}}void _12864_clear_lcd(UINT8 xbegin,UINT8 ybegin,UINT8 xend,UINT8 yend) {UINT8 x,y,pages,pagee,D_LorR,temp;if(xbegin>=xend){temp=xbegin;xbegin=xend;xend=temp;}if(ybegin>=yend){temp=ybegin;ybegin=yend;yend=temp;}if(xend>127)xend=127;if(yend>63)yend=63;pages=ybegin>>3;pagee=yend>>3;for(x=pages;x<=pagee;x++){for(y=xbegin;y<=xend;y++){if(y>63){D_LorR=1;_12864_wr_data(x,y-64,D_LorR,0x00);}else{D_LorR=0;_12864_wr_data(x,y,D_LorR,0x00);}}}}/*****************清除一个点******************/void _12864_clear_dot(UINT8 x,UINT8 y){UINT8 page,row;UINT8 data;if(x<=63){page=y/8;row=y%8;(void)_12864_rd_data(page,x,0);data=_12864_rd_data(page,x,0);data=data&(~(0x01<<row));_12864_wr_data(page,x,0,data);}else{page=y/8;row=y%8;(void)_12864_rd_data(page,x-64,1);data=_12864_rd_data(page,x-64,1);data=data&(~(0x01<<row));_12864_wr_data(page,x-64,1,data);}}/**********************画一个点*********************/ void _12864_write_dot(UINT8 x,UINT8 y){UINT8 page,row;volatile UINT8 data;if(x<=63){page=y/8;row=y%8;delay(5);(void)_12864_rd_data(page,x,0);data=_12864_rd_data(page,x,0);data=data|(0x01<<row);_12864_wr_data(page,x,0,data);}else{page=y/8;row=y%8;delay(5);(void)_12864_rd_data(page,x-64,1);data=_12864_rd_data(page,x-64,1);data=data|(0x01<<row);_12864_wr_data(page,x-64,1,data);}}/*****************初始化*********************/void _12864_init(void){D_REST=1;D_L=1;D_R=1;_12864_wr_cmd(0xc0);_12864_wr_cmd(0x3f);}/******************io封装*****************/void io_keyscan(void){PTGPE=0x1c;PTFDD=0xff;}void io_12864(void){PTBDD=0XFF;PTCDD_PTCDD0=1;PTCDD_PTCDD1=1;PTCDD_PTCDD2=1;PTCDD_PTCDD4=1;PTFDD_PTFDD4=1;PTFDD_PTFDD5=1;}/******************画线函数****************/void _12864_glibline(UINT8 x1,UINT8 y1,UINT8 x2,UINT8 y2) {int dx,dy,sub;dx=x2-x1;dy=y2-y1;if(dx>=0){if(dy>=0){if(dx>=dy)//1/8{sub=2*dy-dx;while(x1<x2){_12864_write_dot(x1,y1);if(sub>0){y1+=1;sub+=(dy-dx)*2;}else{sub+=2*dy;}x1+=1;}}else //2/8{sub=2*dx-dy;while(y1<y2){_12864_write_dot(x1,y1);if(sub>0){x1+=1;sub+=(dx-dy)*2;}else{sub+=2*dx;}y1+=1;}}}else{dy=-dy;if(dx>=dy){sub=2*dy-dx;while(x1<x2){_12864_write_dot(x1,y1);if(sub>0){y1-=1;sub+=(dy-dx)*2;}else{sub+=2*dy;}x1+=1;}}else{sub=2*dx-dy;while(y1>y2){_12864_write_dot(x1,y1);if(sub>0){x1+=1;sub+=(dx-dy)*2;}else{sub+=dx*2;}y1-=1;}}}}else{dx=-dx;if(dy>0){if(dx>dy){sub=2*dy-dx;while(x1>x2){_12864_write_dot(x1,y1);if(sub>0){y1+=1;sub+=(dy-dx)*2;}else{sub+=2*dy;}x1-=1;}}else{sub=2*dx-dy;while(y1<y2){_12864_write_dot(x1,y1);if(sub>0){x1-=1;sub+=(dx-dy)*2;}else{sub+=dx*2;}y1+=1;}}}else{dy=-dy;if(dx>dy){sub=2*dy-dx;while(x1>x2){_12864_write_dot(x1,y1);if(sub>0){y1-=1;sub+=(dy-dx)*2;}else{sub+=dy*2;}}}else{sub=2*dx-dy;while(y1>y2){_12864_write_dot(x1,y1);if(sub>0){x1-=1;sub+=(dx-dy)*2;}else{sub+=2*dx;}y1-=1;}}}}}/********************写16*16点阵的汉字函数*********************///参数page汉字开始的页数,colum汉字开始的列数//字符代码编号//CorN是否是带擦除的写入方式1为不擦除,0为擦除void write_word_16_16(UINT8 page,UINT8 colum,UINT8 word_num,UINT8 CorN,UINT8 filltype){UINT8 i,D_LorR,colum_temp;if(filltype==FillType_Fill){if(CorN==1){for(i=0;i<8;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data_notclear(page,colum_temp,D_LorR,zimo[word_num][i]);}for(i=16;i<24;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data_notclear(page+1,colum_temp,D_LorR,zimo[word_num][i]);}for(i=8;i<16;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data_notclear(page,colum_temp,D_LorR,zimo[word_num][i]);}for(i=24;i<32;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data_notclear(page+1,colum_temp,D_LorR,zimo[word_num][i]);}}else{for(i=0;i<8;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data(page,colum_temp,D_LorR,zimo[word_num][i]);}for(i=16;i<24;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data(page+1,colum_temp,D_LorR,zimo[word_num][i]);}for(i=8;i<16;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data(page,colum_temp,D_LorR,zimo[word_num][i]);}for(i=24;i<32;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data(page+1,colum_temp,D_LorR,zimo[word_num][i]);}}}else{if(CorN==1){for(i=0;i<8;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data_notclear(page,colum_temp,D_LorR,~zimo[word_num][i]);}for(i=16;i<24;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data_notclear(page+1,colum_temp,D_LorR,~zimo[word_num][i]);}for(i=8;i<16;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data_notclear(page,colum_temp,D_LorR,~zimo[word_num][i]);}for(i=24;i<32;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data_notclear(page+1,colum_temp,D_LorR,~zimo[word_num][i]);}}else{for(i=0;i<8;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data(page,colum_temp,D_LorR,~zimo[word_num][i]);}for(i=16;i<24;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data(page+1,colum_temp,D_LorR,~zimo[word_num][i]);}for(i=8;i<16;i++){D_LorR=0;colum_temp=colum+i;if((colum+i)>63){colum_temp=colum-64+i;D_LorR=1;}_12864_wr_data(page,colum_temp,D_LorR,~zimo[word_num][i]);}for(i=24;i<32;i++){D_LorR=0;colum_temp=colum+i-16;if((colum+i-16)>63){colum_temp=colum-64+i-16;D_LorR=1;}_12864_wr_data(page+1,colum_temp,D_LorR,~zimo[word_num][i]);}}}}/********************编写16*16点阵字符串显示函数******************************/ //参数string是字符编号数组的首地址void write_string_16_16(UINT8 page,UINT8 colum,UINT8 *string,UINT8 number,UINT8 CorN,UINT8 filltype){UINT8 i;for(i=0;i<number;i++){write_word_16_16(page,colum+(i<<4),*(string+i),CorN,filltype);}}/****************************************************************************** ******//*************************填充函数****************************/void fill_rectangle(UINT8 xbegin,UINT8 ybegin,UINT8 xend,UINT8 yend){UINT8 x;for(x=xbegin;x<=xend;x++){_12864_glibline(x,ybegin,x,yend);}}/*******************菜单函数*******************///功能:编译出一个菜单可视化图形界面//具有填充,反相功能//struct MenuItem//{ //菜单结构// UINT8 MenuCount;//菜单项所在层的菜单项数目// UINT8 *DisplayString;//显示的名称// void (*subs)(void);//所指向的功能函数// struct MenuItem *ChildrenMenu;//所指向的子菜单// struct MenuItem *ParentMenu;//所指向的父菜单//};void MenuBox(UINT8 xbegin,UINT8 ybegin)/*Xbegin 方框左上角横坐标Ybegin 方框左上角纵坐标Xend 方框右下角横坐标Yend 方框右下角纵坐标*/{UINT8 page,num,xend,yend;struct MenuItem *Menu_point_temp;Menu_point_temp=Menu_point;xend=xbegin+16*3;yend=ybegin+Menu_point->MenuCount*16-1;if(yend>63)yend=63;Menu_point=Menu_point->This;//指向本项菜单的首位地址page=ybegin>>3;_12864_clear_lcd(xbegin,ybegin,xend,yend);_12864_glibline(xbegin,ybegin,xend,ybegin);_12864_glibline(xbegin,ybegin,xbegin,yend);_12864_glibline(xbegin,yend,xend,yend);_12864_glibline(xend,ybegin,xend,yend);for(num=0;num<Menu_point->MenuCount;num++){if(page>7)continue;if(Menu_point==Menu_point_temp){if(key_number!=0){write_string_16_16(page,xbegin,Menu_point->DisplayString,3,1,0);}else{write_string_16_16(page,xbegin,Menu_point->DisplayString,3,1,1);}}else{write_string_16_16(page,xbegin,Menu_point->DisplayString,3,1,1);}Menu_point++;page+=2;}Menu_point=Menu_point_temp;}/******************主函数*******************/void main(void){PLL_init(16);io_12864();io_keyscan();_12864_init();_12864_clear_lcdall();MainMenu_init();ChildMenu1_init();ChildMenu2_init();ChildMenu3_init();ChildMenu4_init();SubChildMenu1_init();/* _12864_glibline(0,0,0,63);_12864_glibline(0,0,63,0);_12864_glibline(63,0,63,63);_12864_glibline(0,63,63,63);write_word_16_16(1,60,1,0,0); */MenuBox(Menu_point->Local_x,Menu_point->Local_y);// MenuBox(65,16);// write_string_16_16(0,40,Menu_point->DisplayString,3,0,0);// write_string_16_16(2,40,&Menu_word[0][0],3,0,0);for(;;){switch(keyscan()){case 1: //DOWM下翻页key_number++;if(key_number>Menu_point->MenuCount){key_number=1;Menu_point=Menu_point->This;}Menu_point=Menu_point->This+key_number-1;MenuBox(Menu_point->Local_x,Menu_point->Local_y);break;case 6:key_number--;if(key_number==0){key_number=Menu_point->MenuCount;}Menu_point=Menu_point->This+key_number-1;MenuBox(Menu_point->Local_x,Menu_point->Local_y);break;case 5://enterif(Menu_point->ChildrenMenu!=NULL){Menu_point=Menu_point->ChildrenMenu;key_number_store=key_number;key_number=0;MenuBox(Menu_point->Local_x,Menu_point->Local_y);}else if(Menu_point->subs!=NULL){(*Menu_point->subs)();}break;case 9://escif(Menu_point->ParentMenu!=NULL){_12864_clear_lcd(Menu_point->Local_x,Menu_point->Local_y,(Menu_point->Local_x+16*3),(Menu_point->Local_y+16*Menu_point->MenuCount-1));key_number=key_number_store;Menu_point=Menu_point->ParentMenu+key_number-1;MenuBox(Menu_point->Local_x,Menu_point->Local_y);}break;}}}.。
LCD12864 多级菜单
首先定义一个菜单结构typedef struct menu//定义一个菜单{u8 range_from,range_to; //当前显示的项开始及结束序号 u8 itemCount;//项目总数u8 selected;//当前选择项u8 *menuItems[17];//菜单项目struct menu **subMenus;//子菜单struct menu *parent;//上级菜单,如果是顶级则为null void (**func)();//选择相应项按确定键后执行的函数}Menu;Menu MainMenu = { //定义主菜单0,3,4,0,//默认显示0-3项,总共4项,当前选择第0项 {"设置1 \x10","设置2 \x10","输入指令发送","查询\x10"}};Menu searchMenu = {//查询菜单0,3,6,0,{"记帐记录明细","未采集记录数","设备机号","本机IP地址","记录空间大小","软件版本"}};Menu *currentMenu;//当前的菜单用于显示菜单项void display(u8 line) //显示菜单项并设置选中的项反白{int i;line = 3-(currentMenu->range_to-line);Lcd_Fill(0x00);for(i = 0;i<4;i++){Lcd_Disp(i+1,0,currentMenu->menuItems[i+currentMenu->range_from]);}highlight(0,line,8,255);//反白显示指定行}void func(void){printf("hello\r\n");}初始化菜单:void initMenu(){MainMenu.subMenus = malloc(sizeof(&MainMenu)*4);MainMenu.subMenus[0] = NULL;//第1到3项没有子菜单置null,选择后程序会调用func中相应项中的函数MainMenu.subMenus[1] = NULL;MainMenu.subMenus[2] = NULL;MainMenu.subMenus[3] = &searchMenu;//第四项查询有子菜单MainMenu.func = malloc(sizeof(&func)*4);MainMenu.func[0] = NULL;MainMenu.func[1] = NULL;MainMenu.func[2] = &func;//当选择了并按了确定,会执行func函数MainMenu.func[3] = NULL;MainMenu.parent = NULL;//表示是顶级菜单searchMenu.subMenus = malloc(sizeof(&searchMenu)*6);searchMenu.subMenus[0] = searchMenu.subMenus[1] = searchMenu.subMenus[2] = searchMenu.subMenus[3] = searchMenu.subMenus[4] = searchMenu.subMenus[5] = NULL;searchMenu.func = malloc(sizeof(&printf)*6);searchMenu.func[0] = searchMenu.func[2] = searchMenu.func[2] = searchMenu.func[3] = searchMenu.func[4] = searchMenu.func[5] = NULL;searchMenu.parent = &MainMenu;//上一级菜单是MainMenu.进入查询子菜单后按返回键,将会显示这个菜单项currentMenu = &MainMenu;}mainint main(void){delay_init();uart_init(9600);Lcd_Init();KEY_Init();initMenu();display(currentMenu->selected);while(1){key = KEY_Scan();if(key == 0){delay_ms(10);continue;}printf("key %d is press\r\n",key);switch(key){case 12://向上if(currentMenu->selected == 0)//到了第一项break;else{currentMenu->selected--;if(currentMenu->selected < currentMenu->range_from)//更新显示的区域 {currentMenu->range_from = currentMenu->selected;currentMenu->range_to = currentMenu->range_from+3;}display(currentMenu->selected);break;}case 8://向下if(currentMenu->selected == currentMenu->itemCount-1)break;else{currentMenu->selected++;if(currentMenu->selected>currentMenu->range_to){currentMenu->range_to = currentMenu->selected;currentMenu->range_from = currentMenu->range_to-3;}display(currentMenu->selected);break;}case 4://Enter键{if(currentMenu->subMenus[currentMenu->selected] !=NULL){currentMenu = currentMenu->subMenus[currentMenu->selected]; display(0);}else{if(currentMenu->func[currentMenu->selected] != NULL){currentMenu->func[currentMenu->selected]();//执行相应的函数 display(currentMenu->selected);//返回后恢复原来的菜单状态}}break;}case 3://返回键{if(currentMenu->parent!=NULL)//父菜单不为空,将显示父菜单{currentMenu = currentMenu->parent;display(currentMenu->selected);}break;}default:break;}delay_ms(10);}}void Lcd_Disp(unsigned char x,unsigned char y,unsigned char *s) {Lcd_Write_Cmd(0x30); //进入标准模式LCD_Set_XY(x,y);while (*s){Lcd_Write_Data(*s);s++;}Lcd_Write_Cmd(0x36); //返回图形模式}void highlight(uchar x,uchar y,uchar width,u8 mode) //反白,X值为0-7,Y值为0-3,width为行反白格数{uchar i,j,flag=0x00;if(y>1){flag=0x08;y=y-2;}Lcd_Write_Cmd(0x34); //写数据时,关闭图形显示,且打开扩展指令集for(i=0;i<16;i++){Lcd_Write_Cmd(0x80+(y<<4)+i);Lcd_Write_Cmd(0x80+flag+x);for(j=0;j<width;j++){Lcd_Write_Data(mode);Lcd_Write_Data(mode);}}Lcd_Write_Cmd(0x36); //写完数据,开图形显示}。
LCD12864多级菜单课程设计
LCD12864多级菜单课程设计一、课程目标知识目标:1. 理解LCD12864液晶显示屏的基本工作原理和接口技术。
2. 掌握多级菜单的设计方法,包括菜单结构、界面布局及跳转逻辑。
3. 学会编写程序代码实现LCD12864多级菜单的显示与操作。
技能目标:1. 能够运用所学知识设计出结构清晰、界面友好的多级菜单界面。
2. 熟练使用相关编程语言和开发工具,完成程序编写和调试。
3. 培养学生的动手操作能力和团队协作能力,提高问题解决能力。
情感态度价值观目标:1. 培养学生对电子技术和编程的兴趣,激发学习热情。
2. 培养学生严谨、细心的学习态度,养成良好的编程习惯。
3. 增强学生的创新意识,鼓励学生敢于尝试、勇于实践。
分析课程性质、学生特点和教学要求,本课程目标旨在帮助学生在掌握LCD12864多级菜单设计的基础上,提高实际操作能力,培养学生的创新思维和团队协作精神。
通过本课程的学习,使学生能够在实际项目中运用所学知识,为我国电子信息产业的发展做出贡献。
同时,注重培养学生的情感态度价值观,使学生在学习过程中形成积极向上的人生态度。
二、教学内容1. LCD12864液晶显示屏原理介绍:包括显示原理、接口技术、指令集等基本知识。
- 教材章节:第三章第二节- 内容列举:LCD12864工作原理、接口类型、指令功能。
2. 多级菜单设计方法:- 教材章节:第五章- 内容列举:菜单结构设计、界面布局、跳转逻辑、操作流程。
3. 编程实现LCD12864多级菜单:- 教材章节:第六章- 内容列举:编程环境搭建、代码编写、程序调试、功能实现。
4. 实例分析与操作:- 教材章节:第七章- 内容列举:典型多级菜单实例、操作方法、优化技巧。
5. 动手实践与团队协作:- 教材章节:第八章- 内容列举:实践任务分配、协作流程、成果展示。
根据课程目标,教学内容分为五个部分,确保学生系统掌握LCD12864多级菜单设计的相关知识。
教学大纲明确指出各部分内容的安排和进度,以及教材对应的章节和具体内容。
LCD12864 多级菜单
searchMenu.subMenus = malloc(sizeof(&searchMenu)*6); searchMenu.subMenus[0] = searchMenu.subMenus[1] = searchMenu.subMenus[2] = searchMenu.subMenus[3] = searchMenu.subMenus[4] = searchMenu.subMenus[5] = NULL; searchMenu.func = malloc(sizeof(&printf)*6); searchMenu.func[0] = searchMenu.func[2] = searchMenu.func[2] = searchMenu.func[3] = searchMenu.func[4] = searchMenu.func[5] = NULL; searchMenu.parent = &MainMenu;//上一级菜单是MainMenu.进入查询 子菜单后按返回键,将会显示这个菜单 项
Lcd_Write_Data(*s); s++; } Lcd_Write_Cmd(0x36); //返回图形模式 }
void highlight(uchar x,uchar y,uchar width,u8 mode)
//反
白,X值为0-7,Y值为0-3,width为行反白格数
{
uchar i,j,flag=0x00;
break; } case 8://向下 if(currentMenu->selected == currentMenu->itemCount-1) break; else { currentMenu->selected++; if(currentMenu->selected>currentMenu->range_to) {
液晶12864分级菜单思想
液晶12864 分级菜单编程思想喜欢单片机的人,想必对液晶12864应该不会陌生。
对于单片机来说,如果用于显示,12864是个不错的选择,编程既简单,而资源消耗又符合单片机的使用要求,是理想的选择。
下面就我做有关单片机的一点心得分享一下我在编写液晶12864的一点思想,希望能个喜欢这些东西的同志们有所启发。
以下是我项目中分级菜单的源文件:(一个12864的五级菜单)/**************************************分级菜单***************************************/#include"STC15F2K.H"#include"KEY.H"#include"LCD.H"#include"LIST.H"#include"YINGY.H"#include"HCSR04.H"#include"HONGW.H"#include "PCF8563.H"/**************************************变量定义***************************************/uchar wendT=30; //温度上限bit fg=0;uchar key = 0; //键值获得//uchar keyq = 0; //子菜单项标志uchar flagk = 0;uint flag = 0; //菜单标志bit flag_ms = 0; //智能模式和安全模式标志位uchar timeflag=0; //时间设置标志位uchar shi=7,fen=0,miao=0; //闹钟标志位uchar ms_h1=6,ms_m1=0,ms_h2=22,ms_m2=0; //时间标志位bit bing_nao = 0; //闹钟开启标志位uchar code l1[] = "年";uchar code l2[] = "月";uchar code l3[] = " ";uchar code l4[] = "时";uchar code l5[] = "分";uchar code l6[] = " ";uchar code l7[] = ":";uchar code l8[] = "为";/**************************************函数声明**************************************/void fenjcd();void yiji_menu();void erji_menu();void sanjims_menu();void sanjiqt_menu();void xiug_time(); //时间修改void ms_back();void qt_back();void siji_nao();void nao_time();void ms_time();void wenduT();/**************************************总菜单**************************************/void fenjcd(){yiji_menu();erji_menu();sanjims_menu();sanjiqt_menu();xiug_time(); //时间修改ms_back();qt_back();siji_nao();nao_time();ms_time();}/**************************************一级菜单**************************************/void yiji_menu(){key=getKey();if(flag==0){if(key==1||IR_code==0x45) //进入功能选择页面{write_com(0x01);write(0x81,lis2);write(0x90,lis21);write(0x88,lis23);write(0x98,lis25);write_com(0x0c);flagk = 1;flag = 1;key = 0;IR_code=0;}}if(flag == 1){if(key == 1||IR_code==0x45) //返回正常页面{write_com(0x01);write(0x82,lis1);write(0x90,lcd_date_H);write(0x88,lisk1);write(0x98,lcd_T);write(0x9c,lcd_H);write_com(0x0c);flag = 0;flagk = 0;key = 0;IR_code=0;}}}/**************************************二级菜单**************************************/void erji_menu(){if(flag==1){if(key==2||IR_code==0x40) //菜单选项加1{keyq++; //功能设置选择中if(keyq == 1){write(0x90,lis20);write(0x88,lis24);write(0x98,lis25);}else if(keyq == 2){write(0x90,lis20);write(0x88,lis23);write(0x98,lis26);}IR_code=0;if(keyq>=3) keyq = 0;if(keyq == 0){write(0x98,lis25);write(0x90,lis21);write(0x88,lis23);}}if(key==4||IR_code==0x47) //进入选中页面{if(keyq == 0) //进入时间设置页面{flag = 20; //时间设置编码write_com(0x01);write(0x82,lis30);write(0x90,lisk0);write(0x89,lisk1);write_num(0x90,year_1);//LCD显示write_num(0x91,time.year);write_num(0x93,time.month);write_num(0x95,time.day);write_num(0x89,time.hour);write_num(0x8b,time.minute);write_num(0x8d,time.second);keyq = 0;key=0;IR_code=0;}if(keyq == 1) //进入模式设置页面{flag=21;write_com(0x01);write(0x82,lis31);write(0x90,lis311);write(0x88,lis312);keyq = 0;key=0;IR_code=0;}if(keyq == 2) //进入其它设置页面{flag=22;write_com(0x01);write(0x82,lis32);write(0x90,lis321);write(0x88,lis322);write(0x98,lis324);keyq = 0;key=0;IR_code=0;}}}}/**************************************三级菜单**************************************///三级模式void sanjims_menu(){if(flag == 21) //模式选择{if(key==2||IR_code==0x40) //菜单选项加1{keyq++; //模式选择中if(keyq == 1){write(0x90,lis310);write(0x88,lis313);}IR_code=0;if(keyq>=2) keyq = 0;if(keyq == 0){write(0x88,lis312);write(0x90,lis311);}}if(key==4||IR_code==0x47) //进入选中页面{if(keyq == 0) //开启智能模式{flag = 210; //智能模式编码flag_ms = 0;write_com(0x01);write(0x82,lis1);write(0x90,lis430);write(0x88,lis432);write(0x99,lis433);keyq = 0;key = 0;IR_code=0;}if(keyq == 1) //开启安全模式{flag = 211; //安全模式编码flag_ms = 1;write_com(0x01);write(0x82,lis1);write(0x88,lis431);keyq = 0;key=0;IR_code=0;}}}if(flag == 21) //返回功能设置页面{if(key == 1||IR_code==0x45){write_com(0x01);write(0x81,lis2);write(0x90,lis21);write(0x88,lis23);write(0x98,lis25);write_com(0x0c);flag = 1;key=0;IR_code=0;}}}//三级其它void sanjiqt_menu(){if(flag == 22) //其它设置选择{if(key==2||IR_code==0x40) //菜单选项加1{keyq++; //其它设置项选择中if(keyq == 1){write(0x90,lis320);write(0x88,lis323);write(0x98,lis324);}else if(keyq == 2){write(0x90,lis320);write(0x88,lis322);write(0x98,lis325);}IR_code=0;if(keyq>=3) keyq = 0;if(keyq == 0){write(0x98,lis324);write(0x90,lis321);write(0x88,lis322);}}if(key==4||IR_code==0x47) //进入选中页面{if(keyq == 0) //进入闹钟设置{flag = 220; //闹钟设置编码write_com(0x01);write(0x82,lis40);write(0x90,lis401);write(0x88,lis402);keyq = 0;key = 0;IR_code=0;}if(keyq == 1) //进入温度上限设置**{flag = 221; //温度上限设置write_com(0x01);write(0x81,lis41);write(0x88,lis410);write_com(0x0c);keyq = 0;key = 0;IR_code=0;}if(keyq == 2) //进入遥控器解码{flag = 222; //遥控解码编码write_com(0x01);write(0x82,lis42);write(0x90,lis420);write(0x98,lis421);keyq = 0;key=0;IR_code=0;}}}if(flag == 22) //返回功能设置页面{if(key == 1||IR_code==0x45){write_com(0x01);write(0x81,lis2);write(0x90,lis21);write(0x88,lis23);write(0x98,lis25);write_com(0x0c);flag = 1;key=0;IR_code=0;}}}/*******************************************时间设置********************************************/void xiug_time(){if(flag==20){if(key == 1||IR_code==0x45){if(timeflag == 0) //秒{write_com(0x0f);write_num(0x8d,time.second);write(0x8c,l5);}else if(timeflag == 1) //分{write_com(0x0f);write_num(0x8b,time.minute);write(0x8a,l4);}else if(timeflag == 2) //时{write_com(0x0f);write_num(0x89,time.hour);write(0x88,l6);}else if(timeflag == 3) //天{write_com(0x0f);write_num(0x95,time.day);write(0x94,l2);}else if(timeflag == 4) //月{write_com(0x0f);write_num(0x93,time.month);write(0x92,l1);}else if(timeflag == 5) //年{write_com(0x0f);write_num(0x91,time.year);write_num(0x90,year_1);}timeflag++;IR_code=0;if(timeflag>6)timeflag = 0;}if(key == 3||IR_code==0x15) //数值加1{if(timeflag == 1) //秒{time.second++;if(time.second>=60)time.second=0;write_num(0x8d,time.second);write(0x8c,l5);}else if(timeflag == 2) //分{time.minute++;if(time.minute>=60)time.minute=0;write_num(0x8b,time.minute);write(0x8a,l4);}else if(timeflag == 3) //时{time.hour++;if(time.hour>=24) time.hour=0;write_num(0x89,time.hour);write(0x88,l6);}else if(timeflag == 4) //天{time.day++;if(time.day>=31)time.day=1;write_num(0x95,time.day);write(0x94,l2);}else if(timeflag == 5) //月{time.month++;if(time.month>=13)time.month=1;write_num(0x93,time.month);write(0x92,l1);}else if(timeflag == 6) //年{time.year++;write_num(0x91,time.year);write_num(0x90,year_1);}IR_code=0;}if(key==4||IR_code==0x47) //返回正常显示页面{settime();write_com(0x01);write(0x82,lis1);write(0x90,lisk0);write(0x88,lisk1);write(0x98,lcd_T);write(0x9c,lcd_H);time_lcd();write_com(0x0c);flag = 0;flagk=0;timeflag = 0;key = 0;IR_code=0;}}}/******************************************* 模式选定返回设置********************************************/ void ms_back(){if(flag==211&&(key==1||IR_code==0x45)){write_com(0x01);write(0x82,lis31);write(0x90,lis311);write(0x88,lis312);write_com(0x0c);flag=21;key=0;IR_code=0;}}/********************************************** 温度上限设置**********************************************/ void wenduT(){if(flag==221){if(fg==0){write_num(0x8d,wendT);write(0x8c,l8);write_com(0x0c);}if(key == 3||IR_code==0x15) //数值加1{fg=1;wendT++;write_com(0x0f);write_num(0x8d,wendT);write(0x8c,l8);key=0;IR_code=0;}if(IR_code==0x07) //数值加1{fg=1;wendT--;write_com(0x0f);write_num(0x8d,wendT);write(0x8c,l8);key=0;IR_code=0;}}if(key==4||IR_code==0x47) //返回正常显示页面{write_com(0x01);write(0x82,lis1);write(0x90,lisk0);write(0x88,lisk1);write(0x98,lcd_T);write(0x9c,lcd_H);time_lcd();write_com(0x0c);flag = 0;flagk = 0;timeflag = 0;key = 0;fg=0;IR_code=0;} IR_code=0;}/*******************************************其它选项选定返回设置********************************************/void qt_back(){if((flag==221||flag==222||flag==220)&&(key==1||IR_code==0x45)){write_com(0x01);write(0x82,lis32);write(0x90,lis321);write(0x88,lis322);write(0x98,lis324);write_com(0x0c);flag=22;key=0;IR_code=0;}}/*******************************************闹钟选择设定********************************************/void siji_nao(){if(flag == 220) //闹钟选择{if(key==2||IR_code==0x40) //菜单选项加1{keyq++; //闹钟选择中if(keyq == 1){write(0x90,lis400);write(0x88,lis403);}IR_code=0;if(keyq>=2) keyq = 0;if(keyq == 0){write(0x88,lis402);write(0x90,lis401);}}if(key==4||IR_code==0x47) //进入选中页面{if(keyq == 0) //关闭闹钟{flag = 2200;bing_nao =0;write_com(0x01);write(0x82,lis40);write(0x88,lis405);keyq = 0;key = 0;IR_code=0;}if(keyq == 1) //开并设置闹钟{flag = 2201;bing_nao =1;write_com(0x01);write(0x82,lis40);write(0x90,lis404);write(0x89,lisk1);write_num(0x89,shi);write_num(0x8b,fen);write_num(0x8d,miao);keyq = 0;key=0;IR_code=0;}}}if(flag == 2200) //返回闹钟选择页面{if(key == 1||IR_code==0x45){write_com(0x01);write(0x82,lis40);write(0x90,lis401);write(0x88,lis402);write_com(0x0c);flag = 220;key=0;IR_code=0;}}}/*******************************************闹钟定时********************************************/void nao_time(){if(flag==2201){{if(key == 1||IR_code==0x45){if(timeflag == 0) //秒{write_com(0x0f);write_num(0x8d,miao);write(0x8c,l5);}else if(timeflag == 1) //分{write_com(0x0f);write_num(0x8b,fen);write(0x8a,l4);}else if(timeflag == 2) //时{write_com(0x0f);write_num(0x89,shi);write(0x88,l6);}timeflag++;IR_code=0;if(timeflag>3)timeflag = 0;}if(key == 3||IR_code==0x15) //数值加1{if(timeflag == 1) //秒{miao++;if(miao>=60)miao=0;write_num(0x8d,miao);write(0x8c,l5);}else if(timeflag == 2) //分{fen++;if(fen>=60)fen=0;write_num(0x8b,fen);write(0x8a,l4);}else if(timeflag == 3) //时{shi++;if(shi>=24)shi=0;write_num(0x89,shi);write(0x88,l6);}IR_code=0;}if(key==4||IR_code==0x47) //返回正常显示页面{write_com(0x01);write(0x82,lis1);write(0x90,lisk0);write(0x88,lisk1);write(0x98,lcd_T);write(0x9c,lcd_H);time_lcd();write_com(0x0c);flag = 0;flagk = 0;timeflag = 0;key = 0;IR_code=0;}}}}/*******************************************智能模式时间定时********************************************/void ms_time(){if(flag==210){{if(key == 1||IR_code==0x45){if(timeflag == 0) //分2{write_com(0x0f);write_num(0x9d,ms_m2);write(0x9c,l4);}else if(timeflag == 1) //时2{write_com(0x0f);write_num(0x9b,ms_h2);write(0x9a,l3);}else if(timeflag == 2) //分1{write_com(0x0f);write_num(0x8d,ms_m1);write(0x8c,l4);}else if(timeflag == 3) //时1{write_com(0x0f);write_num(0x8b,ms_h1);write(0x8a,l7);}timeflag++;IR_code=0;if(timeflag>4)timeflag = 0;}if(key == 3||IR_code==0x15) //数值加1 {if(timeflag == 1) //分2{ms_m2++;if(ms_m2>=60)ms_m2=0;write_num(0x9d,ms_m2);write(0x9c,l4);}else if(timeflag == 2) //时2{ms_h2++;if(ms_h2>=24)ms_h2=0;write_num(0x9b,ms_h2);write(0x9a,l3);}else if(timeflag == 3) //分1{ms_m1++;if(ms_m1>=60)ms_m1=0;write_num(0x8d,ms_m1);write(0x8c,l4);}else if(timeflag == 4) //时1{ms_h1++;if(ms_h1>=24)ms_h1=0;write_num(0x8b,ms_h1);write(0x8a,l7);}IR_code=0;}if(key==4||IR_code==0x47) //返回正常显示页面{write_com(0x01);write(0x82,lis1);write(0x90,lisk0);write(0x88,lisk1);write(0x98,lcd_T);write(0x9c,lcd_H);time_lcd();write_com(0x0c);flag = 0;flagk=0;timeflag = 0;key = 0;IR_code=0;}}}}。
LCD12864菜单说明1-5
笔记本:
我的工作日志
创建时间:
2015/5/11 22:04更新时间:2015/5/18 17:26
URL :file:///LCD12864说明1/5
主界面:显示1,2,3三个挤出头的温度和热床的温度,FR 设置打印速度的倍数
按下旋转按钮以后,进入下面的菜单:
Info Screen:进入主界面
Prepare:执行移动各轴等操作
Control:设置挤出、热床、速度等参数。
Print from SD:从SD 卡打印
Change SD card:更换SD 卡以后,进行加载
点击Prepare 菜单以后,进入下面的菜单:
Disable steppers 失能步进电机,上电状态下电机不再在保持状态。
Auto Home:xyz 三轴回零
Preheat PLA:加热挤出头,预热PLA ,此功能一般不用,直接在Control 里面加热挤出Nozzle 。
Preheat ABS:加热挤出头,预热ABS ,此功能一般不用,直接在Control 里面加热挤出Nozzle Cooldown:冷却挤出头和热床
Move axis:移动各轴
点击Prepare 菜单以后,进入下面的菜单:
Disable steppers 失能步进电机,上电状态下电机不再在保持状态。
Auto Home:xyz 三轴回零
Preheat PLA:加热挤出头,预热PLA ,此功能一般不用,直接在Control 里面加热挤出Nozzle 。
Preheat ABS:加热挤出头,预热ABS ,此功能一般不用,直接在Control 里面加热挤出Nozzle Cooldown:冷却挤出头和热床
Move axis:移动各轴。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include "lcd12864.h" #include "delay.h" #define uchar unsigned char sbit keydown=P0^0; sbit keyenter=P0^1; sbit keyup=P0^2; uchar func_index=0; void (*current_operation_index)(); typedef struct { uchar current; uchar up;//向上翻索引号 uchar down;//向下翻索引号 uchar enter;//确认索引号 void (*current_operation)(); } key_table; key_table code table[30]= { {0,3,1,4,(*fun1)},// 第一层,显示【清华大学】 、北京大学、重庆三峡学院、返回 {1,0,2,8,(*fun2)},// 第一层,显示清华大学、 【北京大学】 、重庆三峡学院、返回 {2,1,3,12,(*fun3)},// 第一层,显示清华大学、北京大学、 【重庆三峡学院】 、返回 {3,2,0,25,(*fun4)},// 第一层,显示清华大学、北京大学、重庆三峡学院、 【返回】 {4,7,5,16,(*fun5)},// 第二层,清华大学层下显示【地点】 、创建时间、简介、返回 {5,4,6,17,(*fun6)},// 第二层,清华大学层下显示地点、 【创建时间】 、简介、返回 {6,5,7,18,(*fun7)}, // 第二层,清华大学层下显示地点、创建时间、 【简介】 、返回 {7,6,4,0,(*fun8)},// 第二层,清华大学层下显示地点、创建时间、简介、 【返回】 {8,11,9,19,(*fun9)},// 第二层,北京大学层下显示【历史】 、政治、简介、返回 {9,8,10,20,(*fun10)},// 第二层,北京大学层下显示历史、 【政治】 、简介、返回 {10,9,11,21,(*fun11)}, // 第二层,北京大学层下显示历史、政治、 【简介】 、返回 {11,10,8,1,(*fun12)},// 第二层,北京大学层下显示历史、政治、简介、 【返回】 {12,15,13,22,(*fun13)},// 第二层,重庆三峡学院层下显示【简介】 、最佳院系、最佳实验室、返回 {13,12,14,23,(*fun14)}, // 第二层,重庆三峡学院层下显示简介、 【最佳院系】 、最佳实验室、返回 {14,13,15,24,(*fun15)}, // 第二层,重庆三峡学院层下显示简介、最佳院系、 【最佳实验室】 、返回 {15,14,12,2,(*fun16)}, // 第二层,重庆三峡学院层下显示简介、最佳院系、最佳实验室、 【返回】 {16,16,16,4,(*fun17)}, // 第三层,清华大学地点层 {17,17,17,5,(*fun18)}, // 第三层,清华大学创时间层 {18,18,18,6,(*fun19)}, // 第三层,清华大学简介层 {19,19,19,8,(*fun20)}, // 第三层,北京大学历史层 {20,20,20,9,(*fun21)}, // 第三层,北京大学政治层 {21,21,21,10,(*fun22)}, // 第三层,北京大学简介层 {22,22,22,12,(*fun23)}, // 第三层,重庆三峡学院简介层 {23,23,23,13,(*fun24)}, // 第三层,重庆三峡学院最佳院系层 {24,24,24,14,(*fun25)}, // 第三层,重庆三峡学院最佳实验室层 {25,25,25,0,(*fun26)}, // 第0层 }; void main() { init_lcd(); //初始化 LCD 模块 while(1) { /*******************find index****************************/ if((keyup==0)||(keydown==0)||(keyenter==0)) { delay(10);//消抖 if(keyup==0) { func_index=table[func_index].up; while(!keyup);//松手检测 } if(keydown==0) { func_index=table[func_index].down; while(!keydown); } // 向下翻 // 向上翻
if(keyenter==0) { func_index=table[func_index].enter; while(!keyenter); } init_lcd(); { current_operation_index=table[func_index].current_operation; (*current_operation_index)();// 执行当前操作函数 } } // 确认
12864多级菜单设计
看到网上有个视频,用的是12864做的菜单,很花哨,自己也心痒痒想做一个,收集了 很多关于这方面的东西,但是都是五花八门,没有一个完整的可以共大家参考的程序,所 以决定写偏文章供大家参考,希望读者下去自己优化,改进。有什么不足之处还请多多包涵。好了,废话不多说,直接进入正题吧。 1、首先定义一个机构体如下 typedef struct { uchar current; //当前状态 uchar up;//上键 uchar down;//下键 uchar enter;//确认键 void (*current_operation)(); //当前状态应该执行的功能操作 } key_table;