一、前言
在我们学习51单片机的过程中,提到温度测量,很多同学的第一反映一定是DS18B20温度传感器。DS18B20是一款物美价廉且十分简单的传感器,它的体积小,测量精度高,使得其成为很多同学的选择。但其实,除了DS18B20,还有一些其他的温度传感器可以选择,例如PT100温度变送器,它将温度信号转变为可以观测到的电信号。在日程生活中,我们所能买到的PT100,一般都是已经设计好的温度变送器,可以将0-100的温度变换为1-5V的电压,不再需要我们去自己调节。
本文将通过一个滑动变阻器模拟出PT100温度变送器所产生的4-20mA电流。首先,我们制定程序实现的功能如下:
-
读取PT100温度变送器产生的电流通过电阻转换为1-5V电压(滑动变阻器模拟)产生的电压,将其通过ADC0804芯片转换为数字信号。
-
读取转换后的数字信号,进行数字滤波。本文采取平均值滤波。
-
将过滤后的数字信号通过标度变换转换为温度值
-
将温度值通过LED数码管显示。本文采取四位数码管进行显示,包含一位小数。
-
当温度高于某一设定值时(本文为70摄氏度),启动蜂鸣器报警。
为了方便大家学习与测试,文末附有源码与仿真文件。如有疏漏错误之处,还请多包涵并指出。
二、装置介绍
本次实验涉及的装置如下:AT89C51芯片、12MHZ晶振、复位按钮、ADC0804芯片、1K欧姆滑动变阻器,1K欧姆电阻,蜂鸣器、三极管。
-
ADC0804
这是一个8位的AD转换芯片,可以将0-5V电压转换为0-255的数字。关于其的使用,网上的资料很多,这里就不在多加赘叙。
![](https://img-blog.csdnimg.cn/img_convert/32562ca106fa23bdb84cfc5b3584afe4.png)
-
蜂鸣器
本文采取的是低电平触发的有源蜂鸣器。顾名思义,即当控制引脚为低电平时,蜂鸣器响起。由于芯片引脚电流较小,无法驱动蜂鸣器,我们一般需要增加一个三极管用来驱动。
![](https://img-blog.csdnimg.cn/img_convert/807f97170eb9768272cd02099fb11f07.png)
-
温度变送器
![](https://img-blog.csdnimg.cn/img_convert/e333097cf14c46c8c9d0b2f46675f61b.png)
-
LED数码管
![](https://img-blog.csdnimg.cn/img_convert/26ab7614784d046223ed642ce7300612.png)
三、代码展示
#include <reg51.h>
#include <intrins.h>
sbit adrd=P3^7; //ADC0804IO口定义
sbit adwr=P3^6;
sbit adcs=P3^4;
sbit intr=P2^2;
sbit w1=P2^0; //数码管引脚定义
sbit w2=P2^1;
sbit w3=P2^3;
sbit w4=P2^4;
sbit dp=P2^5;
sbit buzzer=P2^7; //蜂鸣器引脚
unsigned char ad_data;
int t_data;
unsigned char i, j;
unsigned int t_temp;
unsigned char data_1=0,data_2=0,data_3=0,data_4=0,data_5=0;
void ad0804(); //ADC0804函数声明
void number(); //数字滤波函数声明
void display(); //LED显示函数
unsigned char seg7code[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x40}; //LED共阴字码
unsigned char n_1,n_2,n_3,n_4;
/*函数:延时函数
功能:实现约2us延时*/
void delay(unsigned int t)
{
for(;t>0;t--);
}
/*函数:AD转化程序(ADC0804)
功能:将输入电压信号转为数字信号
基准电压:5V*/
void ad0804 ()
{
P1=0xff;
adcs=0; //芯片有效,启动时序
adwr =0; //启动ADC0804进行ADC采集
delay(2); //延时片刻
adwr =1; //高电平变低电平触发一次ADC转换
while(intr); // ADC转换完成后intr = 0
adcs=0; //芯片有效,读数据时序
adrd=0; //启动读数
delay(10);
number(); //读数并进行数字滤波
adrd=0;
adrd=1;
delay(10); /*使INTR引脚自动拉高,
为下一次转化做准备*/
}
/*函数:数字滤波函数
功能:读数并进行平均值数字滤波*/
void number ()
{
switch(j)
{
case 1 : data_1=P1; break;
case 2 : data_2=P1; break;
case 3 : data_3=P1; break;
case 4 : data_4=P1; break;
case 5 : data_5=P1; break;
}
ad_data=(data_1+data_2+data_3+data_4+data_5)/5;
}
/*函数:温度转换函数
功能:将ADC0804数值转化为摄氏度值*/
void ad_compute()
{
t_data=ad_data-51;
if(ad_data>=51)
{
t_temp=(t_data/2.04)*10; //数值转化
n_1=t_temp/1000;
n_2=t_temp/100-n_1*10;
n_3=t_temp/10-n_1*100-n_2*10;
n_4=t_temp%10;
}
if(ad_data<51)
{
n_1=n_2=n_3=n_4=10;
}
}
/*函数:LED显示函数
功能:将温度数用四位LED显示,包含一位小数*/
void display()
{
w1=0;
dp=0;
P0=seg7code[n_1]; //温度数值百位
delay(5);
w1=1;
w2=0;
dp=0;
P0=seg7code[n_2]; //温度数值十位
delay(5);
w2=1;
w3=0;
dp=1;
P0=seg7code[n_3]; //温度数值个位
delay(5);
w3=1;
w4=0;
dp=0;
P0=seg7code[n_4]; //小数位
delay(5);
w4=1;
}
void main() //主程序
{
TMOD=0x11; //定时器T0的模式1
TH0=0x3c; //定时器T0初值设置,实现1ms定时
TL0=0xb0;
TH1=0x3c; //定时器T1初值设置,实现50ms定时
TL1=0xb0;
TR0=0;
TR1=1;
EA=1; //总中断使能
ET0=1; //定时中断T0使能
ET1=1; //定时中断T1使能
while(1)
{
ad0804(); //ADC0804函数
ad_compute(); //数字滤波
display(); //LED显示
if(t_temp>700||ad_data<51)
{
TR0=1;
}
if(ad_data>=51&&t_temp<=700)
{
buzzer=1; //有源低电平蜂鸣器
TR0=0;
}
}
}
/*函数:定时中断T0函数
功能:实现蜂鸣器发声*/
void timer_t() interrupt 1
{
i++;
if(i==20)
{
i=0;
buzzer=~buzzer;
}
}
/*函数:定时中断T1函数
功能:产生50MS标志*/
void timer_tt() interrupt 3
{
j++;
if(j==6)
{
j=0;
}
}
四、仿真展示
![](https://img-blog.csdnimg.cn/img_convert/9d32a99473db346451f1124987aa6c4d.jpeg)
五、流程图
![](https://img-blog.csdnimg.cn/img_convert/e21fb6dbfa7627084f56d57afa9c50f4.png)
六、程序源码与仿真文件
链接:https://pan.baidu.com/s/1EDGfaHu0CYNNKCPXm5JQlw?pwd=b339
提取码:b339
欢迎大家下载测试,如果本文有帮助到您,烦请您点个赞。