单片机设计数字温度计.docx
《单片机设计数字温度计.docx》由会员分享,可在线阅读,更多相关《单片机设计数字温度计.docx(13页珍藏版)》请在冰豆网上搜索。
单片机设计数字温度计
一、设计题目
这次单片机课程的设计任务选择的是:
数字温度计
二、设计任务和要求
设计要求:
(1)、基本范围-50℃~110℃
(2)、精度误差小于0.5℃
(3)、LED数码直读显示
(4)、实现语音报数
报告要求:
(1)原理图中元件电气图形符号符合国家标准
(2)整体布局合理,注标规范、明确、美观,不产生歧义
(3)列出完整的元件清单(标号、型号及大小、封装形式、数量)
(4)图纸幅面为A4
(5)流程图的符号采用国际标准
三、原理电路和程序设计
(1)方案比较以及元件的选择
1)单片机的选取:
本系统采用STC89C52RC单片机为控制核心。
因为51系列单片机功能齐全,能运行各种项目设计。
且因为51系列单片机操作简单,方便。
2)温度传感器的选取:
传感器是信号输入通道的第一道环节,也是决定整个测试系统性能的关键环节。
相比热敏电阻来说,DS18B20单总线数字式温度传感器灵敏度高,精度高,但本次课程设计对温度精度的要求不高,且因为DS18B20温度传感器需要初始化,价格也比热敏电阻高,综合考虑,本设计采用热敏电阻对温度信号进行采集。
3)显示器的选取:
显示系统是单片机控制系统的重要组成部分,主要用于显示各种参数的值,常用的显示器有CRT、LED、LCD等。
本设计用LED数码管显示需求片数并不多,观察方便,而LED数码管相对于其他显示器价格也比较便宜,成本也较低,所以本系统采用LED数码管显示。
(2)整体电路
图3-2
(3)单元电路设计
1)晶振电路:
瓷片电容C1、C2是用来驱动晶振Y1的,因为晶振的
大小是16M,所以选用20P的电容。
图3-3-1
2)复位电路:
复位电路选用了10nF的电解电容和10K的电阻。
图3-3-2
3)温度显示数码管驱动电路:
PE0~PE3是进行位选通的控制,PD口进行段选通的控制。
图3-3-3
(4)说明电路工作原理
本设计使系统可以检测-50~110℃范围内的温度,考虑到测温精度,设置显示数值精确到0.5℃并且设置温度的上下限,当温度值超过上下限温度时,报警电路中的蜂鸣器鸣响,报警灯闪。
根据STM8S105C6T6的引脚特性,本设计中采用PB0~PB2和PD口作为四位数码管的驱动引脚,PA3~PA5作为外部中断的输入,PB4作为热敏电阻与单片机之间的信息传送。
PB5与蜂鸣器相接,控制蜂鸣器是否鸣响。
RST作为复位输入,当振荡器工作时,RST引脚出现2个机器周期以上高电平使单片机复位。
PB5与正常工作指示灯相连接,PB7引脚与报警灯相接,控制报警灯是否闪亮。
XTAL1振荡器反相放大器及内部时钟发生器的输入端。
XTAL2振荡器反相放大器的输出端。
四、电路和程序调试过程与结果
(1)设计逻辑图:
(2)部分程序代码
#include//调用单片机头文件
#defineucharunsignedchar//无符号字符型宏定义变量范围0~255
#defineuintunsignedint//无符号整型宏定义变量范围0~65535
//数码管段选定义0123456789
ucharcodesmg_du[]={0x14,0x77,0x4c,0x45,0x27,0x85,0x84,0x57,0x04,0x05,
//ABCDEF不显示
0x06,0xa4,0x9c,0x64,0x8c,0x8e,0xff};//断码
//数码管位选定义
sbitsmg_we1=P2^0;//数码管位选定义
sbitsmg_we2=P2^2;
sbitsmg_we3=P2^4;
sbitsmg_we4=P2^6;
uchardis_smg[8]={0x14,0x77,0x4c,0x45,0x27,0x85,0x84};
ucharsmg_i=3;//显示数码管的个位数
sbitdq=P3^3;//18b20IO口的定义
bitflag_wd_z_f;//正负温度
inttemperature;//
/***********************1ms延时函数*****************************/
voiddelay_1ms(uintq)
{
uinti,j;
for(i=0;ifor(j=0;j<120;j++);
}
/***********************小延时函数*****************************/
voiddelay_uint(uintq)
{
while(q--);
}
/***********************数码位选函数*****************************/
voidsmg_we_switch(uchari)
{
switch(i)
{
case0:
smg_we1=0;smg_we2=1;smg_we3=1;smg_we4=1;break;
case1:
smg_we1=1;smg_we2=0;smg_we3=1;smg_we4=1;break;
case2:
smg_we1=1;smg_we2=1;smg_we3=0;smg_we4=1;break;
case3:
smg_we1=1;smg_we2=1;smg_we3=1;smg_we4=0;break;
}
}
/***********************数码显示函数*****************************/
voiddisplay()
{
staticuchari;
i++;
if(i>=smg_i)
i=0;
P0=0xff;//消隐
smg_we_switch(i);//位选
P0=dis_smg[i];//段选
}
/***********************18b20初始化函数*****************************/
voidinit_18b20()
{
bitq;
dq=1;//把总线拿高
delay_uint
(1);//15us
dq=0;//给复位脉冲
delay_uint(80);//750us
dq=1;//把总线拿高等待
delay_uint(10);//110us
q=dq;//读取18b20初始化信号
delay_uint(20);//200us
dq=1;//把总线拿高释放总线
}
/*************写18b20内的数据***************/
voidwrite_18b20(uchardat)
{
uchari;
for(i=0;i<8;i++)
{//写数据是低位开始
dq=0;//把总线拿低写时间隙开始
dq=dat&0x01;//向18b20总线写数据了
delay_uint(5);//60us
dq=1;//释放总线
dat>>=1;
}
}
/*************读取18b20内的数据***************/
ucharread_18b20()
{
uchari,value;
for(i=0;i<8;i++)
{
dq=0;//把总线拿低读时间隙开始
value>>=1;//读数据是低位开始
dq=1;//释放总线
if(dq==1)//开始读写数据
value|=0x80;
delay_uint(5);//60us读一个时间隙最少要保持60us的时间
}
returnvalue;//返回数据
}
/*************读取温度的值读出来的是小数***************/
uintread_temp()
{
uintvalue;
ucharlow;init_18b20();//初始化18b20
write_18b20(0xcc);//跳过64位ROM
write_18b20(0x44);//启动一次温度转换命令
delay_uint(50);//500us
init_18b20();//初始化18b20
EA=0;
write_18b20(0xcc);//跳过64位ROM
write_18b20(0xbe);//发出读取暂存器命令
low=read_18b20();//读温度低字节
value=read_18b20();//读温度高字节
EA=1;
value<<=8;//把温度的高位左移8位
value|=low;//把读出的温度低位放到value的低八中
if((value&0xf000)==0xf000)
{
flag_wd_z_f=1;//负温度
}
else
flag_wd_z_f=0;//正温度
value*=0.625;//转换到温度值小数
returnvalue;//返回读出的温度
}
/*************定时器0初始化程序***************/
voidtime_init()
{
EA=1;//开总中断
TMOD=0X01;//定时器0、定时器1工作方式1
ET0=1;//开定时器0中断
TR0=1;//允许定时器0定时
}
/****************主函数***************/
voidmain()
{
P0=P1=P2=P3=0xff;
time_init();//初始化定时器
temperature=read_temp();//先读出温度的值
delay_1ms(650);
temperature=read_temp();//先读出温度的值
dis_smg[0]=smg_du[temperature%10];//取温度的小数显示
dis_smg[1]=smg_du[temperature/10%10]&0xfb;//取温度的个位显示
dis_smg[2]=smg_du[temperature/100%10];//取温度的十位显示
while
(1)
{
temperature=read_temp();//先读出温度的值
if(flag_wd_z_f==1)//负温度
{
smg_i=4;
dis_smg[0]=smg_du[temperature%10];//取温度的小数显示
dis_smg[1]=smg_du[temperature/10%10]&0xfb;//取温度的个位显示
dis_smg[2]=smg_du[temperature/