在進入正題之前不得不說,由于自己的一個錯誤,導緻此驅動寫了近3天,查閱了無數的資料,基本上都能把ds18b20的原理和使用過程背下來了,可以說有失有得,如果當初一兩次就成功了,可能也就不會深入的去查閱各種資料了。
下面進入正題,心得的角度從快速使用的角度出發。
開發闆将引腳設為輸出,發送一個高電平再拉低,維持480-960US;
引腳拉高釋放總線,主機等待60US-200US;
讀取引腳資料,0為初始化成功;1為初始化失敗;
讀取資料完畢後,延遲等待400US;
程式示範:
void de18b20_init_start(void)
{
int ack = 1;
gpio_direction_output(ds18b20.gpionum, 0); //驅動初始化已經将此GPIO配置輸出高電平,這裡直接就拉低了。
udelay(480);//延遲時間範圍,根據自己的闆子測試更改。
gpio_direction_output(ds18b20.gpionum, 1);//釋放總線等待響應
udelay(60);
ack = gpio_get_value(ds18b20.gpionum);//傳回值為0說明初始化成功,反則為1
printk("ack = %d\n",ack);
udelay(400);//配置完成後延遲400us
gpio_direction_output(ds18b20.gpionum, 1);
}
寫資料
引腳拉高2us,然後拉低(保持1us),産生一個下降沿,表示寫資料開始;
将要寫的1或0放在總線上;
整個過程在15us之内完成;
然後主機延時等待至少50us;
拉高釋放總線;
每寫兩位資料之間的間隔要大于1us;
程式示範
void ds18b20_wriet_data(unsigned char byte)
{
unsigned char i = 0;
for (i = 0; i < 8; i++) {
gpio_set_value(ds18b20.gpionum, 1); //拉高引腳
udelay(2);//保持2us
gpio_set_value(ds18b20.gpionum, 0); //拉低引腳,産生寫間隙
udelay(2); //簡單延時
gpio_set_value(ds18b20.gpionum, 1); //15us之内釋放總線
udelay(2); //簡單延時
gpio_set_value(ds18b20.gpionum, byte & 0x01); //将位元組低位寫入單總線
udelay(50); //在15~60us内等待DS18B20來采集信号
gpio_set_value(ds18b20.gpionum, 1); //釋放總線
byte >>= 1; //每次講要讀取的資料位移至最低位
udelay(2);
}
}
讀資料
拉高引腳,延時2us,然後拉低1us,産生一個下降沿,表示讀資料;
拉高釋放總線,必須在下降沿之後的15us内将端口資料讀取;
讀取資料後,延時60us;
每兩個資料位之間間隔大于1us;
程式示範
unsigned char de18b20_read_data(void)
{
unsigned char i = 0;
unsigned char byte = 0;
for (i = 0; i < 8; i++) {
gpio_set_value(ds18b20.gpionum, 1);//産生讀時序
udelay(2);
gpio_set_value(ds18b20.gpionum, 0);//産生讀時序
udelay(2); //簡單延時
gpio_set_value(ds18b20.gpionum, 1);//釋放總線
byte >>= 1; //先進行移位
if(gpio_get_value(ds18b20.gpionum))
{
byte |= 0x80;
printk("1\n");//調試資訊
}else{
printk("0\n");//調試資訊
}
udelay(60); //延時60us
gpio_set_value(ds18b20.gpionum, 1); //釋放總線
udelay(1);
}
return byte;
}
使用過程
ds18b20_init_start();//複位ds18b20
ds18b20_wriet_data(0xcc);
ds18b20_wriet_data(0x44);
//以上内容是告訴ds18b20,跳過ROM指令(0xcc),轉換溫度(0x44);
//此處需要等待溫度的轉換完成,可以使用延遲函數,也可以使用以下方法,等待第一時間轉換完整讀取資料。
while(!gpio_get_value(ds18b20.gpionum));
ds18b20_init_start();//複位ds18b20
ds18b20_wriet_data(0xcc);
ds18b20_wriet_data(0xbe);
//以上内容是告訴ds18b20,跳過ROM指令(0xcc),讀取溫度寄存器的值(0xbe);
//剩下就是調用read來讀取相應的數值了。