单片机Word下载.docx
《单片机Word下载.docx》由会员分享,可在线阅读,更多相关《单片机Word下载.docx(17页珍藏版)》请在冰豆网上搜索。
驱动电路五个部分。
系统框图如图1所示。
其中数据采集模块负责实时采集温度数据,采集到的温度数据传输到单片
机,由单片机处理后的数据送显示部分显示。
设置模块可设置预定温度,当检测温度高于报警上限温度时,蜂鸣器将会报警。
图1.系统框图
四、系统硬件设计:
1.AT89S52单片机最小系统:
最小系统包括晶体振荡电路、复位开关和电源部分。
图2为AT89S52单片机的最小系统。
图2最小系统电路图
2.温度测量模块:
温度测量传感器采用DALLAS公司DS18B20的单总线数字化温度传感器,测温范围为-55℃~125℃,可编程为9位~12位A/D转换精度,测温分辨率达到0.0625℃,采用寄生电源工作方式,CPU只需一根口线便能与DS18B20通信,占用CPU口线少,可节省大量引线和逻辑电路。
接口电路如图3所示。
图3DS18B20测量电路
3.蜂鸣器报警模块:
蜂鸣器需要三极管放大电流来驱动,一开始由于使用的电阻太大,导致电流较小,蜂鸣器不响,后来并了一个电阻就好了。
电路如图4所示:
图4报警电路
4.LED显示模块:
显示部分选用4位共阳数码管。
由于数码管的驱动电流较大,所以在设计时加上了三极管9013作为驱动电路。
数码管和单片机的接口如图5所示:
图5数码管显示电路
5.整体电路:
系统电路如图6
图6整体电路
五、系统软件设计流程:
(1)主程序流程图
图7主程序流程图
(2)中断程序流程图
图8中断程序流程图
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
AT89S52具有以下标准功能:
8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。
另外,AT89S52引脚图AT89S52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
DS18B20是美国DALLAS半导体公司继DS1820之后最新推出的一种改进型智能温度传感器。
与传统的热敏电阻相比,他能够直接读出被测温度并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
可以分别在93.75ms和750ms内完成9位和12位的数字量,并且从DS18B20读出的信息或写入DS18B20的信息仅需要一根口线(单线接口)读写,温度变换功率来源于数据总线,总线本身也可以向所挂接的DS18B20供电,而无需额外电源。
因而使用DS18B20可使系统结构更趋简单,可靠性更高。
他在测温精度、转换时间、传输距离、分辨率等方面较DS1820有了很大的改进,给用户带来了更方便的使用和更令人满意的效果。
DS18B20工作原理
DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。
DS18B20测温原理如图所示。
图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。
高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。
计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。
图中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。
DS18B20的初始化
(1)先将数据线置高电平“1”。
(2)延时(该时间要求的不是很严格,但是尽可能的短一点)
(3)数据线拉到低电平“0”。
(4)延时750微秒(该时间的时间范围可以从480到960微秒)。
(5)数据线拉到高电平“1”。
(6)延时等待(如果初始化成功则在15到60毫秒时间之内产生一个由DS18B20所返回的低电平“0”。
据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。
(7)若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。
(8)将数据线再次拉高到高电平“1”后结束。
DS18B20的写操作
(1)数据线先置低电平“0”。
(2)延时确定的时间为15微秒。
(3)按从低位到高位的顺序发送字节(一次只发送一位)。
(4)延时时间为45微秒。
(5)将数据线拉到高电平。
(6)重复上
(1)到(6)的操作直到所有的字节全部发送完为止。
(7)最后将数据线拉高。
DS18B20的读操作
(1)将数据线拉高“1”。
(2)延时2微秒。
(3)将数据线拉低“0”。
(4)延时15微秒。
(5)将数据线拉高“1”。
(6)延时15微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时30微秒。
六、系统调试:
下图为系统测试的当前温度值,显示在4位LED数码管上。
下图为系统进入中断,设置报警上限温度。
下图为系统电路板的反面焊接详情。
八、参考文献
[1]童诗白,华成英.模拟电子技术基础[M].北京:
高等教育出版社,2006
[2]阎石主编数字电子技术基础北京:
高等教育出版社,1998
[3]邹应全51系列单片机原理与实验教程西安电子科技大学出版社,2007
[4]
程序:
#include"
reg52.h"
#include<
stdio.h>
#defineAlarm10
sbitDQ=P2^4;
sbitBeep=P3^4;
unsignedchartempL=0,tempH=0;
unsignedcharflag=0;
unsignedinttemperature,negtemper;
unsignedcharidataaddrdat[2]={0x0,0x0};
unsignedchartab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsignedchartab1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsignedchardispbuf[3]={0,0,0};
unsignedcharwarning=30;
biton=1,off=0;
voiddelay(unsignedinti)
{
while(i--)
}
voidbeep(biti)
Beep=i;
voidInit_DS18B20(void)//初始化程序
unsignedcharx=0;
DQ=1;
//DQ先置高
delay(8);
//稍延时
DQ=0;
//发送复位脉冲
delay(85);
//延时(>
480us)
//拉高数据线
delay(14);
//等待(15—60us)
x=DQ;
delay(20);
ReadOneChar(void)
unsignedchari=0;
//主机数据线先从高电平拉至低电平
unsignedchardat=0;
//保持1ms以上,再使数据线
for(i=8;
i>
0;
i--)//升为高电平,从而产生读信号,每个
{DQ=1;
//读周期最短的持续时间为60us,各个读
delay
(1);
//周期之间必须有1ms以上的高电平恢复期
DQ=0;
dat>
>
=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
voidWriteOneChar(unsignedchardat)
{//数据线从高电平拉至低电平,产生写
unsignedchari=0;
//起始信号,15ms之内将所需写的位送
i--)//到数据线上,在15—60ms之间对数据线
{//进行采样,如果是高电平就写1,低就写0
//在开始另一个写周期前必须有1ms以上的高电平
DQ=dat&
0x01;
//恢复期
delay(5);
}
delay(4);
ReadTemperature(void)
Init_DS18B20();
//初始化
WriteOneChar(0xcc);
//跳过读序列号的操作
WriteOneChar(0x44);
//启动温度转换
delay(125);
//转换需要一点时间,延时
WriteOneChar(0xbe);
//读温度寄存器
tempL=ReadOneChar();
//读出温度的低位LSB
tempH=ReadOneChar();
//读出温度的高位MSB
temperature=(tempH*256)+tempL;
//温度转换,对高、低位做相应
return(temperature);
//的运算,转化为实际温度
voidDispbuf(unsignedinttemper)
unsignedchartemp;
dispbuf[2]=(temper>
4)/10;
//取十位
dispbuf[1]=(temper>
4)%10;
//取各位
temp=temper&
0x0F;
dispbuf[0]=temp*625/1000;
//小数近似处理
unsignedchargetkey()//键盘扫描
P2=0xff;
if(P2==0xfe)
{
delay(12000);
if(P2!
=0xfe);
elsereturnP2;
if(P2==0xfd)
=0xfd);
if(P2==0xfb)
=0xfb);
Inter0_process()interrupt2//外部中断1
unsignedcharkey;
inti;
unsignedchardis=0x01;
unsignedintj;
for(j=5000;
j>
j--)
key=getkey();
//取键值
if(key==0xfe)//如+键按下,则温度值递增
{
warning++;
delay(80);
if(key==0xfd)//如-键按下,则温度递减
warning--;
if(key==0xfb)//按键退出中断
j=1;
for(i=0;
i<
2;
i++)//设置两位报警值,并在LED上显示
P1=dis;
dis<
<
if(i==0)
P0=tab[warning%10];
else
P0=tab[warning/10];
delay(200);
dis=0x01;
main()
unsignedchari,npos=0x01;
P0=0xff;
P1=0xff;
EX1=1;
//开中断1
IT1=1;
//下降沿触发
ET1=1;
EA=1;
//开总中断
while
(1)
if((temperature&
0xf000)==0xf000)//判断是否为负温度
ReadTemperature();
for(i=0;
4;
i++)//4为LED显示
{
negtemper=(~temperature)+1;
//取原码
Dispbuf(negtemper);
//取位值
P1=npos;
npos<
//循环使能
if(i==1)//第二位显示有点
{
P0=tab1[dispbuf[i]];
//查表显示
delay(500);
}
elseif(i==3)//显示负号
P0=0xbf;
else
{
P0=tab[dispbuf[i]];
delay(500);
}
}
npos=0x01;
else//如不是负温度
3;
i++)//显示3位
//读温度值
Dispbuf(temperature);
if(((temperature>
4)&
0xff)>
=warning)//温度值大于报警温
//度值则报警
beep(on);
//蜂鸣器响
elsebeep(off);
//不响
P1=npos;
npos<
//循环显示
if(i==1)
P0=tab1[dispbuf[i]];
else
P0=tab[dispbuf[i]];
delay(100);
npos=0x01;