《基于单片机的简易酒店点菜系统.docx》由会员分享,可在线阅读,更多相关《基于单片机的简易酒店点菜系统.docx(29页珍藏版)》请在三一办公上搜索。
1、第1章.设计总体思路与系统框图1.1设计总体思路 根据设计要求我们可知酒店点菜终端系统由控制模块,液晶显示模块,键盘模块组成。控制模块有80C51和80C52可供选择,但考虑到程序占用的空间比较大,所以我选择了80C52单片机。对于液晶显示模块我们这里采用的是LCD12864(64行128列组成)。对于键盘模块由于只要用到三个键,故我们可以用三个按键分别来实现上移,确定,下移功能。再加以简单的辅助电路和C语言程序就可以构成简单的酒店点菜终端系统,在此,我们采用proteus软件进行仿真。1.2系统框图按照设计思路,系统框图如下:AT89C52AMPIRE128X64键盘控制模块图一 系统框图1
2、.3系统显示框图将各模块在Proteus仿真软件中连接好后,点击“运行”,结合键盘上的“上移”、“确定”、“下移”键可以在LCD上看到开机画面、各系菜单以及其子菜单。显示框图如图二。开始 显示作者名称字样返回湘菜粤菜苏菜浙菜闽菜川菜鲁菜各菜系子菜单显示 点菜成功!图二 显示框图第2章.单元函数模块设计2.1 AT89C52单片机控制模块 2.1.1AT89C52介绍 AT89C52是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准
3、MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,AT89C52单片机在电子行业中有着广泛的应用。AT89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2个读写口线,AT89C52可以按照常规方法进行编程,但不可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。2.1.2AT89C52管脚图 AT89C52管脚图如下: 图三 AT89C52管脚图2.1.3头文件注解 在用c语言编程是往往第一行就是reg52.h或者其他的自定义
4、头文件,系统编程将要使用到两个头文件,分别是reg52.h和code.h。下面就reg52.h头文件作简单解释,code.h头文件的编写主要是为了存放菜单中所要使用的汉字的字模,以便主程序调用,程序清单将在附录中给出。程序的第一行是一个“文件包含”处理,所谓“文件包含”是指一个文件将另外一个文件的内容全部包含进来。程序中包含REG51.h头文件的目的是为了要使用P1 (还有其他更多的符号)这个符号,即通知C 编译器,程序中所写的P1 是指80C51 单片机的P1 端口而不是其它变量。2.2键盘控制模块2.2.1键盘功能本系统采用的是三个BUTTON分别实现“上移”,“确定”,“下移”三个功能,
5、有了这三个键我们就能实现菜单,子菜单,功能的进入和返回。图四 键盘控制模块2.2.2键盘控制程序 程序中我定义了P3.0,P3.4,P3.7分别为“上移”,“确定”,“下移”三个功能按键。按键引脚的一端接单片机,一端接低电平,当单片机接收到某个端口的低电平是就表示拿个按键已经按下。否则表示按键没按下,为了更好的实现按键的准确性我加入了消抖程序与松手检测程序。按键判断程序如下:void keyscan() /按键判断 if(qd=0) delay(5); if(qd=0)while(!qd); n=1; if(sy=0) delay(5); if(sy=0)while(!sy); m+;if(m
6、7)m=0; if(xy=0) delay(5); if(xy=0)while(!xy); m-;if(m=255)m=7; 2.3 LCD显示模块2.3.1 LCD12864功能介绍 AMPIRE128x64管脚一共18个(见图五),CS1左半屏片选端,CS2右半屏片选端;VCC、GND就是电源、接地引脚,V0液晶显示驱动电压,RS数据指令选择信号,H为数据,L为指令,也叫D/I,即DATA和INSTRUCTIONS这两个单词的缩写。R/W读写选择信号。E为LCD使能端,R/W为L时,E信号下降沿锁存DB7-DB0;R/W为H时,E为H,DDRAM数据读到DB7-DB0,如果只写不读的话可以
7、接地处理。DB0-DB7数据传输端口。RST为复位信号,-VOUT为液晶显示驱动电压。2.3.2 LCD12864指令说明 AMPIRE128x64共有7个指令,下面分别加以说明:显示开关 :0x3e 关;0x3f开(R/W=0,RS=0)。显示起始行:0xc0+i , i取值0至63(R/W=0,RS=0)。设置DDRAM页地址(X地址):0xb8+i,i取值0至7(R/W=0,RS=0),设置Y地址:0x40+i,i取值0至63(R/W=0,RS=0)。写数据:将数据线上的数据DB7-DB0写到DDRAM 。Y地址指针自动加1(R/W=0,RS=1)。读数据:将DDRAM中的数据读入1数据
8、线DB7-DB0 。Y地址指针自动加1(R/W=1,RS=1)。指令表如表一所示 表一 LCD12864指令表2.3.3 LCD驱动程序驱动程序如下:void CheckState()uchar dat;/状态信息(判断是否忙) RS=0; / 数据指令选择,D/I(RS)=“L” ,表示 DB7DB0 为显示指令数据 RW=1; /R/W=“H” ,E=“H”数据被读到DB7DB0 doDATA=0x00; EN=1;/EN下降沿dat=DATA; EN=0; dat=0x80 & dat; 仅当第7位为0时才可操作(判别busy信号) while(!(dat=0x00); /*写命令到LC
9、D中*/SendCommandToLCD(uchar com)CheckState();/状态检查,LCD是否忙 RS=0; /向LCD发送命令。RS=0写指令,RS=1写数据 RW=0;/R/W=“L” ,E=“HL”数据被写到 IR 或 DR DATA=com; /com :命令 EN=1;/EN下降沿 EN=0;/*设置页 0xb8是页的首地址*/void Setpage(uchar page)page=0xb8|page; /1011 1xxx 0=page=7 设定页地址-X 0-7,8行为一页64/8=8,共8页 SendCommandToLCD(page); /*设定显示开始行,
10、0xc0是行的首地址*/void SetStartLine(uchar startline) startline=0xc0|startline; /1100 0000 SendCommandToLCD(startline); /设置从哪行开始:0-63,一般从0 行开始显示/*设定列地址-Y 0-63 ,0x40是列的首地址*/void SetColumn(uchar column)column=column &0x3f; /column最大值为64,越出 0=column=63 column= 0x40|column; /01xx xxxx SendCommandToLCD(column);
11、 /*开关显示,0x3f是开显示,0x3e是关显示*/void SetOnOff(uchar onoff) onoff=0x3e|onoff; /0011 111x,onoff只能为0或者1 SendCommandToLCD(onoff);/*写显示数据 */void WriteByte(uchar dat)CheckState();/状态检查,LCD是否忙 RS=1; /RS=0写指令,RS=1写数据 RW=0;/R/W=“L” ,E=“HL”数据被写到 IR 或 DR DATA=dat;/dat:显示数据 EN=1; /EN下降源 EN=0;/*选择屏幕screen: 0-全屏,1-左屏,
12、2-右屏*/void SelectScreen(uchar screen) switch(screen) case 0: cs1=1;/全屏 cs2=1; break; case 1: cs1=1;/左屏 cs2=0; break; case 2: cs1=0;/右屏 cs2=1; break; /*清屏screen: 0-全屏,1-左屏,2-右屏*/void ClearScreen(uchar screen) uchar i,j; SelectScreen(screen); for(i=0;i8;i+) /控制页数0-7,共8页 Setpage(i); for(j=0;j64;j+) /控制
13、列数0-63,共64列 SetColumn(j); WriteByte(0x00); /写点内容,列地址自动加1 void InitLCD() /初始化LCD CheckState(); SelectScreen(0); SetOnOff(0); /关显示 SelectScreen(0); SetOnOff(1); /开显示 SelectScreen(0); ClearScreen(0);/清屏 SetStartLine(0); /开始行:0第3章.系统仿真与结果3.1 开机显示 利用proteus软件仿真,点击运行之后会显示如下的开机画面。 图五 开机显示画面 图中菜单为反白颜色,按下“确定
14、”键后即可进入菜单。3.2 主菜单显示系统开机后,按下“确定”键即可进入主菜单。主菜单显示如下: 图六 主菜单显示3.3 子菜单显示 在子菜单中分别有几道菜供顾客享用,当顾客按下“上移”或“下移”键选中想要的菜系再按下“确定”键就可以进入该菜系,再选择自己想要的菜系按下“确定”键即可点菜成功。子菜单显示如下: 图七 子菜单显示3.4 点菜成功显示当顾客选择到自己想要吃的菜并按下“确定”键后就表示顾客点菜成功。点菜成功显示如下: 图八 点菜成功显示当顾客再次按下“确定”键后返回菜系菜单,并且已经点过的菜会以一个钩表示。如下图: 图九 显示已点菜第4章.总结与体会 短短两周的专业设计结束了,回顾这
15、两周我的努力,我觉得我还是收获蛮大的,通过这两周的专业设计,我对单片机有了更深的认识,对LCD12864有了更深入的了解,单片机其实说简单点就是用软件控制单片机各个脚的电平变化,但是实践中还是挺有难度的,这次专业设计我接到的任务是做一个简易的酒店点菜终端系统,刚开始觉得挺有难度的,主要是我对LCD12864一无所知,但是经过上网查找资料及通过看LCD12864的指导手册终于弄懂了这个液晶显示屏,其实一个看似简单的电路,要把他设计出来就比较困难了,这次设计我用的编程语言是C语言,其实单片机的C语言我通过看网上的视频还是有所了解。所以这次编程还算比较顺利,刚开始我只做了两大的菜系,我想这其中的难点
16、就是怎样进入各个子菜单及其返回以及光标的上下移动,我的方法其实也挺简单,就是将选中的菜系字体取反白显示出来。另一个难点就是键盘扫描了,刚开始我出了点小状况,就是按下确定键后不会进入各个菜单,后来认识思考之后才发现用!n代替就行了。每次按键按下n自动取反,最后一个就是各个菜单的显示比较难了,因为你移动一下就是一个状态,最后我经过仔细的思考觉得用个 switchcase语句一下子就出来了,虽然这样会显得程序比较复杂,但是我还没有想到其他更好的简单办法所以就用了这个。 通过这两周的学习,我学到了很多,毕竟自己也做出了一点东西,蛮有成就感的,其实我也知道这只是冰山一角,要想真正的弄通单片机,今后的学习
17、道路还很漫长,我想我也会深深的记住这次课设给我的经验与教训,在今后的学习中一定要多思考,多实践,那样我才会真正有所成就。最后衷心感谢陈老师在这两周对我的细心指导。附录5.1 仿真电路图5.2 程序清单#include #include #include #define uint unsigned int#define uchar unsigned char#define DATA P0 /LCD12864数据线sbit sy=P30;sbit qd=P34;sbit xy=P37;sbit RS=P20; / 数据指令 选择sbit RW=P21; / 读写 选择sbit EN=P22; /
18、读写使能sbit cs1=P23; / 片选1sbit cs2=P24; / 片选2void menuselect();void keyscan();void lucai();void dccg(uchar b);void lucai2();void chuancai();void sorry();void lucaia();uchar n,m,k;/*状态检查,LCD是否忙*/void CheckState()uchar dat;/状态信息(判断是否忙) RS=0; / 数据指令选择,D/I(RS)=“L” ,表示 DB7DB0 为显示指令数据 RW=1; /R/W=“H” ,E=“H”数据
19、被读到DB7DB0 doDATA=0x00; EN=1;/EN下降沿dat=DATA; EN=0; dat=0x80 & dat; /仅当第7位为0时才可操作(判别busy信号) while(!(dat=0x00); /*写命令到LCD中*/SendCommandToLCD(uchar com)CheckState();/状态检查,LCD是否忙 RS=0; /向LCD发送命令。RS=0写指令,RS=1写数据 RW=0;/R/W=“L” ,E=“HL”数据被写到 IR 或 DR DATA=com; /com :命令 EN=1;/EN下降沿 EN=0;/*设置页 0xb8是页的首地址*/void
20、Setpage(uchar page)page=0xb8|page; /1011 1xxx 0=page=7 设定页地址-X 0-7,8行为一页64/8=8,共8页 SendCommandToLCD(page); /*设定显示开始行,0xc0是行的首地址*/void SetStartLine(uchar startline) startline=0xc0|startline; /1100 0000 SendCommandToLCD(startline); /设置从哪行开始:0-63,一般从0 行开始显示/*设定列地址-Y 0-63 ,0x40是列的首地址*/void SetColumn(uch
21、ar column)column=column &0x3f; /column最大值为64,越出 0=column=63 column= 0x40|column; /01xx xxxx SendCommandToLCD(column); /*开关显示,0x3f是开显示,0x3e是关显示*/void SetOnOff(uchar onoff) onoff=0x3e|onoff; /0011 111x,onoff只能为0或者1 SendCommandToLCD(onoff);/*写显示数据 */void WriteByte(uchar dat)CheckState();/状态检查,LCD是否忙 RS
22、=1; /RS=0写指令,RS=1写数据 RW=0;/R/W=“L” ,E=“HL”数据被写到 IR 或 DR DATA=dat;/dat:显示数据 EN=1; /EN下降源 EN=0;/*选择屏幕screen: 0-全屏,1-左屏,2-右屏*/void SelectScreen(uchar screen) switch(screen) case 0: cs1=1;/全屏 cs2=1; break; case 1: cs1=1;/左屏 cs2=0; break; case 2: cs1=0;/右屏 cs2=1; break; /*清屏screen: 0-全屏,1-左屏,2-右屏*/void C
23、learScreen(uchar screen) uchar i,j; SelectScreen(screen); for(i=0;i8;i+) /控制页数0-7,共8页 Setpage(i); for(j=0;j64;j+) /控制列数0-63,共64列 SetColumn(j); WriteByte(0x00); /写点内容,列地址自动加1 /*延时程序*/void delay(uint z)uint i,j; for(i=0; iz; i+) for(j = 0; j 110; j+);/*初始化LCD*/void InitLCD() CheckState(); SelectScreen
24、(0); SetOnOff(0); /关显示 SelectScreen(0); SetOnOff(1); /开显示 SelectScreen(0); ClearScreen(0);/清屏 SetStartLine(0); /开始行:0/*显示全角汉字*/void Display(uchar ss,uchar page,uchar column,uchar number)int i;/选屏参数,page选页参数,column选列参数,number选第几汉字输出 SelectScreen(ss); column=column&0x3f; Setpage(page);/写上半页 SetColumn(
25、column); /控制列 for(i=0;i16;i+) /控制16列的数据输出 WriteByte(Hzki+32*number); /i+32*number汉字的前16个数据输出 Setpage(page+1); /写下半页 SetColumn(column); /控制列 for(i=0;i16;i+) /控制16列的数据输出 WriteByte(Hzki+32*number+16);/i+32*number+16汉字的后16个数据输出 void Display2(uchar ss,uchar page,uchar column,uchar number)int i;/选屏参数,page
26、选页参数,column选列参数,number选第几汉字输出 SelectScreen(ss); column=column&0x3f; Setpage(page);/写上半页 SetColumn(column); /控制列 for(i=0;i16;i+) /控制16列的数据输出 WriteByte(Hzki+32*number); /i+32*number汉字的前16个数据输出 Setpage(page+1); /写下半页 SetColumn(column); /控制列 for(i=0;i16;i+) /控制16列的数据输出 WriteByte(Hzki+32*number+16);/i+32
27、*number+16汉字的后16个数据输出 void menu()uint i; while(!n) /显示汉字 keyscan(); for(i=0;i2;i+) Display(1,0,0+i*16,i);/*Display(选屏参数(cs1,cs2),page选页参数,column选列参数,number选第几汉字输出)*/Display(1,0,32+i*16,i+2);Display(2,0,64+i*16,i+4);Display(2,0,96+i*16,i+6);Display(1,2,0+i*16,i+8);Display(1,2,32+i*16,i+10);Display(2,
28、2,64+i*16,12+i*5);Display(2,2,96+i*16,17);Display(1,4,0+i*16,17);Display(1,4,32+i*16,17);Display(2,4,64+i*16,17);Display(2,4,96+i*16,17);Display(1,6,0+i*16,i+13);Display(1,6,32+i*16,17);Display(2,6,64+i*16,17);Display(2,6,96+i*16,i+15); delay(5); n=0;menuselect();/*主函数*/void main()InitLCD();/初始12864
29、menu();void menuselect() uint i;ClearScreen(0); while(!n) keyscan(); for(i=0;i7)m=0; if(xy=0) delay(5); if(xy=0)while(!xy);m-;if(m=255)m=7; /*鲁菜*/void lucai() uint i,f;ClearScreen(0); while(!n) keyscan(); for(i=0;i2;i+) switch(m%5)case 0: Display2(1,0,0+i*16,26+i);Display2(1,0,32+i*16,28+i);Display(
30、2,0,64+i*16,17);Display(2,0,96+i*16,40+i);Display(1,2,0+i*16,31+i);Display(1,2,32+i*16,33+i);Display(2,2,64+i*16,17);Display(2,2,96+i*16,39+i*2);Display(1,4,0+i*16,35+i);Display(1,4,32+i*16,37+i);Display(2,4,64+i*16,17);Display(2,4,96+i*16,40+i);Display(1,6,0+i*16,15+i);Display(1,6,32+i*16,17);Displ
31、ay(2,6,64+i*16,17+i*29);Display(2,6,96+i*16,47+i);break;case 1:Display(1,0,0+i*16,26+i);Display(1,0,32+i*16,28+i);Display(2,0,64+i*16,17);Display(2,0,96+i*16,40+i);Display2(1,2,0+i*16,31+i);Display2(1,2,32+i*16,33+i);Display(2,2,64+i*16,17);Display(2,2,96+i*16,39+i*2);Display(1,4,0+i*16,35+i);Display(1,4,32+i*16,37+i);D