📄 18b20.c
字号:
/*数字温度计,支持负温度,温度超限报警,远程采集温度等功能*/
/*下位机温度显示采用4位数码管显示,精确度:0.1*/
/*温度超限报警,设置温度高低限,超限触发蜂鸣器报警*/
/*远程温度采集,上位机软件实时读取现场温度*/
#include <REGX51.H>
//#include<port.h>
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^6;
void BeepOn();
//共阳段码表
//字节的高位对应数码管的H段,依次类推
uint j=0;
uchar dispbitcode[8]={0xf7,0xfb,0xfd,0xfe/*,0xef,0xdf,0xbf,0x7f*/}; //位扫描
uchar dispcode[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc6,0xff};
//共阳数码管字段码 0xc6表示C温度符号。
uchar dispbuf[4]={0x00,0x00,0x00,0x00};
uchar data tplsb,tpmsb; // 温度值低位、高位字节
uchar flag=0; //负温度标志位
//**************************************************************/
// 延时子函数11uS
void delay(uint t)
{ for (; t>0 ; t--) ;
}
/************************************************************
/*DS18B20复位函数: 产生复位脉冲初始化DS18B20 */
void ow_reset(void)
{ char presence=1;
while(presence)
{
while(presence)
{
DQ=1;
_nop_();
_nop_();//从高拉倒低
DQ=0;
delay(50); //550 us
DQ=1;
delay(6); //66 us
presence=DQ; //presence=0 复位成功,继续下一步
}
delay(45); //延时500 us
presence=~DQ;
}
DQ=1; //拉高电平
}
/************************************************************
向 1-WIRE 总线上写一个字节**数据线从高电平拉至低电平,产生写起始信号。
15ms之内将所需写的位送到数据线上
**************************************************************/
void write_byte(uchar val)
{
uchar i;
for (i=8; i>0; i--) //在15~60us之间对数据线进行采样,如果是高电平就写1,低写0发生。
{
DQ = 1;
_nop_();
_nop_(); //在开始另一个写周期前必须有1us以上的高电平恢复期。
DQ = 0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //5us
DQ = val&0x01; //最低位移出
delay(6) ; //66us
val = val/2; //右移1位 val=val>>=1;
}
delay(1);
}
/************************************************************
//读1字节 //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
**************************************************************/
uchar read_byte (void)
{
uchar i;
uchar value = 0;
for(i = 8;i>0;i--)
{
DQ = 1; // 给脉冲信号
_nop_();
_nop_();
value>>= 1;
DQ = 0; // 给脉冲信号
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //5us
DQ = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();//5us
if(DQ)
{ value|= 0x80 ; }
delay(13); // 注意延时的长短,如果是delay(6) 会造成LED闪烁
}
DQ = 1;
return(value) ;
}
/*--------------------------------------------------------------------------------------
设置DS18B20转换精度及报警**见配置寄存器说明** 增加功能,在此设置,如温度报警
-----------------------------------------------------------------------------------------*/
void Setting_DS18B20(void)
{
ow_reset();
write_byte(0xCC); // 跳过读序号列号的操作
write_byte(0x4e); //向18B20的暂存器TH和TL中写入数据
write_byte(0x64); //不使用DS18B20本身的温度告警设置,为进行转换精度设定,凑两个写寄存器操作
write_byte(0x8a); //-10
write_byte(0x7f); //设置DS18B20 为12位转换精度 R1,R0的值决定转换精度 R1=R0=1对应12位
}
/*--------------------------------------------------------------------------------------
读取温度并完成转化,
-----------------------------------------------------------------------------------------*/
void Read_Temperature(void)
{
float tt,cc;
ow_reset();
write_byte(0xCC); // 跳过读序号列号的操作
write_byte(0x44); // 启动温度转换
ow_reset();
write_byte(0xCC); //跳过读序号列号的操作
write_byte(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
tplsb=read_byte(); // 温度值低位字节(其中低4位为二进制的“小数”部分)
tpmsb=read_byte(); // 高位值高位字节(其中高5位为符号位
ow_reset();
j=tpmsb;
j<<=8;
j+=tplsb; //写为j=j|tplsb;也可以。// 两字节合成一个整型变量。
if(tpmsb>7)
{
j=(j^0xffff);//异或
j=j+1; //如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。
}
tt=(j*0.0625);
j=tt*10+0.5; //四舍五入成整数,并扩大十倍 此处暂不考虑符号
dispbuf[3]=j/100%10; //十位
dispbuf[2]=j/10%10; //个位
dispbuf[1]= j%10;//取温度小数点1位
dispbuf[0]=10; //表示温度符号C
///////////////////////温度报警。。。。。设置
cc=j;
cc=cc/10;
if(cc>30.0) //设置温度上限为30摄氏度
{
BeepOn();
}
///////////////////////
}
void BeepOn()
{
uchar i;
for(i=0;i<10;i++)
{
P3_3=~P3_3;
delay(50);
}
}
/*------------------------------------------------------------------------
温度显示
-------------------------------------------------------------------------*/
void Display(void)
{
uint k;
/*******************温度为负,求补码*******************************/
if(tpmsb>127)
{
tpmsb=256-tpmsb;
tplsb=256-tplsb;
flag=1;
}
/****************************************************************/
//////////////////////////////////////////
if(flag) //负温度时,最高位显示“-”,温度为依次左移,屏蔽掉最低位的C
{
dispbuf[3]=0x0B;
dispbuf[2]=j/100%10; //十位
dispbuf[1]=j/10%10; //个位
dispbuf[0]= j%10;//取温度小数点1位
for(k=0;k<4;k++)
{
P0 = dispbitcode[k];
P2 = dispcode[dispbuf[k]];
delay(30);
if(k==1) //加上数码管的dp小数点
P2&=0x7f;
delay(40);
P0=0xff;
}
}
/////////////////////////////////////////
for(k=0;k<4;k++)
{
P0 = dispbitcode[k];
P2 = dispcode[dispbuf[k]];
delay(30);
if(k==2) //加上数码管的dp小数点
P2&=0x7f;
delay(40);
P0=0xff;
}
}
/*------------------------------------------------------------------------
主函数
--------------------------------------------------------------------*/
void main ()
{
unsigned char h;
///////////开机显示8888/////////////////
for(h=0;h<4;h++)
{
P0 = dispbitcode[h];
P2 = dispcode[8];
delay(60000);
P0=0xff;
}
//////////////////////////////////////////
//初始化DS18B20
Setting_DS18B20();
while(1)
{
Read_Temperature();
_nop_();
_nop_();
_nop_();
Display();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -