单片机课程设计
班级物联网卓越1502 姓名周* 学号1030615315 基于AT89X52的温度测量系统 单片机实时检测温度传感器DS18B20的状态,并将DS18820得到的数据进行处理。上电后数码管显示当前的环境温度,通过按键可设置高低温报警值,当检测到的温度高于设置的报警值的时候,蜂鸣器报警同时报警灯闪烁,温度检测精确到0.1度。并具有掉电保存功能,数据保存在单片机内部EEPOM中,进入设置界面后如果没有键按下系统会在15秒后自动退出设置界面。 二、硬件实现及单元电路设计 1总系统原理图 2.1 主控制模块 主控制最小系统电路如图1所示。 图1 单片主控电路 2.2 显示模块电路 显示采用四位数码管显示,当位选打开时,送入相应的段码,则相应的数码管打开,关掉位选,打开另一个位选,送入相应的段码,则数码管打开,而每次打开关掉相应的位选时,时间间隔低于20ms,从人类视觉的角度上看,就仿佛是全部数码管同时显示的一样。显示电路如图2 图2 数码管显示 2.3 数码管显示驱动电路三极管8550来驱动4位数码管,不仅简单,而且价格便宜。 图3 驱动电路
2.4 温度传感器(DS18B20)电路2.4.1 DS18B20基本介绍DS18B20是美国DALLAS半导体公司推出的第一片支持“一线总线”接口的温度传感器,它具有微型化、低功耗、高性能、抗干扰能力强、易配微处理器等优点,可直接将温度转化成串行数字信号处理器处理。 DS18B20进行精确的温度转换,I/O线必须保证在温度转换期间提供足够的能量,由于每个DS18B20在温度转换期间工作电流达到1mA,当几个温度传感器挂在同一根I/O线上进行多点测温时,只靠4.7K上拉电阻就无法提供足够的能量,会造成无法转换温度或温度误差极大。 因此,下图电路只适应于单一温度传感器测温情况下使用,不适宜采用电池供电系统中。并且工作电源VCC必须保证在5V,当电源电压下降时,寄生电源能够汲取的能量也降低,会使温度误差变大。 图4 温度传感器电路引脚图 2.4.2 DS18B20控制方法DS18B20有六条控制命令: 温度转换 44H 启动DS18B20进行温度转换 读暂存器 BEH 读暂存器9个字节内容 写暂存器 4EH 将数据写入暂存器的TH、TL字节 复制暂存器 48H 把暂存器的TH、TL字节写到E2RAM中 重新调E2RAM B8H 把E2RAM中的TH、TL字节写到暂存器TH、TL字节 读电源供电方式 B4H 启动DS18B20发送电源供电方式的信号给主CPU 2.4.3 DS18B20供电方式DS18B20可以采用两种方式供电,一种是采用电源供电方式,此时DS18B20的1脚接地,2脚作为信号线,3脚接电源。另一种是寄生电源供电方式,如图3.1所示单片机端口接单线总线,为保证在有效的DS18B20时钟周期内提供足够的电流,可用一个三极管来完成对总线的上拉。本设计采用电源供电方式, P2.2口接单线总线为保证在有效的DS18B20时钟周期内提供足够的电流,可用一个上拉电阻和STC89C52的P2.2来完成对总线的上拉。当DS18B20处于写存储器操作和温度A/D变换操作时,总线上必须有强的上拉,上拉开启时间最大为10 μs。采用寄生电源供电方式是VDD和GND端均接地。由于单线制只有一根线,因此发送接收口必须是三状态的。主机控制DS18B20完成温度转换必须经过3个步骤:
2.6 蜂鸣器、发光二极管报警电路 电路如图5主要是用来设定温度报警温度的、有高温和低温报警。 图5 蜂鸣器、发光二极管驱动引脚图 三、程序设计 3.1程序结构分析 主程序调用了3个子程序,分别是数码管显示程序、温度信号处理程序、按键设定报警温度程序。温度信号处理程序:对温度芯片送过来的数据进行处理,进行判断和显示。数码管显示程序:向数码管的显示送数,控制系统的显示部分。按键设定程序:可以设定低温和高温报警可精确到0.1度。 3.2 系统程序流图主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值,温度测量每1s进行一次。这样可以在一秒之内测量一次被测温度,主程序的主要功能是负责温度的实时显示,读出并处理DS18B20的当前温度值,与设定的报警温度比较,其程序流程见图6所示。 通过调用读温度子程序把存入内存储中的整数部分与小数部分开分存放在不的的两个单元中,然后通过调用显示子程序显示出来。
图6 DS18B20温度流程图
3.2.1 DS18B20初始化程序流程图 在DS18B20工作之前需要进行初始化,流程图如下: 图7 初始化程序流程图 3.2.2 读温度子程序流程图 读温度子程序的主要功能是从DS18B20中读出温度数据,移入温度暂存器保存。其程序流程图如下: 图8 温度子程序流程图 四、Proteus仿真样例 4.1正常运行(预设温度37℃)
4.2 高温报警设置为40℃
4.3温度达到42℃,LED闪烁,蜂鸣器报警
4.4低温报警设置为15℃ 4.3温度达到14℃,LED闪烁,蜂鸣器报警 五、心得总结 本次课程设计的温控报警系统具有一定的挑战性,要求可以任意设置触发所需的温度阈值并通过LED和蜂鸣器发出报警信号,在完成设计任务的过程中查阅了大量的参考资料,同时也加深了对各种元器件使用的理解。通过本次课程设计,又使我学到了许多书本上无法学到的知识,也使我深刻体会到单片机技术应用领域的广泛。
单片机源程序如下: - #include <AT89X52.h>
- #define uint unsigned int
- #define uchar unsigned char //宏定义
- #define SET P3_1 //定义调整键
- #define DEC P3_2 //定义减少键
- #define ADD P3_3 //定义增加键
- #define BEEP P3_6 //定义蜂鸣器
- #define ALAM P1_2 //定义灯光报警
- #define DQ P3_7 //定义DS18B20总线I/O
- bit shanshuo_st; //闪烁间隔标志
- bit beep_st; //蜂鸣器间隔标志
- sbit DIAN = P0^5; //小数点
- uchar x=0; //计数器
- signed char m; //温度值全局变量
- uchar n; //温度值全局变量
- uchar set_st=0; //状态标志
- signed char shangxian=38; //上限报警温度,默认值为38
- signed char xiaxian=5; //下限报警温度,默认值为38
- //uchar code LEDData[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff};
- uchar code LEDData[]={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7,0xCF,0xDA,0x9B,0xDC,0x9B,0x8B};
- //============================================================================================
- //====================================DS18B20=================================================
- //============================================================================================
- /*****延时子程序*****/
- void Delay_DS18B20(int num)
- {
- while(num--) ;
- }
- /*****初始化DS18B20*****/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ复位
- Delay_DS18B20(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- Delay_DS18B20(80); //精确延时,大于480us
- DQ = 1; //拉高总线
- Delay_DS18B20(14);
- x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
- Delay_DS18B20(20);
- }
- /*****读一个字节*****/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat|=0x80;
- Delay_DS18B20(4);
- }
- return(dat);
- }
- /*****写一个字节*****/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- Delay_DS18B20(5);
- DQ = 1;
- dat>>=1;
- }
- }
- /*****读取温度*****/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned int t=0;
- float tt=0;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0x44); //启动温度转换
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器
- a=ReadOneChar(); //读低8位
- b=ReadOneChar(); //读高8位
- t=b; //高8位转移到t
- t<<=8; //t数据左移8位
- t=t|a; //将t和a按位或,得到一个16位的数
- tt=t*0.0625; //将t乘以0.0625得到实际温度值(温度传感器设置12位精度,最小分辨率是0.0625)
- t= tt*10+0.5; //放大10倍(将小数点后一位显示出来)输出并四舍五入
- return(t); //返回温度值
- }
- //=====================================================================================
- //=====================================================================================
- //=====================================================================================
- /*****延时子程序*****/
- void Delay(uint num)
- {
- while( --num );
- }
- /*****初始化定时器0*****/
- void InitTimer(void)
- {
- TMOD=0x1;
- TH0=0x3c;
- TL0=0xb0; //50ms(晶振12M)
- }
- /*****读取温度*****/
- void check_wendu(void)
- {
- uint a,b,c;
- c=ReadTemperature(); //获取温度值
- a=c/100; //计算得到十位数字
- b=c/10-a*10; //计算得到个位数字
- m=c/10; //计算得到整数位
- n=c-a*100-b*10; //计算得到小数位
- if(m<0){m=0;n=0;} //设置温度显示上限
- if(m>99){m=99;n=9;} //设置温度显示上限
- }
- /*****显示开机初始化等待画面*****/
- void Disp_init(void)
- {
- P0 = ~0x80; //显示----
- P2 = 0x7F;
- Delay(200);
- P2 = 0xDF;
- Delay(200);
- P2 = 0xF7;
- Delay(200);
- P2 = 0xFD;
- Delay(200);
- P2 = 0xFF; //关闭显示
- }
- /*****显示温度子程序*****/
- void Disp_Temperature(void) //显示温度
- {
- P0 = ~0x98; //显示C
- P2 = 0x7F;
- Delay(100);
- P2=0xff;
- P0=~LEDData[n]; //显示个位
- P2 = 0xDF;
- Delay(100);
- P2=0xff;
- P0 =~LEDData[m%10]; //显示十位
- DIAN = 0; //显示小数点
- P2 = 0xF7;
- Delay(100);
- P2=0xff;
- P0 =~LEDData[m/10]; //显示百位
- P2 = 0xFD;
- Delay(100);
- P2 = 0xff; //关闭显示
- }
- /*****显示报警温度子程序*****/
- void Disp_alarm(uchar baojing)
- {
- P0 =~0x98; //显示C
- P2 = 0x7F;
- Delay(100);
- P2=0xff;
- P0 =~LEDData[baojing%10]; //显示十位
- P2 = 0xDF;
- Delay(100);
- P2=0xff;
- P0 =~LEDData[baojing/10]; //显示百位
- P2 = 0xF7;
- Delay(100);
- P2=0xff;
- if(set_st==1)P0 =~0xCE;
- else if(set_st==2)P0 =~0x1A; //上限H、下限L标示
- P2 = 0xFD;
- Delay(100);
- P2 = 0xff; //关闭显示
- }
- /*****报警子程序*****/
- void Alarm()
- {
- if(x>=10){beep_st=~beep_st;x=0;}
- if((m>=shangxian&&beep_st==1)||(m<xiaxian&&beep_st==1))
- {
- BEEP=0;
- ALAM=0;
- }
- else
- {
- BEEP=1;
- ALAM=1;
- }
- }
- /*****主函数*****/
- void main(void)
- {
- uint z;
- InitTimer(); //初始化定时器
- EA=1; //全局中断开关
- TR0=1;
- ET0=1; //开启定时器0
- IT0=1;
- IT1=1;
- check_wendu();
- check_wendu();
- for(z=0;z<300;z++)
- {
- Disp_init();
- }
- while(1)
- {
- if(SET==0)
- {
- Delay(2000);
- do{}while(SET==0);
- set_st++;x=0;shanshuo_st=1;
- if(set_st>2)set_st=0;
- }
- if(set_st==0)
- {
- EX0=0; //关闭外部中断0
- EX1=0; //关闭外部中断1
- check_wendu();
- Disp_Temperature();
- Alarm(); //报警检测
- }
- else if(set_st==1)
- {
- BEEP=1; //关闭蜂鸣器
- ALAM=1;
- EX0=1; //开启外部中断0
- EX1=1; //开启外部中断1
- if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
- if(shanshuo_st) {Disp_alarm(shangxian);}
- }
- else if(set_st==2)
- {
- BEEP=1; //关闭蜂鸣器
- ALAM=1;
- EX0=1; //开启外部中断0
- EX1=1; //开启外部中断1
- if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
- if(shanshuo_st) {Disp_alarm(xiaxian);}
- }
- }
- }
- /*****定时器0中断服务程序*****/
- void timer0(void) interrupt 1
- {
- TH0=0x3c;
- TL0=0xb0;
- x++;
- }
- /*****外部中断0服务程序*****/
- void int0(void) interrupt 0
- {
-
- EX0=0; //关外部中断0
- if(DEC==0&&set_st==1)
- {
- do{
- Disp_alarm(shangxian);
- }
- while(DEC==0);
- shangxian--;
- if(shangxian<xiaxian)shangxian=xiaxian;
- }
- else if(DEC==0&&set_st==2)
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
|