01.#include <linux/init.h>
02.#include <linux/module.h>
03.#include <linux/delay.h>
04.#include <linux/kernel.h>
05.#include <linux/moduleparam.h>
06.#include <linux/init.h>
07.#include <linux/types.h>
08.#include <linux/fs.h>
09.#include <mach/regs-gpio.h>
10.#include <linux/device.h>
11.#include <mach/hardware.h>
12.#include <linux/cdev.h>
13.#include <asm/uaccess.h rel='nofollow' onclick='return false;'>
14.#include <linux/errno.h>
15.
16.#include "ds18b20.h"
17.
18.//#define DEBUG
19./* 相关引脚定义,方便以后移植 */
20.#define DEVICE_NAME "ds18b20"
21.#define DQ 8
22.#define CFG_IN 0
23.#define CFG_OUT 1
24.
25.// ds18b20主次设备号(动态分配)
26.int ds18b20_major = 0;
27.int ds18b20_minor = 0;
28.int ds18b20_nr_devs = 1;
29.
30.// 定义设备类型
31.static struct ds18b20_device {
32. struct cdev cdev;
33.};
34.struct ds18b20_device ds18b20_dev;
35.
36.static struct class *ds18b20_class;
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,
44. size_t count, loff_t *f_pos);
45.void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);
46.
47.
48.
49.
50./*
51. 函数名称: ds18b20_open()
52. 函数功能: 打开设备,初始化ds18b20
53. 入口参数: inode:设备文件信息; filp: 被打开的文件的信息
54. 出口参数: 成功时返回0,失败返回-1
55.*/
56.
57.static int ds18b20_open(struct inode *inode, struct file *filp)
58.{
59. int flag = 0;
60. /*struct ds18b20_device *dev;
61. dev = container_of(inode->i_cdev, struct ds18b20_device, cdev);
62. filp->private_data = dev;*/
63.
64. flag = ds18b20_init();
65. if(flag & 0x01)
66. {
67.#ifdef DEBUG
68. printk(KERN_WARNING "open ds18b20 failed\n");
69.#endif
70. return -1;
71. }
72.#ifdef DEBUG
73. printk(KERN_NOTICE "open ds18b20 successful\n");
74.#endif
75. return 0;
76.}
77.
78.
79.
80.
81.
82.
83./*
84. 函数名称: ds18b20_init()
85. 函数功能: 复位ds18b20
86. 入口参数: 无
87. 出口参数: retval:成功返回0,失败返回1
88. 备 注: 操作时序见ds18b20 datasheet
89.*/
90.
91.static int ds18b20_init(void)
92.{
93. int retval = 0;
94.
95. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
96. s3c6410_gpio_pullup(DQ, 0);
97.
98. s3c6410_gpio_setpin(DQ, 1);
99. udelay(2);
100. s3c6410_gpio_setpin(DQ, 0); // 拉低ds18b20总线,复位ds18b20
101. udelay(500); // 保持复位电平500us
102.
103. s3c6410_gpio_setpin(DQ, 1); // 释放ds18b20总线
104. udelay(60);
105.
106. // 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)
107. s3c6410_gpio_cfgpin(DQ, CFG_IN);
108. retval = s3c6410_gpio_getpin(DQ);
109.
110. udelay(500);
111. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
112. s3c6410_gpio_pullup(DQ, 0);
113. s3c6410_gpio_setpin(DQ, 1); // 释放总线
114.
115. return retval;
116.}
117.
118.
119.
120.
121.
122./*
123. 函数名称: write_byte()
124. 函数功能: 向18b20写入一个字节数据
125. 入口参数: data
126. 出口参数: 无
127.*/
128.static void write_byte(unsigned char data)
129.{
130. int i = 0;
131.
132. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
133. s3c6410_gpio_pullup(DQ, 1);
134.
135. for (i = 0; i < 8; i ++)
136. {
137. // 总线从高拉至低电平时,就产生写时隙
138. s3c6410_gpio_setpin(DQ, 1);
139. udelay(2);
140. s3c6410_gpio_setpin(DQ, 0);
141. s3c6410_gpio_setpin(DQ, data & 0x01);
142. udelay(60);
143. data >>= 1;
144. }
145. s3c6410_gpio_setpin(DQ, 1); // 重新释放ds18b20总线
146.}
147.
148.
149.
150.
151.
152./*
153. 函数名称: read_byte()
154. 函数功能: 从ds18b20读出一个字节数据
155. 入口参数: 无
156. 出口参数: 读出的数据
157.*/
158.
159.static unsigned char read_byte(void)
160.{
161. int i;
162. unsigned char data = 0;
163.
164. for (i = 0; i < 8; i++)
165. {
166. // 总线从高拉至低,只需维持低电平17ts,再把总线拉高,就产生读时隙
167. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
168. s3c6410_gpio_pullup(DQ, 0);
169. s3c6410_gpio_setpin(DQ, 1);
170. udelay(2);
171. s3c6410_gpio_setpin(DQ, 0);
172. udelay(2);
173. s3c6410_gpio_setpin(DQ, 1);
174. udelay(8);
175. data >>= 1;
176. s3c6410_gpio_cfgpin(DQ, CFG_IN);
177. if (s3c6410_gpio_getpin(DQ))
178. data |= 0x80;
179. udelay(50);
180. }
181. s3c6410_gpio_cfgpin(DQ, CFG_OUT);
182. s3c6410_gpio_pullup(DQ, 0);
183. s3c6410_gpio_setpin(DQ, 1); // 释放ds18b20总线
184. return data;
185.}
186.
187.
188.
189.
190.
191./*
192. 函数名称: ds18b20_read()
193. 函数功能: 读出18b20的温度
194.*/
195.
196.static ssize_t ds18b20_read(struct file *filp, char __user *buf,
197. size_t count, loff_t *f_pos)
198.{
199. int flag;
200. unsigned long err;
201. unsigned char result[2] = {0x00, 0x00};
202. //struct ds18b20_device *dev = filp->private_data;
203.
204. flag = ds18b20_init();
205. if (flag)
206. {
207.#ifdef DEBUG
208. printk(KERN_WARNING "ds18b20 init failed\n");
209.#endif
210. return -1;
211. }
212.
213. write_byte(0xcc);
214. write_byte(0x44);
215.
216. flag = ds18b20_init();
217. if (flag)
218. return -1;
219.
220. write_byte(0xcc);
221. write_byte(0xbe);
222.
223. result[0] = read_byte(); // 温度低八位
224. result[1] = read_byte(); // 温度高八位
225.
226. err = copy_to_user(buf, &result, sizeof(result));
227. return err ? -EFAULT : min(sizeof(result),count);
228.}
229.
230.
231.
232.
233.
234./*
235. 字符驱动程序的核心,应用程序所调用的open,read等函数最终会
236. 调用这个结构中的对应函数
237.*/
238.static struct file_operations ds18b20_dev_fops = {
239. .owner = THIS_MODULE,
240. .open = ds18b20_open,
241. .read = ds18b20_read,
242.};
243.
244.
245./*
246. 函数名称: ds18b20_setup_cdev()
247. 函数功能: 初始化cdev
248. 入口参数: dev:设备结构体; index:
249.*/
250.
251.void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)
252.{
253. int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);
254.
255. cdev_init(&dev->cdev, &ds18b20_dev_fops);
256. dev->cdev.owner = THIS_MODULE;
257. err = cdev_add(&(dev->cdev), devno, 1);
258. if (err)
259. {
260.#ifdef DEBUG
261. printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);
262.#endif
263. }
264.}
265.
266.
267.
268.
269.
270.
271./*
272. 函数名称: ds18b20_dev_init()
273. 函数功能: 为温度传感器分配注册设备号,初始化cdev
274. 入口参数: 无
275. 出口参数: 若成功执行,返回0
276.*/
277.
278.static int __init ds18b20_dev_init(void)
279.{
280. ds18b20_major = register_chrdev(ds18b20_major, DEVICE_NAME, &ds18b20_dev_fops);
281. if (ds18b20_