基于WinAVR的DS18B20源程序
#define _DS18B20_C_
本文引用地址:http://butianyuan.cn/article/201611/320578.htm
#define DQ_18B20 (1<<3) // PD3
#define DQ_TO_0() (DDRD |= DQ_18B20) // PD3=’0′
#define DQ_TO_1() (DDRD &= ~DQ_18B20) // PD3=’float’
#define DQ_status() (PIND & DQ_18B20) // read PD3 pin
#ifndef CPU_CRYSTAL
#define CPU_CRYSTAL (11.0592)
#endif
#define wait_us(us)
_delay_loop_2((INT16U)((us)*CPU_CRYSTAL/4))
// 1個(gè)初始化模塊
void ds18b20_config(void); // 配置端口
// 3個(gè)基本模塊
BOOL ds18b20_reset(void); // 復(fù)位DS18B20
void ds18b20_write(INT8U dat); // 寫字節(jié)到DS18B20
INT8U ds18b20_read(void); // 讀字節(jié)從DS18B20
// 2個(gè)應(yīng)用模塊
void convert_T(void); // 啟動溫度轉(zhuǎn)換
INT16U read_T(void); // 讀取轉(zhuǎn)換值
void ds18b20_config(void)
{
DDRD &= ~DQ_18B20; // 輸入模式(上電時(shí)為高電平)
PORTD &= ~DQ_18B20; // 輸出鎖存器寫0,以后不再更改
}
BOOL ds18b20_reset(void)
{
BOOL bus_flag;
DQ_TO_0(); // 設(shè)置1-wire總線為低電平(占領(lǐng)總線)…
wait_us(490); // 490us
cli(); // 下面這段時(shí)間要求比較嚴(yán)格,為保險(xiǎn)起見,關(guān)中斷
DQ_TO_1(); // 設(shè)置1-wire總線為高電平(釋放總線)
wait_us(67.5); // 最佳時(shí)間: 60us+7.5us!(忙延時(shí),只是一種策略)
// 探測總線上是否有器件
if(DQ_status()) bus_flag=FAIL; // 復(fù)位單總線但沒有發(fā)現(xiàn)有器件在線
else bus_flag=SUCC; // 復(fù)位單總線并發(fā)現(xiàn)有器件在線
sei(); // 退出臨界代碼區(qū)(開中斷)
wait_us(490-67.5); // 490-67.5us
return(bus_flag);
}
void ds18b20_write(INT8U dat)
{
INT8U count;
// 每個(gè)字節(jié)共8位,一次發(fā)一位
for(count=0; count<8; count++) {
cli(); // 保證絕對不會發(fā)生中斷!
DQ_TO_0(); // 設(shè)置1-wire總線為低電平
wait_us(2); // about 2us
if(dat&0×01) DQ_TO_1(); // 并串轉(zhuǎn)換,先低位后高位
else DQ_TO_0();
dat >>= 1; // 下一位做好準(zhǔn)備
// 60us~120us(實(shí)際不能到120us, 因?yàn)槠渌Z句也用時(shí)間了!)
wait_us(62); // 62us
DQ_TO_1();
sei(); // 恢復(fù)系統(tǒng)中斷
wait_us(2); // 2us
}
}
INT8U ds18b20_read(void)
{
INT8U count,dat;
dat = 0×00; // 數(shù)據(jù)接收準(zhǔn)備
// 每個(gè)字節(jié)共8位,一次收一位
for(count=0; count<8; count++) {
cli(); // 保證絕對不會發(fā)生中斷!
// 從總線拉低到讀總線狀態(tài),不能大于15us!
DQ_TO_0(); // 設(shè)置1-wire總線為低電平(拉低總線以同步)
wait_us(2); // 2us
DQ_TO_1(); // 設(shè)置1-wire總線為高電平(釋放總線)
wait_us(4); // 4us
dat >>= 1;
if(DQ_status()) dat|=0×80; // 讀取總線電平,先收低位再收高位
sei(); // 恢復(fù)系統(tǒng)中斷
wait_us(62); // 必須大于60us
}
return(dat);
}
void convert_T(void)
{
if(ds18b20_reset()==SUCC) { // 如果復(fù)位成功
ds18b20_write(0xcc); // 跳過多器件識別
ds18b20_write(0×44); // 啟動溫度轉(zhuǎn)換
}
}
INT16U read_T(void)
{
INT16U value=0;
if(ds18b20_reset()==SUCC) { // 如果復(fù)位成功
ds18b20_write(0xcc); // 跳過多器件識別
ds18b20_write(0xbe); // 讀暫存器
value = (INT16U)ds18b20_read(); // 低字節(jié)
value += (INT16U)(ds18b20_read())<<8; // 高字節(jié)
}
return(value);
}
#endif
評論