OK6410 Linux DS18B20驱动

[cpp]  view plain  copy
  1. //要注意一点,在裸机状态下可以使用data = data * 6.25来对温度值进行放大100倍,但是在内核中不能使用,但可以使用data = data * 625 / 100;   
[cpp]  view plain  copy
  1. //网上查了一下好像是内核不支持浮点.不知道是不是这回事,但是我不使用浮点驱动加载就没问题,使用后不能加载了.   
[cpp]  view plain  copy
  1.     
[cpp]  view plain  copy
  1.    
[cpp]  view plain  copy
  1. /**************************************************************************************************************** 
  2.  * 文件名称 :   DS18B20_drive.c 
  3.  * 简介       :   OK6410 DS18B20驱动 
  4.  * 作者       :   异灵元(cp1300@139.com) 
  5.  * 创建时间 :   2012/09/18 20:37 
  6.  * 修改时间 :   2012/09/18 
  7.  * 说明       :   OK6410 开发板(S3C6410)DS18B20(GPIO)驱动 
  8.  ****************************************************************************************************************/  
  9.   
  10. //系统头文件  
  11. #include <linux/miscdevice.h>  
  12. #include <linux/delay.h>  
  13. #include <asm/irq.h>  
  14. #include <mach/hardware.h>  
  15. #include <linux/kernel.h>  
  16. #include <linux/module.h>  
  17. #include <linux/init.h>  
  18. #include <linux/mm.h>  
  19. #include <linux/fs.h>  
  20. #include <linux/types.h>  
  21. #include <linux/delay.h>  
  22. #include <linux/moduleparam.h>  
  23. #include <linux/slab.h>  
  24. #include <linux/errno.h>  
  25. #include <linux/ioctl.h>  
  26. #include <linux/cdev.h>  
  27. #include <linux/string.h>  
  28. #include <linux/list.h>  
  29. #include <linux/pci.h>  
  30. #include <asm/uaccess.h>  
  31. #include <asm/atomic.h>  
  32. #include <asm/unistd.h>  
  33.   
  34.   
  35. #include <linux/delay.h>  
  36. #include <linux/io.h>  
  37.   
  38. //--------------------------//  
  39. #include <mach/map.h>  
  40. #include <mach/regs-clock.h>  
  41. #include <mach/regs-gpio.h>  
  42. //--------------------------//  
  43. #include <plat/gpio-cfg.h>  
  44. #include <mach/gpio-bank-e.h>  
  45. #include <mach/gpio-bank-m.h>  
  46.   
  47. #define DS18B20_ERROR   0xf000  //初始化失败  
  48.   
  49.   
  50. //系统US延时定义  
  51. #define Delay_US(x)     udelay(x)  
  52.   
  53.   
  54. //设置DS18B20 IO为推挽输出模式  
  55. void Set18b20IOout(void)  
  56. {  
  57.     unsigned int reg;  
  58.   
  59.     reg = readl(S3C64XX_GPECON);  
  60.     reg |= 1;  
  61.     writel(reg,S3C64XX_GPECON);  
  62. }  
  63.   
  64.   
  65. //读IO  
  66. unsigned char Read18b20IO(void)  
  67. {  
  68.     unsigned int reg;  
  69.   
  70.     reg = readl(S3C64XX_GPEDAT);  
  71.     if(reg & 1)  
  72.         return 1;  
  73.     else  
  74.         return 0;  
  75. }  
  76.   
  77.   
  78. //写IO  
  79. void Write18b20IO(unsigned char data)  
  80. {  
  81.     unsigned int reg;  
  82.   
  83.     reg = readl(S3C64XX_GPEDAT);  
  84.     if(data)  
  85.         reg |= 1;  
  86.     else  
  87.         reg &= ~1;  
  88.     writel(reg,S3C64XX_GPEDAT);  
  89. }  
  90.   
  91.   
  92. //设在DS18B20 IO输入模式  
  93. void Set18b20IOin(void)  
  94. {  
  95.     unsigned int reg;  
  96.   
  97.     reg = readl(S3C64XX_GPECON);  
  98.     reg &= (~0xf);  
  99.     writel(reg,S3C64XX_GPECON);  
  100. }  
  101.   
  102.   
  103. //复位DS18B20  
  104. u8 DS18B20_Reset(void)  
  105. {  
  106.     u8 i = 0;  
  107.   
  108.     Set18b20IOout();  
  109.     Write18b20IO(1);  
  110.     Delay_US(1);  
  111.     Write18b20IO(0);  
  112.     Delay_US(500);  
  113.     Write18b20IO(1);  
  114.     Delay_US(2);  
  115.     Set18b20IOin();  
  116.     while(Read18b20IO())  
  117.     {  
  118.         i ++;  
  119.         Delay_US(1);  
  120.         if(i > 100)  
  121.             return 1;  
  122.     }  
  123.     Delay_US(250);  
  124.     return 0x00;  
  125. }  
  126.   
  127.   
  128. //读DS18B20数据  
  129. u8 DS18B20_ReadData(void)  
  130. {  
  131.     u8 i,data = 0;  
  132.   
  133.     for(i = 0;i < 8;i ++)  
  134.     {  
  135.         Set18b20IOout();  
  136.         Write18b20IO(0);  
  137.         data >>= 1;  
  138.         Delay_US(12);  
  139.         Write18b20IO(1);  
  140.         Set18b20IOin();  
  141.         Delay_US(1);  
  142.         if(Read18b20IO())  
  143.             data |= 0x80;  
  144.         Delay_US(42);  
  145.     }  
  146.     return data;  
  147. }  
  148.   
  149.   
  150.   
  151. //写DS18B20数据  
  152. void DS18B20_WriteData(u8 data)  
  153. {  
  154.     u8 i;  
  155.   
  156.     Set18b20IOout();  
  157.     for(i = 0;i < 8;i ++)  
  158.     {  
  159.         Write18b20IO(0);  
  160.         Delay_US(12);  
  161.         Write18b20IO(data & 0x01);  
  162.         Delay_US(30);  
  163.         Write18b20IO(1);  
  164.         data >>= 1;  
  165.         Delay_US(2);  
  166.     }  
  167. }  
  168.   
  169. //读取温度  
  170. int DS18B20_ReadTemper(void)  
  171. {  
  172.     u8 th, tl;  
  173.     int data;  
  174.   
  175.     if(DS18B20_Reset())  
  176.     {  
  177.         return DS18B20_ERROR;  
  178.     }  
  179.     DS18B20_WriteData(0xcc);  
  180.     DS18B20_WriteData(0x44);  
  181.     DS18B20_Reset();  
  182.     DS18B20_WriteData(0xcc);  
  183.     DS18B20_WriteData(0xbe);  
  184.     tl = DS18B20_ReadData();  
  185.     th = DS18B20_ReadData();  
  186.     data = th;  
  187.     data <<= 8;  
  188.     data |= tl;  
  189.     data = data * 625 / 100;  
  190.   
  191.     return data;  
  192. }  
  193.   
  194.   
  195.   
  196. ///  
  197. //驱动模块名称  
  198. #define DEVICE_NAME "OK6410_DS18B20"  
  199.   
  200. //函数声明  
  201. ///  
  202. static long OK6410_DS18B20_ioctl(  
  203.         struct file *file,  
  204.         unsigned int cmd,  
  205.         unsigned long arg);  
  206. static ssize_t OK6410_DS18B20_write(  
  207.         struct file *file,  
  208.         const char __user *buff,  
  209.         size_t size,  
  210.         loff_t *loff);  
  211. static ssize_t OK6410_DS18B20_read(  
  212.         struct file *file,  
  213.         char __user *buff,  
  214.         size_t size,  
  215.         loff_t *loff);  
  216. ///  
  217.   
  218.   
  219. /*  这个结构是字符设备驱动的核心 
  220. *   当应用程序操作设备文件所提供的open,read,write等函数, 
  221. *   最终会调用到这个结构中的对应函数 
  222. */  
  223. static struct file_operations dev_fops = {  
  224.         .owner              = THIS_MODULE,      //这是一个宏,指向编译模块时自动创建的__this_module变量  
  225.         .unlocked_ioctl     = OK6410_DS18B20_ioctl,  
  226.         .read               = OK6410_DS18B20_read,  
  227.         .write              = OK6410_DS18B20_write  
  228. };  
  229.   
  230. //注册驱动所使用的相关信息  
  231. static struct miscdevice misc = {  
  232.         .minor = MISC_DYNAMIC_MINOR,  
  233.         .name = DEVICE_NAME,                        //驱动模块名称  
  234.         .fops = &dev_fops,  
  235. };  
  236.   
  237. //DS18B20设备访问信号量  
  238. struct semaphore DS18B20_sem;  
  239.   
  240.   
  241. /**************************************************************************************************************** 
  242. *函数名        :   static int  __init OK6410_DS18B20_init(void) 
  243. *功能       : DS18B20模块初始化函数 
  244. *参数       : 无 
  245. *返回       : 0:成功;<0:失败 
  246. *依赖       :     linux底层宏定义 
  247. *作者       : 异灵元(cp1300@139.com) 
  248. *创建时间   :   2012/09/18 20:38 
  249. *最后修改时间:    2012/09/18 20:38 
  250. *说明     :   初始化DS18B20硬件,注册DS18B20驱动 
  251. ****************************************************************************************************************/  
  252. static int  __init OK6410_DS18B20_init(void)  
  253. {  
  254.     int ret;  
  255.   
  256.     ret = misc_register(&misc);     //注册驱动  
  257.     if(ret < 0)  
  258.     {  
  259.         printk(DEVICE_NAME " can't initialized DS18B20!\n");  
  260.         return ret;  
  261.     }  
  262.     init_MUTEX(&DS18B20_sem);           //注册信号量  
  263.     printk(DEVICE_NAME " initialized\n");  
  264.     return 0;                           //返回成功  
  265. }  
  266.   
  267.   
  268. /**************************************************************************************************************** 
  269. *函数名        :   static long OK6410_DS18B20_ioctl( 
  270.                         struct file *file, 
  271.                         unsigned int cmd, 
  272.                         unsigned long arg) 
  273. *功能       : 发送命令给DS18B20驱动模块,无实际作用,直接返回0 
  274. *参数       : 无作用 
  275. *返回       : 0 
  276. *依赖       :     无 
  277. *作者       : 异灵元(cp1300@139.com) 
  278. *创建时间   :   2012/09/18 20:38 
  279. *最后修改时间:    2012/09/18 20:38 
  280. *说明     :   无 
  281. ****************************************************************************************************************/  
  282. static long OK6410_DS18B20_ioctl(  
  283.         struct file *file,  
  284.         unsigned int cmd,  
  285.         unsigned long arg)  
  286. {  
  287.     return 0;  
  288. }  
  289.   
  290.   
  291. /**************************************************************************************************************** 
  292. *函数名        :   static ssize_t OK6410_DS18B20_write( 
  293.                         struct file *file, 
  294.                         const char __user *buff, 
  295.                         size_t size, 
  296.                         loff_t *loff) 
  297. *功能       : 写数据到DS18B20驱动模块,无效函数,返回0 
  298. *参数       : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用 
  299. *返回       : 0:成功;<0:失败 
  300. *依赖       :     linux底层宏 
  301. *作者       : 异灵元(cp1300@139.com) 
  302. *创建时间   :   2012/09/18 20:38 
  303. *最后修改时间:    2012/09/18 20:38 
  304. *说明     :   写无效 
  305. ****************************************************************************************************************/  
  306. static ssize_t OK6410_DS18B20_write(  
  307.         struct file *file,  
  308.         const char __user *buff,  
  309.         size_t size,  
  310.         loff_t *loff)  
  311. {  
  312.   
  313.     return 0;  
  314. }  
  315.   
  316.   
  317. /**************************************************************************************************************** 
  318. *函数名        :   static ssize_t OK6410_DS18B20_read( 
  319.                         struct file *file, 
  320.                         char __user *buff, 
  321.                         size_t size, 
  322.                         loff_t *loff) 
  323. *功能       : 读DS18B20状态,低电平灯亮 
  324. *参数       : file:文件指针(无作用);buff:数据缓冲区指针;buff:数据数量;loff:无作用 
  325. *返回       : 0:成功;<0:失败 
  326. *依赖       :     linux底层宏 
  327. *作者       : 异灵元(cp1300@139.com) 
  328. *创建时间   :   2012/09/18 20:38 
  329. *最后修改时间:    2012/09/18 20:38 
  330. *说明     :   读取到的是一个16位有符号的温度 
  331. ****************************************************************************************************************/  
  332. static ssize_t OK6410_DS18B20_read(  
  333.         struct file *file,  
  334.         char __user *buff,  
  335.         size_t size,  
  336.         loff_t *loff)  
  337. {  
  338.     int temp;  
  339.     int *p;  
  340.   
  341.     if(down_interruptible(&DS18B20_sem))    //获取信号量  
  342.         return -ERESTARTSYS;  
  343.     temp = DS18B20_ReadTemper();            //读取温度  
  344.     if(temp == DS18B20_ERROR)               //DS18B20初始化失败  
  345.         return -1;                              //DS18B20读取失败,返回错误  
  346.     p = (int *)buff;  
  347.     *p = temp;                                  //将温度写入到缓冲区  
  348.   
  349.     up(&DS18B20_sem);                           //释放信号量  
  350.   
  351.     return 0;  
  352. }  
  353.   
  354.   
  355.   
  356. /**************************************************************************************************************** 
  357. *函数名        :   static void __exit OK6410_DS18B20_exit(void) 
  358. *功能       : 卸载DS18B20驱动 
  359. *参数       : 无 
  360. *返回       : 无 
  361. *依赖       :     linux底层宏 
  362. *作者       : 异灵元(cp1300@139.com) 
  363. *创建时间   :   2012/09/18 20:38 
  364. *最后修改时间:    2012/09/18 20:38 
  365. *说明     :   卸载驱动 
  366. ****************************************************************************************************************/  
  367. static void __exit OK6410_DS18B20_exit(void)  
  368. {  
  369.     misc_deregister(&misc);         //卸载驱动  
  370. }  
  371.   
  372.   
  373.   
  374. //动态加载驱动接口(必须)  
  375. module_init(OK6410_DS18B20_init);  
  376. module_exit(OK6410_DS18B20_exit);  
  377. //其它信息(非必需)  
  378. MODULE_AUTHOR("cp1300@139.com");                        //驱动程序作者  
  379. MODULE_DESCRIPTION("OK6410(S3C6410) DS18B20 Driver");   //一些描述信息  
  380. MODULE_LICENSE("GPL");  //遵循的协议  

makefile

[cpp]  view plain  copy
  1. ARCH=arm  
  2. CROSS_COMPILE=arm-linux-  
  3. obj-m := ds18b20_drive.o  
  4. #ds18b20_drive-objs := ds18b20_drive.o  
  5. KDIR :=/home/cfan/linux/linux-3.0.1   
  6. PWD :=$(shell pwd)  
  7. all:  
  8.     $(MAKE) -C $(KDIR) M=$(PWD) modules  
  9. clean:  
  10.     $(MAKE) -C $(KDIR) M=$(PWD) clean  


测试

[cpp]  view plain  copy
  1. /**************************************************************************************************************** 
  2.  * 文件名称 :   ds18b20_teset.c 
  3.  * 简介       :   OK6410 DS18B20驱动测试程序 
  4.  * 作者       :   异灵元(cp1300@139.com) 
  5.  * 创建时间 :   2012/09/19 22:10 
  6.  * 修改时间 :   2012/09/19 
  7.  * 说明       :   OK6410 开发板(S3C6410)DS18B20(GPIO)驱动测试程序 
  8.  ****************************************************************************************************************/  
  9.   
  10.   
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include <unistd.h>  
  14. #include <fcntl.h>  
  15. #include <sys/ioctl.h>  
  16. #include <unistd.h>  
  17.   
  18.   
  19.   
  20. int main(void)  
  21. {  
  22.     int fd;  
  23.     int data;  
  24.   
  25.     //DS18B20测试  
  26.     printf("DS18B20 test...\n");  
  27.     fd = open("/dev/OK6410_DS18B20",O_RDONLY);      //open DS18B20  
  28.     if(fd == -1)  
  29.     {  
  30.         printf("open DS18B20 error!\n");  
  31.         exit(-1);  
  32.     }  
  33.     else  
  34.     {  
  35.         printf("open DS18B20 ok!\n");  
  36.     }  
  37.     while(1)  
  38.     {  
  39.             if(read(fd,&data,(size_t)2))  
  40.                 printf("read error!\n");  
  41.             printf("ds18b20 = %d\n",data);  
  42.             usleep(1000 * 1000);    //1000MS  
  43.     }  
  44. }  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值