基于51单片机课程设计报告 - 图文

更新时间:2024-03-06 07:27:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

单片机课程设计

课 题:基于51单片机的交通灯设计 专 业: 机械设计制造及其自动化 学 号: 指导教师: 邵添 设计日期: 2017/12/18 成 绩:

重庆大学城市科技学院电气学院

基于51单片机数字温度计设计报告

一、设计目的作用

本设计是一款简单实用的小型数字温度计,所采用的主要元件有传感器DS18B20,单片机AT89C52,,四位共阴极数码管一个,电容电阻若干。DS18B20支持“一线总线”接口,测量温度范围-55°C~+125°C。在-10~+85°C范围内,精度为±0.5°C。18B20的精度较差,为±2°C 。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。适合于恶劣环境的现场温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。

本次数字温度计的设计共分为五部分,主控制器,LED显示部分,传感器部分,复位部分,按键设置部分,时钟电路。主控制器即单片机部分,用于存储程序和控制电路;LED显示部分是指四位共阴极数码管,用来显示温度;传感器部分,即温度传感器,用来采集温度,进行温度转换;复位部分,即复位电路,按键部分用来设置上下限报警温度。测量的总过程是,传感器采集到外部环境的温度,并进行转换后传到单片机,经过单片机处理判断后将温度传递到数码管显示。

二、设计要求

(1).利用DS18B20传感器实时检测温度并显示。 (2).利用数码管实时显示温度。

(3).当温度超过或者低于设定值时蜂鸣器报警,LED闪烁指示。 (4).能够手动设置上限和下限报警温度。

三、设计的具体实现

1、系统概述

方案一:由于本设计是测温电路,可以使用热敏电阻之类的器件利用其感温效应,在将随被测温度变化的电压或电流采集过来,进行A/D转换后,就可以用单片机进行数据的处理,在显示电路上,就可以将被测温度显示出来,这种设计需要用到A/D转换电路,感温电路比较麻烦。 方案设计框图如下:

热敏电阻组成的感温电路 AD转换 数码管显示电路 方案二:考虑到用温度传感器,在单片机电路设计中,大多都是使用传感器,所以这是非常容易想到的,所以可以采用一只温度传感器DS18B20,此传感器,

可以很容易直接读取被测温度值,进行转换,就可以满足设计要求。

从以上两种方案,很容易看出,采用方案二,电路比较简单,软件设计也比较简单,故采用了方案二。

2、 单元电路设计与分析

1、硬件设计

按照系统设计功能的要求,确定系统由3个模块组成:主控制器、测温电路和显示电路。

数字温度计总体电路结构框图所示:

电源 按键设置模块 AT89C51单片机 数码管显示 蜂鸣器报LED闪烁

警模块 报警模块

单片机的选择

DB18B20温度传感器 单片机AT89S52具有低电压供电和体积小等特点,四个端口只需要两个口就能满足电路系统的设计需要,很适合便携手持式产品的设计使用系统可用二节电池供电。由于器件问题,我们使用了通用的手机5V充电器接口。

复位电路模块

单片机系统的复位电路在这里使用的是上电+按钮的复位电路模式,其中电阻R采用的是10KΩ的阻值,电容采用电容值为10uF的电解电容,电路图如下:

温度显示模块

四位共阴极数码管,能够显示小数。列扫描用P2.4~P2.7口来实现,列驱动直接51接单片机驱动。电路图如下:

温度传感器模块

DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进

型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。电路图如下:

按键模块

按键是用来设置报警的上下限温。K1是用来进入上下限调节模式的,当按一下K1进入上限调节模式,再按一下进入下限调节模式。在正常模式下,按一下K2进入查看上限温度模式,显示1s左右自动退出;按一下K3进入查看下限温度模式,显示1s左右自动退出;按一下K4消除按键音,再按一下启动按键音。在调节上下限温度模式下,K2是实现加1功能, K1是实现减1功能,K3是用来设定上下限温度正负的。

2、软件设计

主要包括主程序、读出温度子程序、温度转换命令子程序、计算温度子程序和现实数据刷新子程序等。

主程序 主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量温度值。温度测量每1S进行一次。主流程图如下:

/******************************************************/ /* 获取温度函数

/

/*****************************************************/ void get_temperature(bit flag) {

uchar a=0,b=0,c=0,d=0; uinti;

ds18b20_init(); ds18b20_write(0xcc); //向DS18B20发跳过读ROM命令 ds18b20_write(0x44); //写启动DS18B20进行温度转换命令,转换结果存入内部RAM

if(flag==1) { //首次启动DS18B20进行温度转换需要500ms,若转换时间不够就出错,读出的是85度的错误值。 display1(1); //用开机动画耗时 度

} else

ds18b20_delayms(1); ds18b20_init(); ds18b20_write(0xcc); ds18b20_write(0xbe); a=ds18b20_read(); b=ds18b20_read(); if(flag==1)

//读内部RAM (LSB) //读内部RAM (MSB) //局部位变量f=1时读上下线报警温

{

max=ds18b20_read(); min=ds18b20_read();

//读内部RAM (TH) //读内部RAM (Tl)

}

if((max&0x80)==0x80) //若读取的上限温度的最高位(符号位)为‘1’表明是负温度

{f_max=1;max=(max-0x80);} //将上限温度符号标志位置‘1’表示负温度,将上限温度装换成无符号数。 if((min&0x80)==0x80) //若读取的下限温度的最高位(符号位)为

‘1’表明是负温度

{f_min=1;min=(min-0x80);} //将下限温度符号标志位置‘1’表示负温度,将下限温度装换成无符号数。 i=b; i>>=4; if (i==0) {

f=0; temp=((a>>4)|(b<<4));

a=(a&0x0f); temp_d=a; } else { f=1;

//i为0,正温度,设立正温度标记 //整数部分

//小数部分

//i为1,负温度,设立负温度标记

a=~a+1; b=~b;

temp=((a>>4)|(b<<4)); a=(a&0x0f);

//整数部分 //小数部分

temp_d=a; } }

/******************************************************/ /* 存储极限温度函数

/

/*****************************************************/ void store_t() {

if(f_max==1) //若上限温度为负,将上限温度转换成有符号数(最高位为1是负,为0是正) max=max+0x80; if(f_min==1) 号数

min=min+0x80; ds18b20_init();

//若下限温度为负,将上限温度转换成有符

ds18b20_write(0xcc); ds18b20_write(0x4e); 和TL)命令

ds18b20_write(max); ds18b20_write(min); ds18b20_write(0xff); ds18b20_init(); ds18b20_write(0xcc); ds18b20_write(0x48); 容写入EEPROM }

//向DS18B20发写字节至暂存器2和3(TH

//向暂存器TH(上限温度暂存器)写温度 //向暂存器TL(下限温度暂存器)写温度 //向配置寄存器写命令,进行温度值分辨率设置

//向DS18B20发将RAM中2、3字节的内

//DS18B20上电后会自

动将EEPROM中的上下限温度拷贝到TH、TL暂存器

/******************************************************/ /* 温度超限报警函数 /

/*****************************************************/ void alarm() { //若上限值是正值

if(f_max==0) {

if(f_min==0)

{ if(f==0)

//若下限值是正值 //若测量值是正值

{ if(temp<=min||temp>=max) {w=1;TR1=1;} //当测量值小于最小值或大于最大值时报

if((tempmin)) {w=0;} //当测量值大于最小值且小于最大值时

不报警

}

if(f==1){w=1;TR1=1;} //若测量值是负值时报警

//若下限值是负值 //若测量值是正值

}

if(f_min==1)

{ if(f==0)

{ if(temp>=max)//当测量值大于最大值时报警

{w=1;TR1=1;}

if(temp

{w=0;} }

if(f==1)

//若测量值是负值

{ if(temp>=min)//当测量值大于最小值时报警

{w=1;TR1=1;}

if(temp

{w=0;} } } }

if(f_max==1)

//若下限值是负值 //若下限值是负值 //若测量值是负值

{

if(f_min==1)

{ if(f==1)

{ if((temp<=max)||(temp>=min)) {w=1;TR1=1;} //当测量值小于最大值或大于最小值时报

if((tempmax)) {w=0;} //当测量值小于最小值且大于最大值时

不报警

}

if(f==0){w=1;TR1=1;} //若测量值是正值时报警

}

} }

#endif

/**********************************************************************

* 程序名; ds18b20keyscan函数

* 功能:通过键盘设定设定上下限报警温度 * 编程者:彭明闯

* 编程时间:2014/5/30

**********************************************************************/

#ifndef __keyscan_H__ //定义头文件 #define __keyscan_H__

sbit key1=P2^2; sbit key2=P2^1; sbit key3=P2^0; sbit key4=P3^3;

uchari=0; //定义全局变量i用于不同功能模式的选择,‘0’正常模式,‘1’上限调节模式,‘2’下限调节模式 uchar a=0; //定义全局变量a用于不同模式下数码管显示的选择

bit k4=0; //K4按键双功能选择位,k4=0时K4按键选择消按键音的功能,k4=1时K4按键选择正负温度设定功能 bit v=0; //K2、K3按键双功能选择位,v=0时选择上下限查看功能,v=1时选择上下限温度加减功能 bit v1=0; //v1=1时定时1250ms时间到自动关闭报警上下限查看功能 bit v2=0; //消按键音功能调整位,为‘0’时开按键音,为‘1’时关按键音

/******************************************************/ /* 读键盘延时子函数 /

/*****************************************************/ void keyscan_delay(uint z) //延时1ms左右 {

uinti,j;

for(i=z;i>0;i--)

for(j=120;j>0;j--);

}

/******************************************************/ /* 温度调节函数 /

/*****************************************************/ inttemp_change(intcount,bit f) //上下限温度调整 {

if(key2==0)

//判断K2是否按下

//v2=0开按键音,否则消按键音

//延时10ms

//再次判断K2是否按下(实现按按键时消抖) //K2按下关按键音 //若温度为正

{ if(v2==0)beer=0;

keyscan_delay(10); if(key2==0) { beer=1; if(f==0)

{

count++; //每按一下K2温度上调1

if(a==1){if(count>125) count=125;}//当温度值大于125时不上调

if(a==2){if(count>125) count=125;}

//若温度为负

}

if(f!=0)

{ count++; //每按一下K2温度下调1 if(a==1){if(count>55) count=55;}//当温度值小于-55时不再下调 if(a==2){if(count>55) count=55;} } }

while(key2==0); //K2松开按键时消抖 keyscan_delay(10);

}

if(key3==0) {

if(v2==0)beer=0; keyscan_delay(10); if(key3==0)

{

//K3按按键时消抖

}

beer=1; count--; //每按一下K3温度为正时下调1,为负时上调1 if(a==1){if(count<0) count=0;}//当温度值达到0时不再调 if(a==2){if(count<0) count=0;} }

while(key3==0);

keyscan_delay(10); //K3松开按键时消抖

}

return count;

/******************************************************/ /* 读键盘函数 /

/*****************************************************/ void keyscan() {

if(key1==0)

{

if(v2==0)beer=0; keyscan_delay(10); if(key1==0)

//K1按按键时消抖

{ beer=1; TR1=1; //开定时器1,通过s标志位的变化,实现在上下限温度调整时温度显示时闪烁的功能 k4=1; //在上下温度调节功能模式下选择K4的调整上下限温度正负的功能

v=1; //在上下温度调节功能模式下选择K2、K3的温度加减功能 i++; //K1按一下i加1,i=‘0’进入正常模式,i=‘1’进入调上限模式,i=‘2’进入调下限模式 if(i>2) //K1按下三次后退出调节模式

{ i=0; TR1=0;

//进入正常模式

//关定时器1

k4=0;

//在正常模式下选择K4的消按键音功能 //在正常模式下选择K2、K3的查看上下限

v=0; 报警温度功能 store_t();

} switch(i)

//存储调整后的上下限报警温度 //显示选择

{

case 0:a=0;break; //a=0选择显示测得的温度 case 1:a=1;break; //a=1选择显示上限温度 case 2:a=2;break; //a=2选择显示下限温度

default:break; } }

while(key1==0);

//K1松按键时消抖

keyscan_delay(10); }

if(a==1&&v==1)

//a=1选择显示上限温度且v=1时选择上

下限温度加功能

{led=0;max=temp_change(max,f_max);}//显示上限温度 else if(a==2&&v==1) //a=2选择显示下限温度且v=1时选择上下限温度减功能

{led=1;min=temp_change(min,f_min);} else;

if(k4==1) //k4=1时K4按键选择正负温度设定功能 {

if(key4==0) {

if(v2==0)beer=0; keyscan_delay(5); if(key4==0) { beer=1; if(a==1) {if(max>55) f_max=0;else f_max=~f_max;}//当温度大于55度时,只能设定为正温度

if(a==2) {if(min>55) f_max=0;else f_min=~f_min;}//当温度大于55度时,只能设定为正温度 } while(key4==0); keyscan_delay(10); } }

if(v==0) { if(key2==0) {

if(v2==0)beer=0; keyscan_delay(10); if(key2==0) { beer=1; a=1;

TR1=1;

s1=1;

出 } while(key2==0); keyscan_delay(10); }

if(key3==0) {

if(v2==0)beer=0; keyscan_delay(10); if(key3==0) {

beer=1; a=2; TR1=1; s1=1;

//v=0时选择上下限查看功能 //选择上限显示

//开定时器1开始定时一分钟左右

//上限显示不闪烁,显示一分钟左右自动退

//选择下限显示

//开定时器1开始定时1s

//下限显示不闪烁,显示1s自动退出

}

while(key3==0); keyscan_delay(10); } if(v1==1) //v1=1时定时1s时间到自动关闭报警上下限查看功能 {a=0;v1=0;TR1=0;} //a=0显示实测温度,v1清零,关定时器1 if(k4==0) //k4=0时K4按键选择消按键音的功能

{

if(key4==0) {

if(v2==0)beer=0; keyscan_delay(10); if(key4==0) {

beer=1; v2=~v2; //为‘0’时开按键音,为‘1’时关按键音 }

while(key4==0);

keyscan_delay(10); } }

} }

#endif

/**********************************************************************

* 程序名; ds18b20数码管动态显示头文件 * 功能:通过定时器0延时是数码管动态显示 * 编程者:彭明闯

* 编程时间:2014/5/30

**********************************************************************/

#ifndef __ds18b20_display_H__

#define __ds18b20_display_H__

#define uint unsigned int //变量类型宏定义,用uint表示无符号整形(16位)

#define uchar unsigned char //变量类型宏定义,用uchar表示无符号字符型(8位)

sbit wei1=P2^4; sbit wei2=P2^5; sbit wei3=P2^6; sbit wei4=P2^7;

ucharnum=0; 值为‘0’

//可位寻址变量定义,用wei1表示P2.4口 //用wei2表示P2.5口 //用wei3表示P2.6口 //用wei4表示P2.7口

//定义num为全局无符号字符型变量,赋初

uchar code temperature1[]={ 0x3f,0x06,0x5b,0x4f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f};

//定义显示码表0~9

uchar code temperature2[]={ 0xbf,0x86,0xdb,0xcf,0xe6, 0xed,0xfd,0x87,0xff,0xef}; //带小数点的0~9. uchar code temperature3[]={ 0x00,0x80,0x40,0x76,0x38}; //依次是‘不显示’‘.’‘-’‘H’‘L’

/******************************************************/ /* 延时子函数 /

/*****************************************************/

void display_delay(uint t) //延时1ms左右 {

uinti,j;

for(i=t;i>0;i--) for(j=120;j>0;j--); }

/******************************************************/ /* 定时器1初始化函数

/

/*****************************************************/

void timer1_init(bit t) {

TMOD=0x10; TH0=0x3c; TL0=0xb0; EA=1; ET1=1; TR1=t; // 局部变量t为1启动定时器1,为0关闭定时器1

}

/******************************************************/ /* 定时器1中断函数 /

/*****************************************************/

void timer1() interrupt 3 {

TH0=0x3c; TL0=0xb0; num++; 加1一次)

//重新赋初值,定时50ms

//每进入一次定时器中断num加1(每50ms

if(num<5)

{s=1;if(w==1){beer=1;led=1;}else{beer=1;led=1;}}

else //进入4次中断,定时200ms时若报警标志位w为‘1’则启动报警,不为‘1’不启动

//实现间歇性报警功能

{s=0;if(w==1){beer=0;led=0;}else{beer=1;led=1;}} if(num>20) //进入20次中断,定时1s

//num归0,重新定开始定时1s //定时1s时间到时自动关闭报警上下限显示

{

num=0; s1=0; 功能

v1=1; //定时1s时间到时自动关闭报警上下限查看

功能

} }

/******************************************************/ /* 调整报警上下限选择函数

/

/*****************************************************/

void selsct_1(ucharf,uchar k) //消除百位的0显示,及正负温度的显示选择

{

if(f==0) 不显示百位,不为0则显示

//若为正温度,百位为0则

{ if(k/100==0) P0=temperature3[0]; else P0=temperature1[k/100]; }

if(f==1)

//若为负温度,若十位为

0,百位不显示,否则百位显示‘-’

{

if(k0/10==0) P0=temperature3[0]; else P0=temperature3[2]; } }

void selsct_2(bit f,uchar k) //消除十位的0显示,及正负温度的显示选择

{

if(f==0) 则不显示十位,否则显示十位

//若为正温度,百位十位均为0

{ if((k/100==0)&&(k0/10==0)) P0=temperature3[0]; else P0=temperature1[k0/10]; }

if(f==1)

//若为负温度,若十位为

0,十位不显示,否则十位显示‘-’

{

if(k0/10==0) P0=temperature3[2]; else P0=temperature1[k0/10]; } }

/******************************************************/ /* 主函数显示 /

/*****************************************************/

void display(uchart,uchart_d) //用于实测温度、上限温度的显示 {

uchari;

for(i=0;i<4;i++) { switch(i)

{

case 0: //选通第一个数码管 wei2=1; //关第二个数码管 wei3=1; //关第三个数码管 wei4=1; //关第四个数码管 wei1=0; //开第一个数码管 if(a==0){selsct_1(f,t);} //若a=0则在第一个数码管上显示测量温度的百位或‘-’

if(a==1) {

P0=temperature3[3]; //若a=1则在第一个数码管上显示‘H’ }

if(a==2) {

P0=temperature3[4]; //若a=2则在第一个数码管上显示‘L’ } break;

//依次从左至右选通数码管显示,实现动态显示

case 1: //选通第二个数码管

wei1=1; wei3=1; wei4=1; wei2=0; if(a==0){selsct_2(f,t);} //若a=0则在第二个数码管上显示测量温度的十位或‘-’ if(a==1) //若a=1则在第二个数码管上显示上限报警温度的百位或‘-’

{

if(s==0) selsct_1(f_max,max);//若s=0则显示第二个数码管,否则不

显示 else P0=temperature3[0]; //通过s标志位的变化实现调节上下限报警温度时数码管的闪烁 if(s1==1) selsct_1(f_max,max);//若s1=1则显示第二个数码管(s1标志位用于上下限查看时的显示) } if(a==2) 上显示下限报警温度的百位或‘-’

{

//若a=2则在第二个数码管

if(s==0) selsct_1(f_min,min); else P0=temperature3[0]; if(s1==1) selsct_1(f_min,min); } break; case 2:

//选通第三个数码管

wei1=1; wei2=1; wei4=1; wei3=0; if(a==0){P0=temperature2[t];}//若a=0则在第三个数码管上显示测量温度的个位 if(a==1) //若a=1则在第三个数码管上显示上限报警温度的十位或‘-’

{ if(s==0) selsct_2(f_max,max);//若s=0则显示第三个数码管,否则不显示

else P0=temperature3[0];

if(s1==1) selsct_2(f_max,max);//若s1=1则显示第三个数码管

//若a=2则在第三个

} if(a==2) 数码管上显示下限报警温度的十位或‘-’

{ if(s==0) selsct_2(f_min,min); else P0=temperature3[0]; if(s1==1) selsct_2(f_min,min); } break; case 3: //选通第四个数码管

wei1=1; wei2=1; wei3=1; wei4=0; if(a==0){P0=temperature1[t_d];}//若a=0则在第四个数码管上显示测量温度的小数位 if(a==1) //若a=1则在第四个数码管上显示上限报警温度的个位

{ if(s==0) P0=temperature1[max];//若s=0则显示第四个数码管,否则不显示

else P0=temperature3[0];

if(s1==1) P0=temperature1[max];//若s1=1则显示第四个数码管

//若a=2则在第

} if(a==2) 四个数码管上显示下限报警温度的个位 }

{

if(s==0) P0=temperature1[min]; else P0=temperature3[0];

if(s1==1) P0=temperature1[min]; } break; }

display_delay(10); //每个数码管显示3ms左右 }

/******************************************************/ /* 开机显示函数 /

/*****************************************************/ void display1(uint z) //用于开机动画的显示 {

uchari,j; bit f=0;

for(i=0;i

//‘z’是显示遍数的设定

for(j=0;j<4;j++)

//依次从左至右显示‘-’

{

switch(j) { case 0: wei2=1; wei3=1; wei4=1; wei1=0; break; P0=temperature3[2];//第一个数码管显示

case 1: wei1=1; wei3=1; wei4=1; wei2=0;break; P0=temperature3[2];//第二个数码管显示

case 2:

wei1=1; wei2=1;

wei4=1; wei3=0;break; P0=temperature3[2];//第三个数码管显示

case 3:

wei1=1; wei2=1; wei3=1;

wei4=0;break;

P0=temperature3[2];//第四个数码管显示

}

display_delay(400); //每个数码管显示200ms左右

} } }

#endif

六、参考文献

(1).郭天祥.51单片机c语言教程.电子工业出版社.2009.12

(2).李群芳.单片微型计算机与接口技术.电子工业出版社.2012.12

本文来源:https://www.bwwdw.com/article/9oba.html

Top