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

mini2440上DS18B20的驅動程序(含簡單測試)

ds18b20_drv.c

[cpp]

  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. /* 相關引腳定義,方便以後移植 */  
  18. #define DQ         S3C2410_GPF(3)   
  19. #define CFG_IN     S3C2410_GPIO_INPUT   
  20. #define CFG_OUT    S3C2410_GPIO_OUTPUT   
  21.   
  22. // ds18b20主次設備號(動態分配)   
  23. static int ds18b20_major = 0;  
  24. static int ds18b20_minor = 0;  
  25. static int ds18b20_nr_devs = 1;  
  26.   
  27. // 定義設備類型   
  28. static struct ds18b20_device  
  29. {  
  30.     struct cdev cdev;  
  31. };  
  32.   
  33. struct ds18b20_device *ds18b20_devp;    /*設備結構體指針 */  
  34.   
  35. static struct class *ds18b20_class;  
  36. static struct class_device *ds18b20_class_dev;  
  37.   
  38. /* 函數聲明 */  
  39. static int ds18b20_open(struct inode *inode, struct file *filp);  
  40. static int ds18b20_init(void);  
  41. static void write_byte(unsigned char data);  
  42. static unsigned char read_byte(void);  
  43. static ssize_t ds18b20_read(struct file *filp, char __user * buf, size_t count, loff_t * f_pos);  
  44. void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);  
  45.   
  46. static int ds18b20_open(struct inode *inode, struct file *filp)  
  47. {  
  48.     int flag = 0;  
  49.   
  50.     flag = ds18b20_init();  
  51.     if (flag & 0x01)  
  52.     {  
  53.         printk(KERN_WARNING "open ds18b20 failed\n");  
  54.         return -1;  
  55.     }  
  56.     printk(KERN_NOTICE "open ds18b20 successful\n");  
  57.     return 0;  
  58. }  
  59.   
  60. static int ds18b20_init(void)  
  61. {  
  62.     int retval = 0;  
  63.   
  64.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);  
  65.     s3c2410_gpio_pullup(DQ, 0);  
  66.   
  67.     s3c2410_gpio_setpin(DQ, 1);  
  68.     udelay(2);  
  69.     s3c2410_gpio_setpin(DQ, 0); // 拉低ds18b20總線,復位ds18b20   
  70.     udelay(500);                // 保持復位電平500us   
  71.   
  72.     s3c2410_gpio_setpin(DQ, 1); // 釋放ds18b20總線   
  73.     udelay(60);  
  74.   
  75.     // 若復位成功,ds18b20發出存在脈沖(低電平,持續60~240us)   
  76.     s3c2410_gpio_cfgpin(DQ, CFG_IN);  
  77.     retval = s3c2410_gpio_getpin(DQ);  
  78.   
  79.     udelay(500);  
  80.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);  
  81.     s3c2410_gpio_pullup(DQ, 0);  
  82.     s3c2410_gpio_setpin(DQ, 1); // 釋放總線   
  83.   
  84.     return retval;  
  85. }  
  86.   
  87. static void write_byte(unsigned char data)  
  88. {  
  89.     int i = 0;  
  90.   
  91.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);  
  92.     s3c2410_gpio_pullup(DQ, 1);  
  93.   
  94.     for (i = 0; i < 8; i++)  
  95.     {  
  96.         // 總線從高拉至低電平時,就產生寫時隙   
  97.         s3c2410_gpio_setpin(DQ, 1);  
  98.         udelay(2);  
  99.         s3c2410_gpio_setpin(DQ, 0);  
  100.         s3c2410_gpio_setpin(DQ, data & 0x01);  
  101.         udelay(60);  
  102.         data >>= 1;  
  103.     }  
  104.     s3c2410_gpio_setpin(DQ, 1); // 重新釋放ds18b20總線   
  105. }  
  106.   
  107. static unsigned char read_byte(void)  
  108. {  
  109.     int i;  
  110.     unsigned char data = 0;  
  111.   
  112.     for (i = 0; i < 8; i++)  
  113.     {  
  114.         // 總線從高拉至低,只需維持低電平17ts,再把總線拉高,就產生讀時隙   
  115.         s3c2410_gpio_cfgpin(DQ, CFG_OUT);  
  116.         s3c2410_gpio_pullup(DQ, 0);  
  117.         s3c2410_gpio_setpin(DQ, 1);  
  118.         udelay(2);  
  119.         s3c2410_gpio_setpin(DQ, 0);  
  120.         udelay(2);  
  121.         s3c2410_gpio_setpin(DQ, 1);  
  122.         udelay(8);  
  123.         data >>= 1;  
  124.         s3c2410_gpio_cfgpin(DQ, CFG_IN);  
  125.         if (s3c2410_gpio_getpin(DQ))  
  126.             data |= 0x80;  
  127.         udelay(50);  
  128.     }  
  129.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);  
  130.     s3c2410_gpio_pullup(DQ, 0);  
  131.     s3c2410_gpio_setpin(DQ, 1); // 釋放ds18b20總線   
  132.     return data;  
  133. }  
  134.   
  135. static ssize_t ds18b20_read(struct file *filp, char __user * buf, size_t count, loff_t * f_pos)  
  136. {  
  137.     int flag;  
  138.     unsigned long err;  
  139.     unsigned char result[2] = { 0x00, 0x00 };  
  140.     //struct ds18b20_device *dev = filp->private_data;   
  141.   
  142.     flag = ds18b20_init();  
  143.     if (flag & 0x01)  
  144.     {  
  145.         printk(KERN_WARNING "ds18b20 init failed\n");  
  146.         return -1;  
  147.     }  
  148.   
  149.     write_byte(0xcc);  
  150.     write_byte(0x44);  
  151.   
  152.     flag = ds18b20_init();  
  153.     if (flag & 0x01)  
  154.         return -1;  
  155.   
  156.     write_byte(0xcc);  
  157.     write_byte(0xbe);  
  158.   
  159.     result[0] = read_byte();    // 溫度低八位   
  160.     result[1] = read_byte();    // 溫度高八位   
  161.   
  162.     err = copy_to_user(buf, &result, sizeof(result));  
  163.     return err ? -EFAULT : min(sizeof(result), count);  
  164. }  
  165.   
  166. static struct file_operations ds18b20_dev_fops = {  
  167.     .owner = THIS_MODULE,  
  168.     .open = ds18b20_open,  
  169.     .read = ds18b20_read,  
  170. };  
  171.   
  172. void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)  
  173. {  
  174.     int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);  
  175.   
  176.     cdev_init(&dev->cdev, &ds18b20_dev_fops);  
  177.     dev->cdev.owner = THIS_MODULE;  
  178.     err = cdev_add(&(dev->cdev), devno, 1);  
  179.     if (err)  
  180.     {  
  181.         printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);  
  182.     }  
  183. }  
  184.   
  185. static int __init ds18b20_dev_init(void)  
  186. {  
  187.     int result;  
  188.     dev_t dev = 0;  
  189.   
  190.     dev = MKDEV(ds18b20_major, ds18b20_minor);  
  191.   
  192.     if (ds18b20_major)  
  193.     {  
  194.         result = register_chrdev_region(dev, ds18b20_nr_devs, "ds18b20");  
  195.     }  
  196.     else  
  197.     {  
  198.         result = alloc_chrdev_region(&dev, ds18b20_minor, ds18b20_nr_devs, "ds18b20");  
  199.         ds18b20_major = MAJOR(dev);  
  200.     }  
  201.     if (result < 0)  
  202.     {  
  203.         printk(KERN_WARNING "ds18b20: failed to get major\n");  
  204.         return result;  
  205.     }  
  206.   
  207.     /* 為新設備分配內存和初始化 */  
  208.     ds18b20_devp = kmalloc(sizeof(struct ds18b20_device), GFP_KERNEL);  
  209.     if (!ds18b20_devp)  
  210.     {                           /*申請失敗 */  
  211.         result = -ENOMEM;  
  212.         goto fail_malloc;  
  213.     }  
  214.     memset(ds18b20_devp, 0, sizeof(struct ds18b20_device));  
  215.   
  216.     ds18b20_setup_cdev(ds18b20_devp, 0);  
  217.   
  218.     /* 自動創建設備節點 */  
  219.     ds18b20_class = class_create(THIS_MODULE, "ds18b20_sys_class");  
  220.     if (IS_ERR(ds18b20_class))  
  221.         return PTR_ERR(ds18b20_class);  
  222.   
  223.     ds18b20_class_dev =  
  224.         device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, 0), NULL, "ds18b20");  
  225.     if (unlikely(IS_ERR(ds18b20_class_dev)))  
  226.         return PTR_ERR(ds18b20_class_dev);  
  227.   
  228.     return 0;  
  229.   
  230.   fail_malloc:  
  231.     unregister_chrdev_region(dev, 1);  
  232.     return result;  
  233. }  
  234.   
  235. static void __exit ds18b20_dev_exit(void)  
  236. {  
  237.     cdev_del(&ds18b20_devp->cdev);  /*注銷cdev */  
  238.     kfree(ds18b20_devp);        /*釋放設備結構體內存 */  
  239.     unregister_chrdev_region(MKDEV(ds18b20_major, 0), ds18b20_nr_devs); /*釋放設備號 */  
  240.     device_unregister(ds18b20_class_dev);  
  241.     class_destroy(ds18b20_class);  
  242. }  
  243.   
  244. module_init(ds18b20_dev_init);  
  245. module_exit(ds18b20_dev_exit);  
  246. MODULE_LICENSE("Dual BSD/GPL");  
  247. MODULE_AUTHOR("[email protected]");  
app-ds18b20.c

[cpp]

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <unistd.h>   
  4. #include <linux/ioctl.h>   
  5.   
  6. // 函數聲明   
  7. void ds18b20_delay(int i);  
  8.   
  9. int main()  
  10. {  
  11.     int fd, i;  
  12.     unsigned char result[2];    // 從ds18b20讀出的結果,result[0]存放低八位   
  13.     unsigned char integer_value = 0;  
  14.     float decimal_value = 0;    // 溫度數值,decimal_value為小數部分的值   
  15.     float temperature = 0;  
  16.   
  17.     fd = open("/dev/ds18b20", 0);  
  18.     if (fd < 0)  
  19.     {  
  20.         perror("open device failed\n");  
  21.         exit(1);  
  22.     }  
  23.     while (1)  
  24.     {  
  25.         i++;  
  26.         read(fd, &result, sizeof(result));  
  27.         integer_value = ((result[0] & 0xf0) >> 4) | ((result[1] & 0x07) << 4);  
  28.         // 精確到0.25度   
  29.         decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2);  
  30.         temperature = (float)integer_value + decimal_value;  
  31.         printf("Current Temperature:%6.2f\n", temperature);  
  32.   
  33.         ds18b20_delay(500);  
  34.     }  
  35. }  
  36.   
  37. void ds18b20_delay(int i)  
  38. {  
  39.     int j, k;  
  40.     for (j = 0; j < i; j++)  
  41.         for (k = 0; k < 50000; k++) ;  
  42. }  
Makefile

[cpp]

  1. ifneq ($(KERNELRELEASE),)  
  2. obj-m := ds18b20_drv.o  
  3.   
  4. else  
  5. KDIR := /home/youshan/linux-2.6.32.2  
  6. MYAPP := app-ds18b20  
  7.   
  8. all:  
  9.     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-  
  10.     arm-linux-gcc $(MYAPP).c -o $(MYAPP)  
  11.       
  12. clean:  
  13.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*  
  14.     rm -f $(MYAPP)  
  15.       
  16. endif  

運行結果:

[cpp]

  1. [[email protected] home]#  
  2. [[email protected] home]#./app-ds18b20  
  3. open ds18b20 successful  
  4. Current Temperature: 23.50  
  5. Current Temperature: 23.50  
  6. Current Temperature: 23.25  
  7. Current Temperature: 23.50  
  8. Current Temperature: 23.50  
  9. Current Temperature: 23.50  
  10. ^C  
  11. [[email protected] home]#  
Copyright © Linux教程網 All Rights Reserved