标题:
单片机DS18b20温度检测程序
[打印本页]
作者:
zhangjinyu
时间:
2022-9-21 00:37
标题:
单片机DS18b20温度检测程序
#include<reg51.h> //51单片机的头文件
#define uchar unsigned char //宏定义,用uchar来代替unsigned char(无符号字符型变量,也即是无符号的8位变量),
//宏定义的原因就是书写方便,宏定义后,uchar可直接用来定义变量
#define uint unsigned int //原因同上,不过要注意,unsigned int为无符号的整型变量
uint present; // 实际温度(扩大了10倍)
uint setting=30; //设定值
sbit led=P3^5; //sbit是用来管脚的。此处定义LED灯由P3.5口控制
sbit buzzer=P3^6; //蜂鸣器由P3.6口控制
sbit DS=P3^7; //读取温度引脚
sbit NixieTube0_DIG1=P1^2; // 实际温度显示十位数字的数码管位选端
sbit NixieTube0_DIG2=P1^3; //// 实际温度显示个位数字的数码管位选端
sbit NixieTube1_DIG1=P1^4; //// 设定温度显示十位数字的数码管位选端
sbit NixieTube1_DIG2=P1^5; //// 设定温度显示个位数字的数码管位选端
sbit add=P1^0; //按键加
sbit sub=P1^1; //按键减
unsigned char code table[]={0x82,0xF3,0x4A,0x62,0x33,0x26,0x06,0xE3,0x02,0x22}; //数码管端码表,相当于显示缓冲区,依次是0——9.
void delay(uint count) //延时函数,用来进行延时,应该是毫秒级延时
{
uint i;
while(count) // count为函数的形参,当count为0时,跳出此处while循环
{
i=200;
while(i>0) //
i--; //此i--和while(i>0)可以看成是一个整体,当i=0时,就会跳出,执行count--。
count--; //count自减一次,i就会由200减到0
}
}
/***********************************************************
void initialize(void)//初始化函数
温度传感器采用的是DS18b20,此传感器采用的
是“单总线”来传输数据。
在使用DS18b20时,要对其进行初始化操作,其初始化的要求是(根据DS18b20的时序图得):
(1)先将数据线置1,但是置1的时间要尽可能短(可以直接忽略此操作,因为51单片机引脚上电默认就是高电平。)。
(2)将数据线(DS)拉低
(3)延时750us左右
(4)再将数据线(DS)拉高
(5)进行短暂延时
*****************************************************************/
void initialize(void) //初始化
{
uint i;
DS=0; //将DS(P3.7)引脚拉低。请注意,这里的DS不是变量,而是单片机的引脚!!!
i=103;
while(i>0)i--; //延时
DS=1; //将DS拉高
i=4;
while(i>0)i--; //短暂延时
}
/*************************************************************************************
说明:DS18b20采用的是单总线,一次只能读取温度的1个Bit。
函数作用:bit tmpreadbit(void) //温度读取函数,此处读取的是温度的1个bit,带返回值
函数使用举例:A=tmpreadbit(); // 变量A保存的只是温度的一个bit
DS18B20温度读取时序用单片机来实现的步骤如下:
(1) 数据线DS拉低
(2) 延时6us左右
(3)将数据线DS拉高
(4)延时4us左右
(5) 此时DS便会得到一个状态位,即1个Bit的数据
(6)延时30us左右
**************************************************************************************/
bit tmpreadbit(void) //温度读取函数,此处读取的是温度的1个bit.带返回值
{
uint i;
bit dat;
DS=0;i++; //将数据线拉低并延时
DS=1;i++;i++; //将数据线拉高并延时
dat=DS; //读取1个bit数据,此处注意,DS变成了输入引脚,DS18b20的数据会保存到局部变量dat中
i=8;while(i>0)i--; //延时
return (dat); //将读取的数据返回
}
/***********************************************************************************************
说明:DS18b20采用的是单总线,一次只能读取温度的1个Bit。温度一共8个bit,此函数共读了8次
函数作用:uchar tmpread(void) //温度读取函数,此处读取的是温度数据的原始数据,带返回值
函数使用举例:A=tmpread(); // 变量A保存的是温度的原始数据
*************************************************************************************************/
uchar tmpread(void)
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++) //采用for 循环,读取原始温度数据
{
j=tmpreadbit(); //读取一个位
dat=(j<<7)|(dat>>1);//读取的温度最低位在前,这样刚好一个字节的温度在dat中
}
return(dat); //将温度数据返回
}
void tmpwritebyte(uchar dat) // 写指令函数, dat为形参。
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++) //for循环,8次,刚好写一个字节
{
testb=dat&0x01; //将形参的最低位与1相与,1&1=1,0&1=0;
dat=dat>>1; //执行完testb=dat&0x01;把传入的形参右移一位,方便判断下一位数据是0还是1,共移位8次,保证写入一个字节
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1; //DS=1的延时比较长,写入的就是1
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;while(i>0)i--; //DS=0的延时比较长,写入的就是0
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //温度转换函数,
{
initialize(); //初始
delay(1);
tmpwritebyte(0xcc); //跳过读ROM指令
tmpwritebyte(0x44); //告诉DS18b20转换温度
}
uint tmp() //转换函数,将原始数据转化成实际的温度数据
{
float tt;
uchar a,b;
initialize(); //初始化
delay(1); //延时
tmpwritebyte(0xcc);//跳过读ROM指令
tmpwritebyte(0xbe); //读温度指令
a=tmpread(); // 低8位数据,即温度的小数部分
b=tmpread(); //高8位,即温度的整数部分
present=b;
present<<=8; //将整数部分右移8位
present=present|a; //将两个字节组合成一个字
tt=present*0.0625; //分辨率是0.0625,即原始数据*分辨率=实际温度
present=tt*10+0.5; //乘10表示小数点后面只取一位,+0.5是表示四舍五入
return present; //返回实际温度
}
//用的是共阳极数码管,显示原理采用的是动态显示
void display0(uint temp) //温度显示函数 ,temp 为形参
{
uchar A1,A2,A2t;
////此处注意!因温度读取函数中 present=tt*10+0.5;即将温度扩大了10倍,所以原始温度的十位变成了百位,
//各位变成了十位,十分位变成了个位,因此我们只需取百位上的数字和十位上的数字即可。注意,是数字,不是数!
A1=temp/100; //取模,将百位数字取下,存到变量A1中,
A2t=temp%100; //取余,比如传进来的temp=325,则325%100=25;
A2=A2t/10; //将余数对10取模,比如 25/10=2;
NixieTube0_DIG1=1; //打开数码管位选端
if(A1<=9|A1>=0) //判断A1是否位一位数字,实际温度的十位上的数字
P2=table[A1]; //送入显示
delay(1); //延时,待显示稳定
NixieTube0_DIG1=0; // 关断数码管
NixieTube0_DIG2=1; //打开数码管位选端
if(A2<=9|A2>=0) //判断A2是否位一位数字,实际温度的个位上的数字
P2=table[A2]; //送入显示
delay(1); //延时,待显示稳定
NixieTube0_DIG2=0; // 关断数码管
}
void display1(uint spare) //设定温度显示
{
uchar B1,B2;
B1=spare/10; //将设定温度对10取模,获取十位上的数字
B2=spare%10; //将设定温度对10取余,获取个位上的数字
NixieTube1_DIG1=1; ////打开数码管位选端
P2=table[B1]; //送入十位上的数字
delay(1); ////延时,待显示稳定
NixieTube1_DIG1=0; //关断显示
NixieTube1_DIG2=1; //打开显示
P2=table[B2]; //送入个位上的数字
delay(1); //延时,待显示稳定
NixieTube1_DIG2=0; //关断显示
}
void main() //主函数
{
uchar a;
uchar b;
uchar c;
P2=0xf7; //对P2口初始化,开机先不让数码管显示
NixieTube0_DIG1=1; //初始化,数码管位选端拉高
NixieTube0_DIG2=1; //同上
NixieTube1_DIG1=1; //同上
NixieTube1_DIG2=1; //同上
buzzer=0; //蜂鸣器引脚拉低,上电,蜂鸣器响一秒
delay(1000); //延时1S左右
while(1)
{
tmpchange();//向温度传感器写入温度转换指令
if(add==1) //如果 按键加 没有按下
b=1; //b=1;b的作用相当于松手检测
if(add==0&b==1) //如果按键按下
{
if(setting==99)
{}
else
{
setting++;//设定值自加一次
b=0; //只有按下松手后,再按 按键加 才能再次使设定值自加一次
}
};
if(sub==1) //按键减未被按下
c=1; //作用与b相同
if(sub==0&c==1) //如果按键减 被按下
{
if(setting==0)
{}
else
{
setting--;//设定值自减一次
c=0; //作用同上面的b
}
};
if(present<=setting*10) //如果实际温度小于设定温度
{
buzzer=0; //蜂鸣器不响
led=0; //灯亮
}
else
{
buzzer=0; //否则 蜂鸣器响
led=1; //灯不亮
}
for(a=10;a>0;a--)
{
display0(tmp()); //显示实际温度
display1(setting); //显示设定温度
}
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1