设计要求
- 掌握行列式键盘的工作原理及LED动态显示方式下的工作原理;
- 了解18B20单总线温度传感器的工作原理及相关程序的编写;
- 掌握常用的报警输出及功率接口电路的设计;
- 了解设计一个独立、完整系统的步骤及有关注意事项,培养独立解决问题的能力。
- 进一步熟悉单片机开发软件keil5,掌握工程的设置方法、工程的编译、调试等步;
- 复习行列式键盘识别中的扫描法和线反转法,了解各自的特点;
- 理解LED显示中动态扫描法和静态扫描法各自的特点及应用场合;
系统设计过程
1. 系统总体方案设计
本设计主要是以单片机来实现对温度的采集,其中AT89C51芯片为控制核心。该系统包括单片机最小系统、传感器电路、报警电路、LED数码管显示电路、继电器工作电路、电源电路六大部分组成,实时监控温度的变化后通过LED数码管来显示温度的数值,扩展功能为可以通过按键设置上下限报警值,一般情况下,电路正常显示绿灯,若温度超出所设定的上限值时,报警器开始报警,并且继电器电扇开始工作进行降温,同时上方灯(ledh)亮的工作指示灯亮起;若温度低于所设定的下限值时下方灯(ledl)亮的工作指示灯也亮起,从而可以远程实现对整个温度系统的管理与控制。
方案一:采用纯硬件的闭环控制系统。
方案二:测温电路的设计,可以使用热敏电阻之类的器件利用其感温效应,在将随被测温度变化的电压或电流采集过来,进行A/D转换后,就可以用单片机进行数据的处理,在显示电路上,就可以将被测温度显示出来。
方案三:考虑使用数字温度传感器,结合单片机电路设计,采用一只DS18B20温度传感器,直接读取被测温度值,之后进行转换,依次完成设计要求。
方案比较:方案一优点在于速度较快,但可靠性比较差控制精度比较低、灵活性小、线路复杂、调试、安装都不方便,且要实现题目所有的要求难度较大。方案二采用模拟温度传感器,数据处理麻烦,且容易产生信号失真。方案三可以只用一根线实现信号的双向传输,具有接口简单容易扩展等优点。DS18B20可以直接温度转换为串行数字信号,供单片机进行处理,具有低功耗、商性能、抗干扰能力强等优点。比较以上三种方案,很容易看出,采用方案三,电路比较简单,软件设计容易实现,故实际设计中拟采用方案三。
2. 硬件电路设计
温度传感器DS18B20可以直接读取被测温度值.进行数值转换,模拟温度值经过DS18B20处理后将转换为数字值,将数值送到单片机中进行数据处理,同时与上下限进行比较,超过限度后通过发光二极管显示报警。同时处理后的数据送到数码管中显示。此外,设置了按键,可以手动输入要保持的温度值,实测温度值与设定值相比,以控制加热或散热模块运行,同也可以手动输入设定时间,对恒温控制进行定时功能。
本课足以AT89S1/52单片机为核心设计的一种数字温度控制系统,该系统整体硬件电路包括:24VDC电源电路、单片机主板电路、传感器数据采集电路、温度和时问显示电路、设定按键电路、加热和散热电路等组成。
系统框图主要由主控制器、单片机复位、按键设置、时钟振荡、数码管显示、温度传感器组成。8051单片机主要由以下几部分组成:
CPU系统;
81CPU;
时钟电路;
总线控制逻辑;
存储器系统;
4K字节的程序存储器(ROM。可外扩至64KB);
128字节的数据存储器(RAM,可再外扩64KB);
特殊功能寄存器SFR;
I/O口和其它功能单元;
4个并行的IO口;
2个16位定时/计数器;
1个全双工异步串行口;
5个中断源;
3. 软件设计
整个系统的功能是由硬件电路配合软件来实现的,当硬件基本定型后,软件的功能也就基本确定下来。从软件的功能不同可分为两大类:一是监控软件(主程序),它是整个控制系统的核心,专门用来协调各执行模块之间的关系。二是执行软件(子程序),它是用来完成各种实质性的功能如测量、计算、显示、通讯等。每一个执行软件也就是一个小的功能执行模块。模块分为:毫秒延迟模块、微秒延迟模块、数码管显示模块、扫描键盘模块、返回键盘位置模块、初始化温度传感器模块、向温度传感器写入模块、温度传感器读取字符模块、传感器读取温度模块、切换显示标志模块、警告显示模块、温度设置模块、中断模块。
总原理图及元器件清单
1.总原理图
2.元件清单
元件序号 |
型号 |
主要参数 |
数量 |
备注 |
R0 |
普通电阻器0603 |
10KΩ |
1 |
无 |
R1-R4 |
普通电阻器0603 |
1KΩ |
4 |
无 |
R5-R12 |
普通电阻器0603 |
100Ω |
7 |
无 |
R13-R15 |
普通电阻器0603 |
1KΩ |
3 |
无 |
R16 |
普通电阻器0603 |
10KΩ |
1 |
无 |
CAP-E |
TC212B335M035Y |
3.3uF ±20% 35V |
1 |
无 |
C2-C3 |
1206 |
30pf |
2 |
无 |
C4 |
1206 |
104 |
1 |
无 |
C5 |
TC212B335M035Y |
3.3uF ±20% 35V |
1 |
无 |
Q1-Q5 |
2SB1132R |
PNP 晶体管 |
5 |
无 |
SMG数码管 |
FJ3104BH |
1位0.3英寸共阳红光 |
4 |
无 |
性能分析
设计内容包括两部分,一是对系统硬件部分的设计,包括温度采集电路和显示电路,二是系统软件部分的设计,通过C语言编写程序实现温度的采集与显示。这种温度测量系统的优点体现在成本低廉、性价比高、测量精度高、性能稳定等。
本设计采用AT89C51芯片作为控制核心,它具有如下特点:
(1)兼容MCS51指令系统;
(2)4K字节可编程FLASH存储器,128×8位内部RAM;
(3)32可编程I/O线,两个16位定时器/计数器;
(4)全静态工作:0Hz-24MHz;
(5)5个中断源,可编程串行通道;
(6)低功耗的闲置和掉电模式,片内振荡器和时钟电路。
本设计采用数字温度传感器DS18B20作为测为测温元件,它具有如下特点:
(1)只要求一个端口即可实现通信;
(2)在DS18B20中的每个器件上都有独一无二的序列号;
(3)实际应用中不需要外部任何元器件即可实现测温;
(4)测量温度范围在一55℃到+125℃之间,可满足满足指标要求;
(5)数字温度计的分辨率用户可以从9位到12位选择;
(6)内部有温度上、下限告警设置,可用于报警设计。
本设计采用LED数码管(7SEG-MPX6-CA)作为温度显示元件,它具有如下特点:
(1)共阳数码管共阳端直接接电源,不需要上拉电阻,则亮度较高;
(2)若用共阴数码管,单片机上电和复位后所有的I/O口都是高电位,即当单片机上电后,电流经过数码管的位流向共阴至地,数码管就会亮,耗电大,不节能,需要每次编程序时把位控制端赋予低电平,则显得麻烦。
代码
#include<reg52.h>
#include<math.h>
#define uint unsigned int
#define uchar unsigned char
#define SMG P0
sbit RED=P1^4;
sbit GREEN=P1^5;
sbit SMG1=P1^0;
sbit SMG2=P1^1;
sbit SMG3=P1^2;
sbit SMG4=P1^3;
sbit SENS=P3^6;
sbit RELAY=P1^6;
uchar S[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x38,0x40,0x00}; //10=A, 11=L, 12=-, 13=null
bit convflag=0;
bit alaflag=1;
bit dispflag=1;
bit key1flag=0;
bit keyupflag=0;
uchar x;
uchar key;
uchar s1,s2,s3,s4;
uchar count=0;
int t,at;
int account_temp=999;
void delay_ms(uint t)
{
TMOD=0X01;
TR0=1;
while(t--)
{
TH0=0Xfc;
TL0=0X18;
while(!TF0);
TF0=0;
}
TR0=0;
}
void delay_us(uint t)
{
while(t--);
}
void display(uchar n1,uchar n2,uchar n3,uchar n4,bit p,bit d){
if(d==1){
SMG4=1;
SMG1=0;
SMG=S[n1];
delay_ms(5);
SMG1=1;
SMG2=0;
SMG=S[n2];
delay_ms(5);
SMG2=1;
SMG3=0;
if(p==1){
SMG=S[n3]+0x80;
}else{
SMG=S[n3];
}
delay_ms(5);
SMG3=1;
SMG4=0;
SMG=S[n4];
delay_ms(5);
}
SMG4=1;
}
uchar key_scan(){
uchar temp=0x7f;
P2=0x1c;
if(P2!=0x1c){
delay_ms(5);
if(P2!=0x1c){
while((temp&0x10)!=0){
P2=temp;
if((P2&0x1c)!=0x1c){
return P2&0xfc;
}else{
temp=temp>>1|0x80;
}
}
}
}
return 0xff;
}
uchar key_transform(){
uchar key=key_scan();
switch(key){
case 0x6c:
return 1;
case 0x74:
return 2;
case 0x78:
return 3;
case 0xac:
return 4;
case 0xb4:
return 5;
case 0xb8:
return 6;
case 0xcc:
return 7;
case 0xd4:
return 8;
case 0xd8:
return 9;
default:
return 0;
}
}
void init_sensor(){
uint t=0;
SENS=1;
delay_us(10);
SENS=0;
delay_us(480);
SENS=1;
delay_us(480);
}
void writechar(uchar c){
uchar i=0;
for(i=0;i<8;i++){
SENS=0;
SENS=c&0x01;
delay_us(1);
SENS=1;
c>>=1;
}
delay_us(1);
}
uchar readchar(){
uchar i;
uchar c=0;
for(i=0;i<8;i++){
SENS=0;
c>>=1;
SENS=1;
if(SENS){
c|=0x80;
}
delay_us(1);
}
return c;
}
int readtemp(){
uchar h,l;
init_sensor();
writechar(0xcc);
writechar(0x44);
init_sensor();
writechar(0xcc);
writechar(0xbe);
l=readchar();
h=readchar();
return (int)(((h<<8)|l)*0.625);
}
void dispornot(){
if(key1flag==0){
dispflag=!dispflag;
key1flag=1;
}
}
void alarm(){
RELAY=0;
if(key==9){
alaflag=0;
}
if(alaflag){
RED=0;
for(x=0;x<5;x++){
display(10,11,10,13,0,dispflag);
}
RED=1;
for(x=0;x<5;x++){
display(13,13,13,13,0,dispflag);
}
return;
}
display(s1,s2,s3,s4,1,dispflag);
}
void setting(){
char i=1;
t=account_temp;
if(t>=0)
s1=13;
else
s1=12;
at=abs(t);
s2=at/100%10;
s3=at/10%10;
s4=at%10;
while(1){
key=key_transform();
if(key==0){
keyupflag=1;
}
if(key==5&&keyupflag){
alaflag=1;
return;
}
if(key==4&&keyupflag){
i-=1;
if(i<0){
i+=4;
}
keyupflag=0;
}
if(key==6&&keyupflag){
i+=1;
if(i>4){
i-=4;
}
keyupflag=0;
}
switch(i){
case 1:
if((key==2||key==8)&&keyupflag){
if(s1==12){
s1=13;
}else{
s1=12;
}
keyupflag=0;
}
for(x=0;x<5;x++){
display(13,s2,s3,s4,1,1);
}
break;
case 2:
if((key==2)&&keyupflag){
s2++;
if(s2>9){
s2=0;
}
keyupflag=0;
}else if((key==8)&&keyupflag){
s2--;
if(s2>9){
s2=9;
}
keyupflag=0;
}
for(x=0;x<5;x++){
display(s1,13,s3,s4,1,1);
}
break;
case 3:
if((key==2)&&keyupflag){
s3++;
if(s3>9){
s3=0;
}
keyupflag=0;
}else if((key==8)&&keyupflag){
s3--;
if(s3>9){
s3=9;
}
keyupflag=0;
}
for(x=0;x<5;x++){
display(s1,s2,13,s4,1,1);
}
break;
case 4:
if((key==2)&&keyupflag){
s4++;
if(s4>9){
s4=0;
}
keyupflag=0;
}else if((key==8)&&keyupflag){
s4--;
if(s4>9){
s4=9;
}
keyupflag=0;
}
for(x=0;x<5;x++){
display(s1,s2,s3,13,1,1);
}
break;
}
account_temp=100*s2+10*s3+s4;
if(s1==12){
account_temp=-account_temp;
}
t=account_temp;
if(t>=0)
s1=13;
else
s1=12;
at=abs(t);
s2=at/100%10;
s3=at/10%10;
s4=at%10;
for(x=0;x<5;x++){
display(s1,s2,s3,s4,1,1);
GREEN=1;
}
}
}
main(){
TMOD=0X11;
TH1=TL1=0;
EA=1;
ET1=1;
TR1=1;
while(1){
if(count>=100){
if(t!=readtemp()){
t=readtemp();
if(t>=0)
s1=13;
else
s1=12;
at=abs(t);
s2=at/100%10;
s3=at/10%10;
s4=at%10;
}
count=0;
}
key=key_transform();
if(key==3){
dispornot();
}else{
key1flag=0;
}
if(key==1){
setting();
}
if(t>account_temp){
alarm();
GREEN=1;
if(key==7){
dispflag=!dispflag;
}
}else{
if(t<=account_temp-1){ //Schmitt
alaflag=1;
GREEN=0;
RELAY=1;
}
display(s1,s2,s3,s4,1,dispflag);
}
}
}
void cooldown() interrupt 3{
count++;
}