基于51单片机的红外控制LCD1602显示系统
摘要:该设计由硬件和软件共同组成。首先是硬件部分,该系统的最终实现选用的单片处理器(AT89S52)、21键遥控器、LCD1602 显示、单片机的串行接口电路。因此应充分了解单片机,包括存储空间,并行口,串行口,串行通信,定时器等,21键遥控器键值编码和LCD1602 的显示,本系统是以单片机为控制器的核心,本系统主要由红外接收电路、接收红外信号处理电路、单片机系统及控制电路组成。工作时,可以将21键遥控器上按键出来的键值编码等信息送到单片机,单片机根据这些信息通过控制电路把要显示的内容由LCD1602显示屏显示出21键每个键对应的内容,从而实现红外控制LCD1602显示。
一、 设计目的
课程名称:《单片机原理及应用——c51编程+proteus仿真》 张毅刚 著, 学后感:熟悉单片机的人都知道,要学好单片机可不是一件容易的事,倒不是因为单片机很难学,而是很难找到一本专为单片机入门者而编写的教材。翻一下身边的单片机教材,都好像是为已经懂单片机的人而写的,一般先介绍单片机的硬件结构和指令系统,再是系统扩展和外围器件,顺便讲一些应用设计(随便说一下,很多书中的电路设计已经过时,并且有些程序还是错误的)。如果按照此种学习方法,想进行产品开发,就必须先把所有的知识全部掌握了才可以进行实际应用。学习使用单片机只能靠循序渐进的积累,下面就本人学习单片机的过程和经验做简要介绍。
- 编程环境和仿真环境
编程环境:keil 4
仿真环境:proteus 8
二、 设计要求
根据仿真图搭建硬件电路,硬件主要由AT89S52单片机最小系统一个,LCD1602显示屏一个,21键红外遥控器一个,HS0038红外接收头一个,470欧姆电阻一个,电源线一根,母对母杜邦线若干,排阻一个,11.0592晶振一个,贴片电容两个,47μ电容一个。根据proteus仿真上能够实现的电路搭建硬件电路
在keil4中编写代码,根据红外的编结码,和LCD1602显示屏初始化查忙,写命令,写数据,来编写代码,了解红外编结码是编写代码重要的过程。
三、 设计内容
- 最小系统电路
- AT89S52芯片
图一、AT89S52芯片
AT89S52 是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编AT89S52-24PU程Flash存储器。使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 AT89S52具有以下标准功能: 8k字节Flash,256字节RAM, 32 位I/O 口线,看门狗定时器,2 个数据指针,三个16 位 定时器/计数器,一个6向量2级中断结构,全双工串行口, 片内晶振及时钟电路。另外,AT89S52 可降至0Hz 静态逻 辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM、定时器/计数AT89S52引脚图 DIP封装器、串口、中断继续工 作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
晶振是晶体振荡器的简称,在电气上它可以等效成一个电容和一个电阻并联再串联一个电容的二端网络。电工学上这个网络有两个谐振点,以频率的高低分,其中较低的频率是串联谐振;较高的频率是并联谐振。由于晶体自身的特性致使这两个频率的距离相当的接近,在这个极窄的频率范围内,晶振等效为一个电感,所以只要晶振的两端并联上合适的电容它就会组成并联谐振电路。这个并联谐振电路加到一个负反馈电路中就可以构成正弦波振荡电路,由于晶振等效为电感的频率范围很窄,所以即使其他元件的参数变化很大,这个振荡器的频率也不会有很大的变化
图二、晶振电路
红外接收电路一体化的红外接收装置将遥控信号的接收、放大、检波、整形集于一身,并且输出可以让单片机识别的TTL 信号,这样大大简化了接收电路的复杂程度和电路的设计工作,方便使用。在本系统中我们采用红外一体化接收头HS0038,HS0038 黑色环氧树脂封装,不受日光、荧光灯等光源干扰,内附磁屏蔽,功耗低,灵敏度高。在用小功率发射管发射信号情况下,其接收距离可达35m。它能与TTL、COMS 电路兼容。HS0038 为直立侧面收光型。它接收红外信号频率为38 kHz,周期约26 μs,同时能对信号进行放大、检波、整形,得到TTL 电平的编码信号。三个管脚分别是地、+5 V 电源、解调信号输出端。 红外一体化接收头的测试可以利用图4 所示的电路进行,在HS0038 的电源端与信号输出端之间接上一只二极管及一只发光二极管后,再配上规定的工作电源(为+5V),当手拿遥
控器对着接收头按任意键时,发光二极管会闪烁,说明红外接收头和遥控器工作都正常;如果发光二极管不闪烁发光,说明红外接收头和遥控器至少有一个损坏。
图三、hs0038实物与原件介绍图
图四、左边为遥控器的编结码,右边为遥控器的按键
主要功能就是显示红外遥控传给单片机的数据,也可以算作红外对单片机的控制
1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之
间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母"A"的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母"A"。
图五、lcd1602proteus图和实物图
图六、lcd1602指令码
四、 结论、总结与建议
仿真图结果:
图七、protues仿真效果
实物图结果:
图八、实物效果图
图八、实物电路搭建图
流程图:
此次试验的关键是键盘的编结码,与对红外信号发射原理的理解,接收装置对红外信号发射脉冲次数的记录是关键。发射管的频率一般为38kHz。通过这次课设实验,让我懂得的实验要踏实,一步一个脚印的弄,不管遇到什么问题都不能亲言放弃,这样你必定会成功,还会在失败的路上学习到好多好多经验,这是一笔宝贵的财富
五、主要参考文献
[1]唐正. Proteus在单片机教学中的应用[D].华中科技大学,2008.(参考文献字体字号要求,中文:宋体;英文与数字:Times New Roman,五号)
[2]刁宇清. 基于PROTEUS的单片机仿真实验系统研究及应用[D].西安工业大学,2011
[3]赵月静,陈继荣,张永弟. 单片机原理及应用课程创新实践教学改革[J]. 实验技术与管理,2013,01:176-179.
[4]周灵彬,张靖武. PROTEUS的单片机教学与应用仿真[J]. 单片机与嵌入式系统应用,2008,01:76-79.
六、 附录
源代码
- #include<reg52.h> //包含头文件,一般情况不需要改动
- intrins.h>
- sbit IR=P3^2; //红外接口标志
- sbit LCD_RS=P1^0;
- sbit LCD_RW=P1^1;
- sbit LCD_EN=P2^5;
-
- #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
- Unsigned char code dofly_DuanMa[10]={0X30,0X31,0X32,0X33,0X34,0X35,0X36,0X37,0X38,0X39};// 显示段码值0~9
- unsigned char irtime;//红外用全局变量
-
- bit irpro_ok,irok;
- unsigned char IRcord[4];
- unsigned char irdata[33];
-
- void Ir_work(void);
- void Ircordpro(void);
-
- void delay(unsigned char t) {
- unsigned char i;
- while(t--)
- for(i = 200; i > 0; i--);
- }
- void LCD_write_instruction(unsigned char LCD_instruction) { //写指令到LCD
- LCD_RS = 0;
- LCD_RW = 0;
- DataPort = LCD_instruction;
- LCD_EN = 1;
- _nop_();
- LCD_EN = 0;
- delay(1);
- }
-
- void LCD_write_data(unsigned char LCD_data) { //输出一个字节数据到LCD
- LCD_RS = 1;
- LCD_RW = 0;
- DataPort = LCD_data;
- LCD_EN = 1;
- _nop_();
- LCD_EN = 0;
- delay(1);
- }
-
- void LCD_set_position(unsigned char x) { //LCD光标定位到x处
- LCD_write_instruction(0x80|x);
- }
-
- void LCD_printc(unsigned char lcd_data) { //输出一个字符到LCD
- LCD_write_data(lcd_data);
- }
- void LCD_prints(unsigned char *lcd_string) { //输出一个字符串到 LCD
- unsigned char i = 0;
- while(lcd_string[i] != 0x00) {
- LCD_write_data(lcd_string[i]);
- i++;
- }
- }
-
- void LCD_initial(void) {
- LCD_RW = 0; //初始化 LCD
- LCD_write_instruction(0x38);
- LCD_write_instruction(0x0c);
- LCD_write_instruction(0x06);
- LCD_write_instruction(0x01);
- }
-
- void tim0_isr (void) interrupt 1 using 1
- {
- irtime++; //用于计数2个下降沿之间的时间
- }
-
- void EX0_ISR (void) interrupt 0 //外部中断0服务函数
- {
- static unsigned char i; //接收红外信号处理
- static bit startflag; //是否开始处理标志位
-
- if(startflag)
- {
- if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
- i=0;
- irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
- irtime=0;
- i++;
- if(i==33)
- {
- irok=1;
- i=0;
- }
- }
- else
- {
- irtime=0;
- startflag=1;
- }
-
- }
- void TIM0init(void)//定时器0初始化
- {
-
- TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
- TH0=0x00; //重载值
- TL0=0x00; //初始化值
- ET0=1; //开中断
- TR0=1;
- }
- void EX0init(void)
- {
- IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
- EX0 = 1; //使能外部中断
- EA = 1; //开总中断
- }
-
- void Ir_work(void)//红外键值散转程序
- {
- switch(IRcord[2])//判断第三个数码值
- {
- case 0x0C:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0x49); //LCD换行显示
- LCD_printc(dofly_DuanMa[1]);
- break;//1 显示相应的按键值
- case 0x18:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[2]);break;//2
- case 0x5E:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[3]);break;//3
- case 0x08:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[4]);break;//4
- case 0x1C:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[5]);break;//5
- case 0x5A:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[6]);break;//6
- case 0x42:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[7]);break;//7
- case 0x52:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[8]);break;//8
- case 0x4A:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[9]);break;//9
- case 0x45:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("WuLian");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Class 152");
- break;//9
- case 0x46:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("NAME: TangFang");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("ID:220153297 ");
- break;//9
- case 0x47:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("NAME:CaiChaoyong");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("ID:220153273 ");
- break;//9
- case 0x44:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("teacher: zzy");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("class:DanPianJi ");
- break;//9
- case 0x40:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("key null");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("key null");
- break;//9
- case 0x43:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("key null 1");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("key null 1");
- break;//9
- case 0x07:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("key null -");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("key null -");
- break;//9
- case 0x15:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("key null +");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("key null +");
- break;//9
- case 0x09:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("key null EQ");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("key null EQ");
- break;//9
- case 0x16:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints(" NOW: On");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("Number: ");
- LCD_set_position(0xC8); //LCD换行显示
- LCD_printc('0');
- LCD_set_position(0xC9); //LCD换行显示
- LCD_printc(dofly_DuanMa[0]);break;//7
- case 0x19:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("usb sd");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("usb sd");
- break;//9
- case 0x0d:
- LCD_write_instruction(0x01);
- LCD_set_position(0x00);
- LCD_prints("back!!!");
- LCD_set_position(0x40); //LCD换行显示
- LCD_prints("back!!!");
- break;//9
- default:break;
- }
-
- irpro_ok=0;//处理完成标志
-
- }
- void Ircordpro(void)//红外码值处理函数
- {
- unsigned char i, j, k;
- unsigned char cord,value;
-
- k=1;
- for(i=0;i<4;i++) //处理4个字节
- {
- for(j=1;j<=8;j++) //处理1个字节8位
- {
- cord=irdata[k];
- if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
- value|=0x80;
- if(j<8)
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
分工合作
唐*(220153297):1.仿真图搭建
2.硬件材料选购
3.课设实验报告的撰写,硬件资料的查找及整理,课程设计资料的查找分析与整理
4、对搭建出来,和搭档写好的代码进行通读和理解,分析不足,共同改进不足
蔡*(220153273):1.流程图的先驱
2.实物图连接,代码编写
3.实物图调试分析
4.录制讲解整个课设制作的流程