mini2440 驱动ds18b20


想着有个ds18b20,于是就写了一个18b20的驱动。是在mini2440上面实现的。

ldd3的大师说得好,linux驱动应该尽可能多的提供机制,而不是提供策略。我觉得说得太有道理了。驱动本身就不应该涉及到太多策略问题,策略问题应该尽可能多的由应用程序去提供。作为驱动,应该尽可能多得去实现提供硬件的功能,然后留出接口给上面的应用程序调用。

其实ds18b20驱动比较简单,无非就是在单片机驱动18b20的基础上,家里一个字符驱动设备的外套。下面直接上代码吧。

驱动代码:

  1. #include <linux/init.h>   
  2. #include <linux/module.h>   
  3. #include <linux/delay.h>   
  4. #include <linux/kernel.h>   
  5. #include <linux/moduleparam.h>   
  6. #include <linux/init.h>   
  7. #include <linux/types.h>   
  8. #include <linux/fs.h>   
  9. #include <mach/regs-gpio.h>   
  10. #include <mach/hardware.h>   
  11. #include <linux/cdev.h>   
  12. #include <asm/uaccess.h>   
  13. #include <linux/errno.h>   
  14. #include <linux/gpio.h>   
  15. #include <linux/device.h> //自动创建设备需要此头文件   
  16.   
  17. #define DQ     S3C2410_GPF(3)      //mini2440里面是这样定义GPIO的   
  18. #define DQ_IN  S3C2410_GPIO_INPUT  //设置DQ为输入   
  19. #define DQ_OUT S3C2410_GPIO_OUTPUT //设置DQ为输入   
  20.   
  21. #define D_MAJOR 0                  //定义主设备号   
  22. #define D_MINOR 0                  //定义从设备号   
  23. #define DEV_NAME "ds18b20"         //定义设备名   
  24.   
  25. static int ds18b20_major = D_MAJOR;//ds18b20主设备号   
  26. static int ds18b20_minor = D_MINOR;//ds18b20从设备号   
  27. static struct class *my_class;     //定义class,用于自动挂载设备   
  28. static struct class_device *my_device; //自动挂载设备   
  29.   
  30. static struct ds18b20_dev{           //放在一个结构体中            
  31.     struct cdev cdev;                //这个结构体比较简单,但是建议以后将用户的东西都放在一个结构体中   
  32. };  
  33.   
  34. struct ds18b20_dev *ds18b20_devp;  
  35.   
  36. void ds18b20_reset(void)             //重启ds18b20   
  37. {  
  38.     s3c2410_gpio_cfgpin(DQ, DQ_OUT); //设置为输出   
  39.     s3c2410_gpio_pullup(DQ, 0);      //设置下拉   
  40.     s3c2410_gpio_setpin(DQ, 0);      //拉低总线   
  41.     udelay(500);                     //需要将总线拉低480~950us   
  42.     s3c2410_gpio_setpin(DQ, 1);      //释放总线   
  43.     udelay(60);                      //DS18B20拉低信号,60~240us表示应答   
  44.     s3c2410_gpio_cfgpin(DQ, DQ_IN);  //读入DS18B20拉低信号   
  45.     while(s3c2410_gpio_getpin(DQ));  //等待DS18B20应答   
  46.     while(!s3c2410_gpio_getpin(DQ)); //等待DS18B20释放总线       
  47. }  
  48.   
  49. void write_ds18b20(unsigned char Data)           //写命令到ds18b20   
  50. {     
  51.     unsigned char i;  
  52.     s3c2410_gpio_cfgpin(DQ, DQ_OUT);              //设置为输出   
  53.     s3c2410_gpio_pullup(DQ, 1);                   //上拉       
  54.     for(i=0;i<8;i++){  
  55.         s3c2410_gpio_setpin(DQ, 0);              //拉低总线   
  56.         udelay(10);                              //需要拉低10~15us   
  57.    
  58.         if(Data&0x01)  
  59.             s3c2410_gpio_setpin(DQ, 1);  
  60.         else  
  61.             s3c2410_gpio_setpin(DQ, 0);  
  62.         udelay(40);                             //需要拉低20~40us来写0   
  63.         s3c2410_gpio_setpin(DQ, 1);            //释放总线   
  64.         udelay(1);                            //稍微延时   
  65.         Data >>= 1;          
  66.     }  
  67. }  
  68.   
  69. static unsigned char read_ds18b20(void)    //读ds18b20   
  70. {  
  71.     unsigned char Temp=0,i;  
  72.     for(i=0;i<8;i++){  
  73.         Temp >>= 1;  
  74.         s3c2410_gpio_cfgpin(DQ, DQ_OUT);  //DQ为输出状态   
  75.         s3c2410_gpio_setpin(DQ, 0);       //拉低总线,启动输入   
  76.         udelay(1);                        //拉低总线约1us   
  77.         s3c2410_gpio_setpin(DQ, 1);       //释放总线   
  78.         s3c2410_gpio_cfgpin(DQ, DQ_IN);   //DQ为输入状态   
  79.         if(s3c2410_gpio_getpin(DQ))  
  80.           Temp |= 0x80;  
  81.         udelay(45);      //延时45us   
  82.     }  
  83.     return Temp;  
  84. }  
  85.   
  86. static int ds18b20_open(struct inode *inode,struct file *filp)  
  87. {  
  88.     filp->private_data = ds18b20_devp;  
  89.     ds18b20_reset();  
  90.     printk(KERN_NOTICE "open ds18b20 successful\n");  
  91.     return 0;  
  92. }  
  93.   
  94. static ssize_t ds18b20_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)  
  95. {  
  96.     unsigned long err;  
  97.     struct ds18b20_dev *dev = filp->private_data;  
  98.     unsigned char result[2] = {0x00, 0x00};       //这个是用来存放从ds18b20读到的值   
  99.     ds18b20_reset();                              //reset ds18b20   
  100.     write_ds18b20(0xCC);                          //跳过ROM   
  101.     write_ds18b20(0x44);                          //温度转换   
  102.     ds18b20_reset();                              //reset ds18b20   
  103.     write_ds18b20(0xCC);                          //跳过ROM   
  104.        write_ds18b20(0xbe);                          //读取RAM   
  105.     result[0] = read_ds18b20();                   //读低8位,存放在result[0]   
  106.     result[1] = read_ds18b20();                   //读高8位,存放在result[1]   
  107.     ds18b20_reset();  
  108.     err = copy_to_user(buf, &result, sizeof(result));  
  109.     return err ? -EFAULT : min(sizeof(result), size);  
  110. }  
  111.   
  112. static int ds18b20_release(struct inode *inode,struct file *filp)  
  113.   
  114. {  
  115.     return 0;  
  116. }  
  117.   
  118. static const struct file_operations ds18b20_fops={  
  119.     .owner=THIS_MODULE,   
  120.     .read=ds18b20_read,  
  121.     .open=ds18b20_open,  
  122.     .release=ds18b20_release,  
  123.   
  124. };  
  125. void ds18b20_setup_dev(struct ds18b20_dev *dev,int minor)  
  126. {  
  127.     int err;  
  128.     int devno;  
  129.     devno = MKDEV(ds18b20_major,minor);  
  130.     cdev_init(&dev->cdev,&ds18b20_fops);  
  131.     dev->cdev.owner=THIS_MODULE;  
  132.     dev->cdev.ops=&ds18b20_fops;  
  133.     err=cdev_add(&dev->cdev,devno,1);  
  134.     if(err)  
  135.         printk(KERN_NOTICE "Error %d adding %d\n",err,minor);  
  136. }  
  137.   
  138. static int  __init ds18b20_init(void)  
  139. {  
  140.     int result;  
  141.     dev_t devno = 0;  
  142.       
  143.     if(ds18b20_major){  
  144.         devno = MKDEV(ds18b20_major,ds18b20_minor);  
  145.         result = register_chrdev_region(devno,1,DEV_NAME);  
  146.     }  
  147.     else{  
  148.         result = alloc_chrdev_region(&devno,0,1,DEV_NAME);  
  149.         ds18b20_major = MAJOR(devno);  
  150.     }  
  151.     if(result < 0)  
  152.         return result;  
  153.     ds18b20_devp = kmalloc(sizeof(struct ds18b20_dev),GFP_KERNEL);  
  154.     if(ds18b20_devp){  
  155.         result = -ENOMEM;  
  156.         goto fail_malloc;  
  157.     }  
  158.     memset(ds18b20_devp,0,sizeof(struct ds18b20_dev));  
  159.     ds18b20_setup_dev(ds18b20_devp,0);  
  160.     my_class = class_create(THIS_MODULE,"ds18b20_class");  
  161.     /*在linux 2.6.27之前是:class_device_create*/  
  162.     my_device = device_create(my_class,NULL,MKDEV(ds18b20_major, ds18b20_minor),NULL,"ds18b20");  
  163.     return 0;  
  164.     fail_malloc:  
  165.         unregister_chrdev_region(devno,1);  
  166.         return result;  
  167. }  
  168.   
  169. static void __exit ds18b20_exit(void)  
  170. {  
  171.     cdev_del(&ds18b20_devp->cdev);  
  172.     kfree(ds18b20_devp);  
  173.     device_destroy(my_class, MKDEV(ds18b20_major, ds18b20_minor));//删除设备文件 /dev/ds18b20    
  174.     class_destroy(my_class);   //删除创建的bus   
  175.     unregister_chrdev_region(MKDEV(ds18b20_major,ds18b20_minor),1);  
  176. }  
  177.   
  178. module_init(ds18b20_init);  
  179. module_exit(ds18b20_exit);  
  180.   
  181. MODULE_LICENSE("GPL");  
  182. MODULE_AUTHOR("WIOT");  
  • 1
  • 2
  • 下一页

相关内容