linux ds18s20驱动,已测试通过
at91sam9260芯片,寄生电源,支持3个传感器,一次读取一个温度
#include
#include
#include
#include
#include
#include
#include
#define PFX "ds18s20: "
#define DS18S20_MINOR 120 /*minor number of this ds18s20*/
#define DS18S20_SENSOR_0 0
#define DS18S20_SENSOR_1 1
#define DS18S20_SENSOR_2 2
/*commad*/
#define GET_TEMP_0 0
#define GET_TEMP_1 1
#define GET_TEMP_2 2
#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
/*
* ds18s20_set_input:
*
* @action: set input and pull low
*
* @index: sensor select
*
* @return: none
*/
static void ds18s20_set_input(int index)
{
if(index == DS18S20_SENSOR_0){
at91_set_gpio_input(AT91_PIN_PC10, LOW);
}
if(index == DS18S20_SENSOR_1){
at91_set_gpio_input(AT91_PIN_PC9, LOW);
}
if(index == DS18S20_SENSOR_2){
at91_set_gpio_input(AT91_PIN_PC7, LOW);
}
}
/*
* ds18s20_set_output:
*
* @action: set output and clear io
*
* @index: sensor select
*
* @return: none
*/
static void ds18s20_set_output(int index, int high)
{
if(high){
if(index == DS18S20_SENSOR_0){
at91_set_gpio_output(AT91_PIN_PC10, HIGH);
}
if(index == DS18S20_SENSOR_1){
at91_set_gpio_output(AT91_PIN_PC9, HIGH);
}
if(index == DS18S20_SENSOR_2){
at91_set_gpio_output(AT91_PIN_PC7, HIGH);
}
}
if(!high){
if(index == DS18S20_SENSOR_0){
at91_set_gpio_output(AT91_PIN_PC10, LOW);
}
if(index == DS18S20_SENSOR_1){
at91_set_gpio_output(AT91_PIN_PC9, LOW);
}
if(index == DS18S20_SENSOR_2){
at91_set_gpio_output(AT91_PIN_PC7, LOW);
}
}
}
/*
* ds18s20_get_io:
*
* @action: get io value
*
* @index: sensor select
*
* @return: 1 for success
* 0 for failure
*/
static int ds18s20_get_io(int index)
{
int ret = 0;
if(index == DS18S20_SENSOR_0){
ret = at91_get_gpio_value(AT91_PIN_PC10);
}
if(index == DS18S20_SENSOR_1){
ret = at91_get_gpio_value(AT91_PIN_PC9);
}
if(index == DS18S20_SENSOR_2){
ret = at91_get_gpio_value(AT91_PIN_PC7);
}
return ret;
}
/*
* ds18s20_set_io:
*
* @action: set io value
*
* @index: sensor select
*
* @return: none
*/
static void ds18s20_set_io(int index)
{
if(index == DS18S20_SENSOR_0){
at91_set_gpio_value(AT91_PIN_PC10, 1);
}
if(index == DS18S20_SENSOR_1){
at91_set_gpio_value(AT91_PIN_PC9, 1);
}
if(index == DS18S20_SENSOR_2){
at91_set_gpio_value(AT91_PIN_PC7, 1);
}
}
static unsigned char bit_io(unsigned char b, int index)
{
//OW_DIR_OUT(); // drive bus low
ds18s20_set_output(index, LOW);
//delay_us(1); // Recovery-Time wuffwuff was 1
udelay(1);
//if(b) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)
if(b)
ds18s20_set_input(index);
// wuffwuff delay was 15uS-1 see comment above
//delay_us(15-1-OW_CONF_DELAYOFFSET);
udelay(15 - 1);
//if( OW_GET_IN() == 0 ) b = 0; // sample at end of read-timeslot
if(ds18s20_get_io(index) == 0)
b = 0;
//delay_us(60-15);
udelay(60 - 15);
//OW_DIR_IN();
ds18s20_set_input(index);
return b;
}
/*
* ds18s20_write_byte:
*
* @action: write byte to ds18s20 register
*
* @b: the data value ready to write
*
* @index: sensor select
*
* @return: none
*/
static unsigned char ds18s20_write_byte(unsigned char b, int index)
{
unsigned char i = 8, j;
do{
j = bit_io((b & 1), index);
b >>= 1;
if( j )
b |= 0x80;
} while( --i );
return b;
}
/*
* ds18s20_read_byte:
*
* @action: read data value(byte) form register
*
* @index: sensor select
*
* @return: data value
*/
static unsigned char ds18s20_read_byte(int index)
{
// read by sending 0xff (a dontcare?)
return ds18s20_write_byte(0xFF, index);
}
/*
* ds18s20_reset:
*
* @action: reset ds18s20
*
* @index: sensor select
*
* @return: 1 for success
* 0 for failure
*/
static int ds18s20_reset(int index)
{
unsigned char data = 0;
/*master tx reset pulse*/
ds18s20_set_output(index, LOW); /*bus master pull low*/
/*master watis 480us minimum*/
udelay(480);
/*ds18s20 waits 15~60 us*/
udelay(60);
/*presence pulse*/
data = ds18s20_get_io(index);
/*watis 60~240 us*/
udelay(60);
/*master rx*/
ds18s20_set_input(index); /*ds18s20 pull low*/
/*master rx delay 480 minimum
* == ds18s20 waits + presence pulse + resistor pullup
*/
udelay(480 -60 - 60);
if(ds18s20_get_io(index) == 0)
data = 1;
printk("data = %d\n", data);
return data;
}
/*
* ds18s20_reset:
*
* @action: read temperature
*
* @index: sensor select
*
* @return: current temperature
*/
static int ds18s20_read_temp(int index)
{
unsigned short t = 0;
u8 subzero;
unsigned char sp[9];
u16 meas;
unsigned char temp = 0;
ds18s20_reset(index);
//ds18s20_get_io(index);
ds18s20_write_byte(SKIP_ROM, index); /*skip ROM operation*/
ds18s20_write_byte(TEMP_CONVET, index); /*start temperature convertion*/
//ds18s20_set_output(index, HIGH);
//mdelay(1);
//ds18s20_set_input(index);
//mdelay(1);
mdelay(750);
ds18s20_reset(index);
ds18s20_write_byte(SKIP_ROM, index); /*skip ROM operation*/
ds18s20_write_byte(READ_TEMP, index); /*start read temperature*/
int i;
for(i = 0; i < 9; i++){
sp[i] = ds18s20_read_byte(index);
printk("0x%x ", sp[i]);
}
printk("\n");
t = sp[0];
t |= ((u16)sp[1]) << 8;
return t;
}
static int ds18s20_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int temp = 0;
switch(cmd){
case GET_TEMP_0:
temp = ds18s20_read_temp(GET_TEMP_0);
put_user(temp, (int *)arg);
break;
case GET_TEMP_1:
temp = ds18s20_read_temp(GET_TEMP_1);
put_user(temp, (int *)arg);
break;
case GET_TEMP_2:
temp = ds18s20_read_temp(GET_TEMP_2);
put_user(temp, (int *)arg);
break;
default:
printk(KERN_ERR PFX "not sppoted choice = %d\n", cmd);
return -1;
}
return 0;
}
static const struct file_operations ds18s20_fops =
{
.owner = THIS_MODULE,
.ioctl = ds18s20_ioctl,
};
static struct miscdevice ds18s20_miscdev =
{
.minor = DS18S20_MINOR,
.name = "ds18s20",
.fops = &ds18s20_fops,
};
static char banner[] __initdata = KERN_INFO "Temperature Sensor Driver For Ds18s20\n";
static int __init ds18s20_init(void)
{
int ret;
ret = misc_register(&ds18s20_miscdev);
if(ret){
printk(KERN_ERR PFX "cannot register miscdev on minor = %d(err = %d)\n", DS18S20_MINOR, ret);
return ret;
}
printk(banner);
return 0;
}
static void __exit ds18s20_exit(void)
{
misc_deregister(&ds18s20_miscdev);
printk(KERN_INFO PFX "ds18s20 dirver removed\n");
}
module_init(ds18s20_init);
module_exit(ds18s20_exit);
MODULE_AUTHOR("");
MODULE_DESCRIPTION("temperature sensor driver for ds18s20");
MODULE_LICENSE("Dual BSD/GPL");