设计要求
- 掌握行列式键盘的工作原理及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++; }