调试了很久的DS18B20驱动,前些日子出现的问题一直是读出为0 ,卡了4天之后终于解决了,之前在控制口没有加上拉电阻,
后来想到可能是这个问题,加了个大电阻,果然好了~
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEV_NAME "ds18b20"
#define PFX "ds18b20: "
#define ds18b20_MINOR 120 /*minor number of this ds18b20*/
/*commad*/
#define SKIP_ROM 0xCC /*skip rom operation*/
#define TEMP_CONVET 0x44 /*start temperature convertion*/
#define READ_TEMP 0xBE /*start read temperature*/
#define HIGH 1
#define LOW 0
static int char_major=231;
unsigned char data[2];
/*
* ds18s20_set_input:
*
* @action: set input and pull low
*
* @index: sensor select
*
* @return: none
*/
static void ds18s20_set_input(int high)
{
if(high)
{
at91_set_gpio_input(AT91_PIN_PA24, HIGH);
}
else
{
at91_set_gpio_input(AT91_PIN_PA24, LOW);
}
}
/*
* ds18b20_set_output:
*
* @action: set output and clear io
*
* @index: sensor select
*
* @return: none
*/
static void ds18b20_set_output( int high)
{
if(high)
{
at91_set_gpio_output(AT91_PIN_PA24, HIGH);
}
if(!high)
{
at91_set_gpio_output(AT91_PIN_PA24, LOW);
}
}
/*
* ds18b20_get_io:
*
* @action: get io value
*
* @index: sensor select
*
* @return: 1 for success
* 0 for failure
*/
static unsigned char ds18b20_get_io(void)
{
unsigned char ret = 0;
ret = at91_get_gpio_value(AT91_PIN_PA24);
return ret;
}
/*
* ds18b20_write_byte:
*
* @action: write byte to ds18b20 register
*
* @b: the data value ready to write
*
* @index: sensor select
*
* @return: none
*/
static unsigned char ds18b20_write_byte(unsigned char b)//b=skip ROM operation
{
int i;
/*
// 写“1”时隙:
// 保持总线在低电平1微秒到15微秒之间
// 然后再保持总线在高电平15微秒到60微秒之间
// 理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平
//
// 写“0”时隙:
// 保持总线在低电平15微秒到60微秒之间
// 然后再保持总线在高电平1微秒到15微秒之间
// 理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平
*/
for(i=0;i<8;i++)
{
if(b&1)
{
ds18b20_set_output(LOW);
udelay(8);
ds18b20_set_output(HIGH);
udelay(55);
}
else
{
ds18b20_set_output(LOW);
udelay(55);
ds18b20_set_output(HIGH);
udelay(8);
}
b>>=1;
}
return b;
}
/*
* ds18b20_read_byte:
*
* @action: read data value(byte) form register
*
* @index: sensor select
*
* @return: data value
*/
static unsigned char ds18b20_read_byte(void)
{
unsigned char i=0,byte=0;
for(i=0;i<8;i++)
{
byte>>=1;
ds18b20_set_output(LOW);
udelay(1);
ds18b20_set_output(HIGH);
udelay(1);
ds18s20_set_input(HIGH);
if(ds18b20_get_io())
byte|=0x80;
udelay(60);
}
return byte;
// 读“1”时隙:
// 若总线状态保持在低电平状态1微秒到15微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“1”信号
// 理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平
//
// 读“0”时隙:
// 若总线状态保持在低电平状态15微秒到30微秒之间
// 然后跳变到高电平状态且保持在15微秒到60微秒之间
// 就认为从DS18B20读到一个“0”信号
// 理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平
}
/*
* ds18b20_reset:
*
* @action: reset ds18b20
*
* @index: sensor select
*
* @return: 1 for success
* 0 for failure
*/
static int ds18b20_reset(void)
{
ds18b20_set_output(HIGH);
ds18b20_set_output(LOW);//
udelay(500);
ds18b20_set_output(HIGH);
ds18s20_set_input(HIGH);//set input mode
udelay(15);//wait 15-60us DS18b20 will respond
ds18b20_get_io();//if answer is 0
printk("DS18b20 respond 0\n");
//ds18b20_set_output(HIGH);
udelay(800);
return 0;
}
/*
* ds18b20_reset:
*
* @action: read temperature
*
* @index: sensor select
*
* @return: current temperature
*/
static int ds18b20_read_temp(void)
{
ds18b20_reset();//
//ds18b20_get_io(index);
ds18b20_write_byte(SKIP_ROM); /*skip ROM operation*/
ds18b20_w