空调遥控器设计.docx
《空调遥控器设计.docx》由会员分享,可在线阅读,更多相关《空调遥控器设计.docx(25页珍藏版)》请在冰豆网上搜索。
空调遥控器设计
设计题目:
空调遥控器可以用来庙宇空调机的控制温度(室内温度)、工作状态(常态、除湿、通风)、风扇风速(强、弱、中)以及定时时间(空调工作多少小时自动开机或延时多少小时自动开机)。
使用者在遥控器上庙宇预期的空调机工作状态、控制温度及延时时间后,这些参数即送至空调机,空调机按要求开始工作。
该遥控器的要求如下:
(1)数字显示器:
第一组显示时间,发送前指示设定的延时时间:
0——9h,发送后指示剩余的延时时间;第二组显示控制温度15——35℃。
(2)工作状态指示器3组:
第一组指示设定的工作状态:
常态、除湿、通风;第二组指示延时开机、延时停机、取消等三种延时要求;第三组指示空调机的三种工作速度:
慢速、中速、高速。
(3)红外发射管,发射的调制频率是45KHz。
(4)3节5号电供电。
(5)面板示意图见图。
设计以AT89C51为核心的遥控器电路,并编写相关的系统软件(汇编、C51程序均可)。
设计思路:
数字显示器使用LCD1602显示时间和温度值,其中时间的切换利用AT89C51内部自带的定时器0,定时初值为3cb0,定时器工作模式为’01’16位定时器,工作状态利用LED灯的亮灭来指示,其中LED亮代表相对应的工作模式被选中,各种工作状态的切换使用8个独立按键来实现,分别位‘工作状态设定键’、‘延时状态设定键’、‘风速选定键’、‘温度+键’、‘温度-键’、‘延时时间位选定键’、‘延时时间设置键’、‘发送键’;按下‘发送键’后信息的发送使用串行口的方式发送给上位机并显现出来,当延时时间到启动空调。
具体实现:
经分析将该设计划分为如下4个模块:
按键模块,LED状态显示模块,LCD1602显示模块,双机串口通信模块
按键模块:
仿真原理图:
详细描述:
8个按键的功能如下表:
按键
功能
K1
工作状态设定键(常态、除湿、通风)
K2
延时状态设定键(延时开、延时关、取消)
K3
风速选定键(慢、中、快)
K4
温度设定键(增加+)
K5
温度设定键(减少-)
K6
延时时间位选定键(XXXXXX)
K7
延时时间设置键(默认为循环增加)
K8
发送键
当K1按下时,保持P0高5位状态,按下第一次最后一位置0,倒数第二、三位置1按下第二次时到数第二位置0,倒数第一、三位置1,按下第三次时倒数第三位置0,倒数第一、二位置1,依次循环,代码实现:
P0=(states1[i]&(P0|0x07));
当K2按下时,保持P0倒数第1、2、3位和正数第1、2、3状态按下第一次时倒数第一位亮表示延时开,按下第二次时倒数第五位亮表示延时关,按下第三次时倒数第3、4位皆灭表示取消延时,依次循环,代码实现:
P0=(states2[j]&(P0|0x18));
当K3按下时,保持P0低5位不变,按下最高两位置1,第三位置0,表示慢速,按下第二次时第二位置0,第一、三位置1,表示中速,按下第三次时第一位置0,第一、二位置1,依次循环,代码实现:
P0=(states3[k]&(P0|0xe0));
LED状态显示模块:
仿真原理图:
详细描述:
8个按键的功能如下表:
LED
状态指示
D1
正常
D2
除湿
D3
通风
D4
延时开(如果D4/D5两灯全灭则取消延时)
D5
延时关
D6
慢
D7
中
D8
高
LCD1602显示模块:
仿真原理图:
详细描述:
LCD1602一共可以显示16x2个字符,其中数据线为8位分别接AT89C51的P2端口的8个管脚,控制线为RS、RW、E分别接P3.3,P3.4,P3.5管脚,仿真电路中排阻是必要的它的功能是电阻作为有功原件串联在电路中能消除振荡,目的是得到更好的EMC性能。
主要子函数包括:
(详细代码见附录源程序LCD部分)
voidinitLCM(void);//LCD初始化子程序
voidDisplayListChar(unsignedcharX,unsignedcharY,unsignedchar*DData);//显示指定坐标的一串字符子函数
voidDisplayOneChar(ucharX,ucharY,ucharDData);//显示单个字符
双机串口通信功能:
仿真原理图:
详细描述:
利用串口查询的方式实现两台单片机之间通信的功能:
单片机1(模拟遥控器)作为发送机其P3.0/RXD、P3.1/TXD分别接从机(模拟空调)的P3.1/TXD、P3.0/RXD引脚。
发送机和接收机串口采用方式1,8位UART,波特率可变,其中T1的采用方式3(8位自填装模式),计数初值为f4f4,因此串口的波特率为2400bits
主要实现代码如下:
(详细代码见附录源代码部分:
)
主机发送:
while(++counter<=8)
{SBUF=sender[counter-1];
while(TI==0);
TI=0;
while(RI==0);
RI=0;
}
从机接收:
counter++;
RI=0;//接受中断标志清零,可以接收新的数据
receive=SBUF;//开始接收新的数据
ADDRR[counter-1]=receive;//把接受的数据存入字符串数组ADDRR中
delay_LCM(100);
delay_LCM(100);
SBUF=ADDRR[counter-1];//由单片机2向单片机1发送数据
while(TI==0);//循环等待直到发送数据完毕
TI=0;
设计过程中遇到的问题及解决过程:
问题1、LCD1602不能够显示
最终解决方案:
经查阅相关资料与书上LCD1602电路连线图相对照发现未接排阻。
仿真电路中排阻是必要的它的功能是电阻作为有功原件串联在电路中能消除振荡,目的是得到更好的EMC性能。
经加入排阻后能够正常显示。
问题2、通过串口线两片单片机不能正常的通信
最终解决方案:
原因是在主机中由于我既用到了定时器来作为计时中断,有用到了定时器为串口提供波提率,我误把定时器0来为串口提供波特率,定时器1来为做计时时钟,后查阅书籍在《单片机原理及控制技术》P161、L17中提到方式1和方式3的波特率“与定时器T1的溢出率有关。
”也就是说串口通信方式1的波特率不能由定时器0来提供后经改变两定时器的功能后串口通信正常。
问题3、编译程序代码时总会出现“ERRORL107:
ADDRESSSPACEOVERFLOW”.
最终解决方案:
AT89C51有三种存储器模式:
“SMALL模式,COMPACT模式,LARGE模式。
不同的存储模式对变量的默认的存储器类型不一样。
”程序在编译时默认为小编译模式,此时数据的存储容量为128B当我定义的数据变量所占据的地址空间超过128B时,编译器就会报错。
我首先尝试将编译器的模式设置为CMOPACT模式,但发现编译器虽无报错但仿真的结果并不是我所期望的结果,最终我在SMALL模式下,将我所定义的数据变量尽量缩减,例如用10个字符“0123456789”来表示21个温度数据,这样的缺点是给软件的编写带来了较大的复杂度,优点是可以节省内存空间,最终将所用字节缩减至97远小于128B,编译无错误,且仿真成功。
课程设计收获与心得:
本次课程设计从审题、模块的划分、各个模块的实现和各个模块之间的连接均为自己独立完成,无抄袭借鉴他人的现象发生,通过本次课程设计自己几乎将单片机教材又细致的看了一遍尤其是中断一章看了不下3遍其中串口一节更是把每个字都仔细研究一番,最终完成了课程设计题目的要求。
通过此次课程设计增强了我对学习单片机的信心,也激发了我对单片机设计的热情。
成为我大学生涯中的一次难忘的经历,我会在今后生活中更加深入学习单片机知识,争取设计出更多自己喜欢的又实用价值的作品。
附录:
软件仿真图:
源代码:
第一部分:
LCD显示文件
#include
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineBUSY0x80
#defineDATAPORTP2
sbitLCM_RS=P3^3;
sbitLCM_RW=P3^4;
sbitLCM_EN=P3^5;
voiddelay_LCM(uint);
voidlcd_wait(void);
voidWriteCommandLCM(ucharWCLCM,ucharBusyC);
voidWriteDataLCM(ucharWDLCM);
voidDisplayOneChar(ucharX,ucharY,ucharDData);
voidinitLCM(void);
voidDisplayListChar(ucharX,ucharY,unsignedchar*DData);
voiddelay_LCM(uintk)
{
uinti,j;
for(i=0;i{
for(j=0;j<60;j++)
{;}
}
}
voidWriteCommandLCM(ucharWCLCM,ucharBusyC)
{
if(BusyC)lcd_wait();
DATAPORT=WCLCM;
LCM_RS=0;
LCM_RW=0;
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
voidWriteDataLCM(ucharWDLCM)
{
lcd_wait();
DATAPORT=WDLCM;
LCM_RS=1;
LCM_RW=0;
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
voidlcd_wait(void)
{
DATAPORT=0xff;
LCM_EN=1;
LCM_RS=0;
LCM_RW=1;
_nop_();
while(DATAPORT&BUSY)
{LCM_EN=0;
_nop_();
_nop_();
LCM_EN=1;
_nop_();
_nop_();
}
LCM_EN=0;
}
voidinitLCM()
{
DATAPORT=0;
delay_LCM(15);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,1);
WriteCommandLCM(0x08,1);
WriteCommandLCM(0x01,1);
WriteCommandLCM(0x06,1);
WriteCommandLCM(0x0c,1);
}
voidDisplayOneChar(ucharX,ucharY,ucharDData)
{