歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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");  
Copyright © Linux教程網 All Rights Reserved