MCU:PIC16F690
系统频率:8MHZ
目的:实现对18b20 1-wire协议的实现,通过18b20测得环境温度;
18b20通过1-wire协议与主机实现通讯,1-wire协仪非常简单,关键问题是时序问题,只要时序没问题,就可以通过1-wire协议与18b20实现通讯;
测试过的程序如下:
/******************************************************************
** Function name :Reset_18b20(void)
** Description :reset the 18b20
** Input parameter :
******************************************************************/
void Reset_18b20(void)
{
DQ_OUT_HIGH();
Delay(10); //do nothing
DQ_OUT_LOW();
Delay(180); //output 0 delay about 639us(480~960us)
DQ_OUT_HIGH();
Delay(10); //output 1 delay about 45us(15~60us)
DQ_IN();
NOP();
while(DQ); //wait for the response
Delay(80); //the response delay 290us(60-240us)
}
/******************************************************************
** Function name :Write_18b20(unsigned char cmd)
** Description :write to the 18b20
** Input parameter :unsigned char cmd
******************************************************************/
void Write_18b20(unsigned char cmd)
{
unsigned char i;
for(i=0;i<8;++i)
{
if(cmd&(1<<i))
{
DQ_OUT_LOW();
Delay(1); //13us (1us-15us)
DQ_OUT_HIGH();
Delay(20); //delay 80us 写时隙至少60us
}
else
{
DQ_OUT_LOW();
Delay(20); //delay 80us 至少保持60us的时间
DQ_OUT_HIGH();
Delay(1); //delay 13us 时隙恢复至少1us的时间
}
}
}
/******************************************************************
** Function name :Read_18b20(void)
** Description :read from the 18b20
** Input parameter :
**Output parameter :unsigned char
******************************************************************/
unsigned char Read_18b20(void)
{
unsigned char i;
unsigned char result=0;
for(i=0;i<8;++i)
{
DQ_OUT_LOW();
Delay(0); //delay us 读时隙开始,至少1us的时间
DQ_IN(); //15us内读取
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
if(DQ)
{
result |= 1<<i;
}
Delay(1); //delay 13us 时隙恢复时间
}
return result;
}
/******************************************************************
** Function name :Read_temp(void)
** Description :read temperature
** Input parameter :
**Output parameter :unsigned int
******************************************************************/
unsigned int Read_temp(void)
{
unsigned char templ;
unsigned char temph;
unsigned int result=0;
Reset_18b20();
Write_18b20(0xCC); //跳过rom
Write_18b20(0x44); //温度转化命令
Delay(200); //delay us (200~300us)
Delay(200);
Delay(200);
Reset_18b20();
Write_18b20(0xCC); //跳过rom
Write_18b20(0xBE); //读取温度命令
templ=Read_18b20();
temph=Read_18b20();
signal_flag = 0;
if(temph & 0xF0) //读取温度为零下负值,此时将温度高8位取反,低8位取反后加1,即可获得正确温度值
{
temph = ~temph;
templ = ~templ+1;
signal_flag = 1;
}
result=temph;
result=result<<8;
result|=templ;
result =(float)result * 0.625; //精确到1位小数点
return result;
}