Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3727
  • 博文数量: 3
  • 博客积分: 135
  • 博客等级: 入伍新兵
  • 技术积分: 30
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-02 17:22
文章分类
文章存档

2010年(3)

我的朋友
最近访客

分类: 嵌入式

2010-08-04 16:08:04

linux ds18s20驱动,已测试通过
at91sam9260芯片,寄生电源,支持3个传感器,一次读取一个温度
 
#include
#include
#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");
阅读(529) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~