📄 ds18b20.c
字号:
#include "system.h"
//----------------DS18B20温度读取程序-----------------
//OneWire.c文件,用于操作DS18B20/DS2401等单总线器件
//注意实际硬件工作的频率
volatile unsigned char EnableOneWireFlag=1; //用户设置的DS18B20使能标志
volatile unsigned char OneWireConnectFlag=1; //DS18B20连接标志
volatile unsigned int DataT=150; //实际测得的温度值
volatile unsigned char _T=1; //正负温度标志:<16为正 >15为负
volatile unsigned char DataT_shi=0; //温度的十位
volatile unsigned char DataT_ge=0; //温度的个位
volatile unsigned char ProcessReadT=_ConvertT; //读取DS18B20温度时的进程,0:启动(复位)DS18B20; 1:读取温度并计算数值
volatile unsigned char ReadTFlag=0; //读取DS18B20温度时,启动温度转化等待200ms,开启计数器的标志
volatile unsigned char ReadTCounter=0; //读取DS18B20温度时,启动温度转化等待200ms计数器
volatile unsigned char TChangeFlag=0; //温度变化标志位
volatile unsigned char LastT=150; //上一次测得的温度值
volatile unsigned char TWarningFlag=0; //温度警告标志
volatile unsigned char OneWireID[8]; //DS18B20 ROM ID
volatile unsigned char TemperatrueBuffer[6]; //百位.十位.个位..十分位.百分位.千分位.
volatile unsigned int CheckDS18B20Counter=0; //重检DS18B20计时器
volatile unsigned char CheckDS18B20TimeoutFlag=0; //重检DS18B20定时到时标志
prog_uchar Crc8Table[256]={
0,94, 188,226,97,63,221,131,194,156,126,32,163,253,31, 65,
157,195,33,127,252,162,64,30,95,1,227,189,62,96,130, 220,
35,125,159,193,66,28,254,160,225,191,93,3,128,222,60, 98,
190,224,2,92,223,129,99,61,124,34,192,158,29,67,161, 255,
70,24,250,164,39,121,155,197,132,218,56,102,229,187,89, 7,
219,133,103,57,186,228,6,88,25,71,165,251,120,38,196, 154,
101,59,217,135,4,90,184,230,167,249,27,69,198,152,122, 36,
248,166,68,26,153,199,37,123,58,100,134,216,91,5,231, 185,
140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
202,148, 118,40,171,245,23,73,8,86,180,234,105,55,213,139,
87,9,235,181,54,104,138,212,149,203,41,119,244,170,72, 22,
233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53};
//#define Crc8Table(i) (pgm_read_byte(Crc8Table+(i)))
unsigned char CRC8(unsigned char *checkbuf,unsigned char checkbyte)
{
unsigned char i;
unsigned char crcdata;
for(i=0;i<checkbyte;i++)
{
crcdata=pgm_read_byte(Crc8Table+(crcdata^(*(checkbuf+i))));
}
return crcdata;
}
void OneWireInit(void) //复位
{
unsigned int i=0;
OneWireDDR |= (1<<DS18B20);
OneWirePORT |= (1<<DS18B20);
OneWirePORT &=~(1<<DS18B20);
_delay_us(200); //480~960us
_delay_us(200);
_delay_us(200);
_delay_us(100);
OneWirePORT |= (1<<DS18B20);
OneWireDDR &=~(1<<DS18B20);
_delay_us(90); //15~60us
while(OneWirePIN&(1<<DS18B20)) //注意此处如果检测不到DS18B20,那会产生温度报警,但是不能影响正常工作.
{
i++;
if(i>=500) //注意此处i的大小要根据测温器件与系统的连接线的长短而定
{
OneWireConnectFlag=0;
return;
}
}
OneWireConnectFlag=1;
OneWireDDR |= (1<<DS18B20);
OneWirePORT |= (1<<DS18B20);
_delay_us(240); //60~240us
}
void ReadOneWireID(void)
{
unsigned char i;
OneWireInit();
WriteOneWire(0x33); //ReadROM(读ROM) [33h]
for(i=0;i<8;i++)
{
OneWireID[i]=ReadOneWire();
}
}
void WriteOneWire(unsigned char Data) //向单总线的从机写入数据(先写低位再写高位,与SPI相反)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWirePORT&=~(1<<DS18B20);
if(Data&(1<<i))OneWirePORT|=(1<<DS18B20);//写数据了,先写低位的!
else OneWirePORT&=~(1<<DS18B20);
_delay_us(60); //15~60us
OneWirePORT|=(1<<DS18B20);
}
OneWirePORT|=(1<<DS18B20);
_delay_us(3);
}
unsigned char ReadOneWire(void)
{
unsigned char temp;
unsigned char n;
unsigned char OneWireData=0;
for(n=0;n<8;n++)
{
OneWirePORT &=~(1<<DS18B20);
OneWirePORT |= (1<<DS18B20);
OneWireDDR &=~(1<<DS18B20);
temp=(OneWirePIN&(1<<DS18B20)); //读数据,从低位开始
if(temp)OneWireData |= (1<<n);
else OneWireData &=~(1<<n);
_delay_us(120); //60~120us
OneWireDDR |= (1<<DS18B20);
}
return OneWireData;
}
void ReadTemperature(void) //读取温度值
{
unsigned char i;
unsigned char OneWireData[8];
if(ProcessReadT==_ConvertT)
{
OneWireInit(); //复位DS18B20
WriteOneWire(0xcc); //跳过ID码匹配,适用于一个DS18B20
WriteOneWire(0x44); //启动温度转换
ReadTFlag=1;
}
else if(ProcessReadT==_ReadT)
{
ProcessReadT=_ConvertT;
OneWireInit();
WriteOneWire(0xcc); //跳过ID码匹配,适用于一个DS18B20
WriteOneWire(0xbe); //通知DS18B20,准备读数据
for(i=0;i<8;i++)
{
OneWireData[i]=ReadOneWire();
//TEMPERATURELSB 0
//TEMPERATUREMSB 1
//TH/USERBYTE1 2
//TL/USERBVTE2 3
//RESERVED 4
//RESERVED 5
//COUNTREMAIN 6
//COUNTPER 7
//CRC 8
}
/*
UartSendByte(OneWireData,8);
OneWireData[7]=CRC8(OneWireData,7);
UartSendByte(OneWireData,8);
_delay_ms(3);
OneWireInit();
ReadOneWireID();
UartSendByte(OneWireID,8);
OneWireID[7]=CRC8(OneWireID,7);
UartSendByte(OneWireID,8);
*/
// if(OneWireData[7]==CRC8(OneWireData,7))
{
if(OneWireData[1]<16)
{
_T=1;
}
DataT=OneWireData[1]*256+OneWireData[0];//合并后得到原始温度数据
if(_T) //+
{
DataT=DataT/16;
}
else //-
{
DataT=(~DataT+1)/16;
}
//计算实际温度 -55~+125 器件以0.0625摄氏度递增
//如果温度为正 则T的最高位的4位都为0 否则为1;
//负温度的计算:原始数据取反 加1 再乘以0.0625;正温度的计算:原始数据乘以0.0625
if((DataT!=85)&(DataT!=95))
{
TemperatrueBuffer[0]=DataT/100; //100
TemperatrueBuffer[1]=DataT/10%10; //10
TemperatrueBuffer[2]=DataT%10; //1
DataT%=0xff;
DataT*=625;
TemperatrueBuffer[3]=DataT/100%10; //.1
TemperatrueBuffer[4]=DataT/10%10; //0.01
TemperatrueBuffer[5]=DataT%10; //0.001
}
else
{
for(i=0;i<8;i++)
{
TemperatrueBuffer[i]=0;
}
UartSendString((unsigned char *)"测温异常!");
UartSendString((unsigned char *)"\r\n");
}
}
}
}
//温度处理函数,按照用户设定,有温度报警时,可以有一个IO进行开启或关闭操作.
//目前软件设定是一个加热设备.低温开启IO,高温关闭IO.
//在参数设置中,可以设置是否启用温度报警IO机制
void TemperatureProcessing(void)
{
unsigned char temp[10]={'\0'};
UartSendString((unsigned char *)"当前温度是:");
if(_T) //+
{
if(TemperatrueBuffer[0]) //最高百位
{
sprintf(temp,"%d%d%d.%d%d%d",TemperatrueBuffer[0]%256,TemperatrueBuffer[1]%256,TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
}
else if(TemperatrueBuffer[1]) //最高十位
{
sprintf(temp,"%d%d.%d%d%d",TemperatrueBuffer[1]%256,TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
}
else //最高个位
{
sprintf(temp,"%d.%d%d%d",TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
}
}
else //-
{
if(TemperatrueBuffer[1]) //最高十位
{
sprintf(temp,"-%d%d.%d%d%d",TemperatrueBuffer[1]%256,TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
}
else //最高个位
{
sprintf(temp,"-%d.%d%d%d",TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
}
}
UartSendString(temp);
UartSendString((unsigned char *)"℃");
UartSendString((unsigned char *)"\r\n");
}
void DS18B20Processing(void)
{
if(OneWireConnectFlag)
{
ReadTemperature();
TemperatureProcessing();
}
else
{
if(EnableOneWireFlag)//如果的确设置的测温器件,那么隔ns检测一下器件是否重新连接
{
if(CheckDS18B20TimeoutFlag)
{
CheckDS18B20TimeoutFlag=0;
OneWireInit();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -