歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 基於Tiny6410的ds18b20驅動

基於Tiny6410的ds18b20驅動

日期:2017/3/1 10:32:56   编辑:Linux編程

從網站上下載了lixin的mini2410的ds18b20代碼,並做了修改,成功實現了Tiny6410的ds18b20驅動。感謝署名為lixin的網友!

【程序清單】

ds18b20.c

[html]
  1. /******************************************Copyright(c)************************************************
  2. ** 文件名稱: ds18b20_drv.c
  3. ** 作 者: lixin
  4. ** 版 本: v1.0
  5. ** 說 明: ds18b20驅動程序.工作過程及時序見ds18b20 datasheet
  6. ** 修改記錄: 2009-8-27創建
  7. ** 最後修改時間: 2009-09-01
  8. ******************************************************************************************************/
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/delay.h>
  12. #include <linux/kernel.h>
  13. #include <linux/moduleparam.h>
  14. #include <linux/init.h>
  15. #include <linux/types.h>
  16. #include <linux/fs.h>
  17. #include <mach/regs-gpio.h>
  18. #include <linux/device.h>
  19. #include <mach/hardware.h>
  20. #include <linux/cdev.h>
  21. #include <asm/uaccess.h>
  22. #include <linux/errno.h>
  23. #include "s3c6410_gpio.h"
  24. //#define DEBUG
  25. /* 相關引腳定義,方便以後移植 */
  26. #define DEVICE_NAME "ds18b20"
  27. #define DQ 8
  28. #define CFG_IN 0
  29. #define CFG_OUT 1
  30. // ds18b20主次設備號(動態分配)
  31. int ds18b20_major = 0;
  32. int ds18b20_minor = 0;
  33. int ds18b20_nr_devs = 1;
  34. // 定義設備類型
  35. static struct ds18b20_device {
  36. struct cdev cdev;
  37. };
  38. struct ds18b20_device ds18b20_dev;
  39. static struct class *ds18b20_class;
  40. /* 函數聲明 */
  41. static int ds18b20_open(struct inode *inode, struct file *filp);
  42. static int ds18b20_init(void);
  43. static void write_byte(unsigned char data);
  44. static unsigned char read_byte(void);
  45. static ssize_t ds18b20_read(struct file *filp, char __user *buf,
  46. size_t count, loff_t *f_pos);
  47. void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);
  48. /******************************************************************************************************
  49. ** 函數名稱: ds18b20_open()
  50. ** 函數功能: 打開設備,初始化ds18b20
  51. ** 入口參數: inode:設備文件信息; filp: 被打開的文件的信息
  52. ** 出口參數: 成功時返回0,失敗返回-1
  53. ** 備 注:
  54. ******************************************************************************************************/
  55. static int ds18b20_open(struct inode *inode, struct file *filp)
  56. {
  57. int flag = 0;
  58. /*struct ds18b20_device *dev;
  59. dev = container_of(inode->i_cdev, struct ds18b20_device, cdev);
  60. filp->private_data = dev;*/
  61. flag = ds18b20_init();
  62. if(flag & 0x01)
  63. {
  64. #ifdef DEBUG
  65. printk(KERN_WARNING "open ds18b20 failed\n");
  66. #endif
  67. return -1;
  68. }
  69. #ifdef DEBUG
  70. printk(KERN_NOTICE "open ds18b20 successful\n");
  71. #endif
  72. return 0;
  73. }
  74. /******************************************************************************************************
  75. ** 函數名稱: ds18b20_init()
  76. ** 函數功能: 復位ds18b20
  77. ** 入口參數: 無
  78. ** 出口參數: retval:成功返回0,失敗返回1
  79. ** 備 注: 操作時序見ds18b20 datasheet
  80. ******************************************************************************************************/
  81. static int ds18b20_init(void)
  82. {
  83. int retval = 0;
  84. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
  85. s3c6410_gpio_pullup(DQ, 0);
  86. s3c6410_gpio_setpin(DQ, 1);
  87. udelay(2);
  88. s3c6410_gpio_setpin(DQ, 0); // 拉低ds18b20總線,復位ds18b20
  89. udelay(500); // 保持復位電平500us
  90. s3c6410_gpio_setpin(DQ, 1); // 釋放ds18b20總線
  91. udelay(60);
  92. // 若復位成功,ds18b20發出存在脈沖(低電平,持續60~240us)
  93. s3c6410_gpio_cfgpin(DQ, CFG_IN);
  94. retval = s3c6410_gpio_getpin(DQ);
  95. udelay(500);
  96. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
  97. s3c6410_gpio_pullup(DQ, 0);
  98. s3c6410_gpio_setpin(DQ, 1); // 釋放總線
  99. return retval;
  100. }
  101. /******************************************************************************************************
  102. ** 函數名稱: write_byte()
  103. ** 函數功能: 向18b20寫入一個字節數據
  104. ** 入口參數: data
  105. ** 出口參數: 無
  106. ** 備 注:
  107. ******************************************************************************************************/
  108. static void write_byte(unsigned char data)
  109. {
  110. int i = 0;
  111. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
  112. s3c6410_gpio_pullup(DQ, 1);
  113. for (i = 0; i < 8; i ++)
  114. {
  115. // 總線從高拉至低電平時,就產生寫時隙
  116. s3c6410_gpio_setpin(DQ, 1);
  117. udelay(2);
  118. s3c6410_gpio_setpin(DQ, 0);
  119. s3c6410_gpio_setpin(DQ, data & 0x01);
  120. udelay(60);
  121. data >>= 1;
  122. }
  123. s3c6410_gpio_setpin(DQ, 1); // 重新釋放ds18b20總線
  124. }
  125. /******************************************************************************************************
  126. ** 函數名稱: read_byte()
  127. ** 函數功能: 從ds18b20讀出一個字節數據
  128. ** 入口參數: 無
  129. ** 出口參數: 讀出的數據
  130. ** 備 注:
  131. ******************************************************************************************************/
  132. static unsigned char read_byte(void)
  133. {
  134. int i;
  135. unsigned char data = 0;
  136. for (i = 0; i < 8; i++)
  137. {
  138. // 總線從高拉至低,只需維持低電平17ts,再把總線拉高,就產生讀時隙
  139. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
  140. s3c6410_gpio_pullup(DQ, 0);
  141. s3c6410_gpio_setpin(DQ, 1);
  142. udelay(2);
  143. s3c6410_gpio_setpin(DQ, 0);
  144. udelay(2);
  145. s3c6410_gpio_setpin(DQ, 1);
  146. udelay(8);
  147. data >>= 1;
  148. s3c6410_gpio_cfgpin(DQ, CFG_IN);
  149. if (s3c6410_gpio_getpin(DQ))
  150. data |= 0x80;
  151. udelay(50);
  152. }
  153. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
  154. s3c6410_gpio_pullup(DQ, 0);
  155. s3c6410_gpio_setpin(DQ, 1); // 釋放ds18b20總線
  156. return data;
  157. }
  158. /******************************************************************************************************
  159. ** 函數名稱: ds18b20_read()
  160. ** 函數功能: 讀出18b20的溫度
  161. ** 入口參數:
  162. ** 出口參數:
  163. ** 備 注:
  164. ******************************************************************************************************/
  165. static ssize_t ds18b20_read(struct file *filp, char __user *buf,
  166. size_t count, loff_t *f_pos)
  167. {
  168. int flag;
  169. unsigned long err;
  170. unsigned char result[2] = {0x00, 0x00};
  171. //struct ds18b20_device *dev = filp->private_data;
  172. flag = ds18b20_init();
  173. if (flag)
  174. {
  175. #ifdef DEBUG
  176. printk(KERN_WARNING "ds18b20 init failed\n");
  177. #endif
  178. return -1;
  179. }
  180. write_byte(0xcc);
  181. write_byte(0x44);
  182. flag = ds18b20_init();
  183. if (flag)
  184. return -1;
  185. write_byte(0xcc);
  186. write_byte(0xbe);
  187. result[0] = read_byte(); // 溫度低八位
  188. result[1] = read_byte(); // 溫度高八位
  189. err = copy_to_user(buf, &result, sizeof(result));
  190. return err ? -EFAULT : min(sizeof(result),count);
  191. }
  192. /**************************************************************
  193. * 字符驅動程序的核心,應用程序所調用的open,read等函數最終會
  194. * 調用這個結構中的對應函數
  195. *************************************************************/
  196. static struct file_operations ds18b20_dev_fops = {
  197. .owner = THIS_MODULE,
  198. .open = ds18b20_open,
  199. .read = ds18b20_read,
  200. };
  201. /******************************************************************************************************
  202. ** 函數名稱: ds18b20_setup_cdev()
  203. ** 函數功能: 初始化cdev
  204. ** 入口參數: dev:設備結構體; index:
  205. ** 出口參數: 無
  206. ** 備 注:
  207. ******************************************************************************************************/
  208. void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)
  209. {
  210. int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);
  211. cdev_init(&dev->cdev, &ds18b20_dev_fops);
  212. dev->cdev.owner = THIS_MODULE;
  213. err = cdev_add(&(dev->cdev), devno, 1);
  214. if (err)
  215. {
  216. #ifdef DEBUG
  217. printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);
  218. #endif
  219. }
  220. }
  221. /******************************************************************************************************
  222. ** 函數名稱: ds18b20_dev_init()
  223. ** 函數功能: 為溫度傳感器分配注冊設備號,初始化cdev
  224. ** 入口參數: 無
  225. ** 出口參數: 若成功執行,返回0
  226. ** 備 注:
  227. ******************************************************************************************************/
  228. static int __init ds18b20_dev_init(void)
  229. {
  230. ds18b20_major = register_chrdev(ds18b20_major, DEVICE_NAME, &ds18b20_dev_fops);
  231. if (ds18b20_major<0)
  232. {
  233. printk(DEVICE_NAME " Can't register major number!\n");
  234. return -EIO;
  235. }
  236. ds18b20_class = class_create(THIS_MODULE, DEVICE_NAME);
  237. device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, ds18b20_minor), NULL, DEVICE_NAME);
  238. #ifdef DEBUG
  239. printk(KERN_WARNING "register ds18b20 driver successful!\n");
  240. #endif
  241. return 0;
  242. }
  243. /******************************************************************************************************
  244. ** 函數名稱: ds18b20_dev_exit()
  245. ** 函數功能: 注銷設備
  246. ** 入口參數: 無
  247. ** 出口參數: 無
  248. ** 備 注:
  249. ******************************************************************************************************/
  250. static void __exit ds18b20_dev_exit(void)
  251. {
  252. device_destroy(ds18b20_class, MKDEV(ds18b20_major,ds18b20_minor));
  253. class_unregister(ds18b20_class);
  254. class_destroy(ds18b20_class);
  255. unregister_chrdev(ds18b20_major, DEVICE_NAME);
  256. #ifdef DEBUG
  257. printk(KERN_WARNING "Exit ds18b20 driver!\n");
  258. #endif
  259. }
  260. module_init(ds18b20_dev_init);
  261. module_exit(ds18b20_dev_exit);
  262. MODULE_LICENSE("Dual BSD/GPL");
  263. MODULE_AUTHOR("[email protected]");
  264. /******************************************************************************************************
  265. ** 文件到此結束
  266. ******************************************************************************************************/
Copyright © Linux教程網 All Rights Reserved