ds18b20驱动及应用程序

------------------------------------------------------------------------------------------------------------------------------

交叉编译器:arm-linux-gcc-4.5.4

Linux内核版本:Linux-3.0

主机操作系统:Centos 6.5

开发板:FL2440

温度传感器:ds18b20

------------------------------------------------------------------------------------------------------------------------------

之前看过led的,platform_led的,platform_button的。当时以为看懂了,可是真的拿到一个模块要去写他的驱动的时候发现有些无从下手。于是借鉴了朋友的一篇混杂设备驱动,半抄半写的写出来了一个miscdevice类型的驱动。之后又在miscdevice与led的基础上写出来了cdev类型的驱动。并附上一个小小的测试程序。

一、miscdevice驱动

  1 #include <linux/interrupt.h>
  2 #include <linux/poll.h>
  3 #include <linux/configfs.h>
  4 #include <linux/module.h>
  5 #include <linux/kernel.h>
  6 #include <linux/fs.h>
  7 #include <linux/clk.h>
  8 #include <linux/init.h>
  9 #include <linux/device.h>
 10 #include <linux/miscdevice.h>
 11 #include <linux/delay.h>
 12 #include <linux/mm.h>
 13 #include <plat/regs-timer.h>
 14 #include <mach/regs-gpio.h>
 15 #include <mach/map.h>
 16 #include <mach/gpio-nrs.h>
 17 #include <mach/regs-irq.h>
 18 #include <asm/io.h>
 19 #include <mach/hardware.h>
 20 #include <asm/uaccess.h>
 21 #include <asm/system.h>
 22 #include <mach/regs-clock.h>
 23 #include <asm/irq.h>
 24 #include <linux/types.h>
 25 #include <linux/moduleparam.h>
 26 #include <linux/slab.h>
 27 #include <linux/errno.h>
 28 #include <linux/ioctl.h>
 29 #include <linux/cdev.h>
 30 #include <linux/string.h>
 31 #include <linux/list.h>
 32 #include <linux/pci.h>
 33 #include <asm/atomic.h>
 34 #include <asm/unistd.h>
 35 #include <linux/miscdevice.h>
 36 #include <linux/gpio.h>
 37
 38 /*********************************************************************************
 39  *      Copyright:  (C) 2016 2013dianxin_3
 40  *                  All rights reserved.
 41  *
 42  *       Filename:  ds18b20.c
 43  *    Description:  This file
 44  *
 45  *        Version:  1.0.0(08/07/2016)
 46  *         Author:  xiaohexiansheng <[email protected]>
 47  *      ChangeLog:  1, Release initial version on "08/07/2016 02:21:17 PM"
 48  *
 49  ********************************************************************************/
 50 #define DRV_AUTHOR                          "xiaohexiansheng <[email protected]>"
 51 #define DRV_DESC                            "s3c2440 ds18b20 driver"
 52 #define DEVICE_NAME                         "ds18b20"
 53
 54 #define LOW                                 0
 55 #define HIGH                                1
 56 typedef unsigned char BYTE;
 57
 58 static BYTE data[2];
 59
 60 BYTE ds18b20_reset(void)
 61 {
 62     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);         //配置GP0输出模式
 63     s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);            //向ds18b20发送一个下降沿,并保持480us
 64     udelay(480);
 65     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);            //向ds18b20发送一个上升沿,此时可释放ds18b20总线
 66     udelay(60);
 67
 68 //以上动作是给ds18b20一个复位脉冲,通过配置GPIO引脚为输入模式可检测ds18b20是否复位成功
 69     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
 70 //若总线在释放后为高电平,则复位失败
 71     if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
 72     {
 73         printk("ds18b20 reset failed.\r\n");
 74         return 1;
 75     }
 76     udelay(240);
 77     return 0;
 78 }
 79
 80 BYTE ds18b20_read_byte(void)
 81 {
 82     BYTE i = 0;
 83     BYTE byte = 0;
 84     // 读“1”时隙:
 85     //     若总线状态保持在低电平状态1微秒到15微秒之间
 86     //     然后跳变到高电平状态且保持在15微秒到60微秒之间
 87     //      就认为从DS18B20读到一个“1”信号
 88     //     理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平
 89     // 读“0”时隙:
 90     //     若总线状态保持在低电平状态15微秒到30微秒之间
 91     //     然后跳变到高电平状态且保持在15微秒到60微秒之间
 92     //     就认为从DS18B20读到一个“0”信号
 93     //     理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平
 94     for(i = 0; i < 8; i++)
 95     {
 96         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
 97
 98         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
 99         udelay(1);
100         byte >>= 1;
101         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
102         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
103         // 若总线在我们设它为低电平之后若1微秒之内变为高
104         // 则认为从DS18B20处收到一个“1”信号
105         // 因此把byte的D7为置“1”
106         if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
107             byte |= 0x80;
108         udelay(50);
109     }
110     return byte;
111 }
112
113 BYTE ds18b20_write_byte(BYTE byte)
114 {
115     BYTE i;
116     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);            // 配置GPG0为输出模式
117     // 写“1”时隙:
118     //     保持总线在低电平1微秒到15微秒之间
119     //     然后再保持总线在高电平15微秒到60微秒之间
120     //     理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平
121     // 写“0”时隙:
122     //     保持总线在低电平15微秒到60微秒之间
123     //     然后再保持总线在高电平1微秒到15微秒之间
124     //     理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平
125     for(i = 0; i < 8; i++)
126     {
127         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
128         udelay(15);
129         if(byte & HIGH)
130         {
131             // 若byte变量的D0位是1,则需向总线上写“1”
132             // 根据写“1”时隙规则,电平在此处翻转为高
133             s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
134         }
135         else
136         {
137             // 若byte变量的D0位是0,则需向总线上写“0”
138             // 根据写“0”时隙规则,电平在保持为低
139             s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
140         }
141         // 电平状态保持60微秒
142         udelay(45);
143
144         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);        //释放总线
145         udelay(1);
146         byte >>= 1;
147     }
148     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);        //释放总线
149 }
150
151 void ds18b20_proc(void)                //读取温度
152 {
153     while(ds18b20_reset());            //循环判断DS18B20直到复位,延时120ms;
154     udelay(120);
155     ds18b20_write_byte(0xcc);        //写入CCH命令,跳过读序列号过程;
156     ds18b20_write_byte(0x44);        //写入44H命令,开始温度转换,延时5 ms;
157     udelay(5);
158
159     while(ds18b20_reset());            //循环判断DS18B20直到复位,延时200 ms;
160     udelay(200);
161     ds18b20_write_byte(0xcc);        //写入CCH命令,跳过读序列号过程;
162     ds18b20_write_byte(0xbe);        //写入BEH命令,读取寄存器;
163
164     data[0] = ds18b20_read_byte();            //读温度整数部分;
165     data[1] = ds18b20_read_byte();            //读温度小数部分
166 }
167
168 static ssize_t s3c2440_ds18b20_read(struct file *filp, char *buff, size_t len, loff_t *off)
169 {
170     ds18b20_proc();
171
172     buff[0] = data[0];
173     buff[1] = data[1];
174
175     return 1;
176 }
177
178 static struct file_operations s3c2440_ds18b20_fops =
179 {
180     .owner = THIS_MODULE,
181     .read = s3c2440_ds18b20_read,
182 };
183
184 static struct miscdevice misc =
185 {
186     .minor = MISC_DYNAMIC_MINOR,
187     .name = DEVICE_NAME,
188     .fops = &s3c2440_ds18b20_fops,
189 };
190
191 static int __init s3c2440_ds18b20_init(void)
192 {
193     int result;
194     result = misc_register(&misc);
195     printk(DEVICE_NAME "initialized.\n");
196
197     while(ds18b20_reset());
198     return result;
199 }
200
201 static void __exit s3c2440_ds18b20_exit(void)
202 {
203     misc_deregister(&misc);
204 }
205
206 module_init(s3c2440_ds18b20_init);
207 module_exit(s3c2440_ds18b20_exit);
208 MODULE_AUTHOR(DRV_AUTHOR);
209 MODULE_DESCRIPTION(DRV_DESC);
210 MODULE_LICENSE("GPL");

二、cdevdevice驱动

  1 #include <linux/module.h>
  2 #include <linux/init.h>
  3 #include <linux/kernel.h>
  4 #include <linux/fs.h>
  5 #include <linux/delay.h>
  6 #include <asm/irq.h>
  7 #include <mach/regs-gpio.h>
  8 #include <mach/hardware.h>
  9 #include <linux/cdev.h>
 10 #include <linux/device.h>
 11 #include <linux/kdev_t.h>
 12 #include <asm/uaccess.h>
 13 #include <linux/platform_device.h>
 14 #include <linux/gpio.h>
 15
 16 /*********************************************************************************
 17  *      Copyright:  (C) 2016 2013dianxin_3
 18  *                  All rights reserved.
 19  *
 20  *       Filename:  ds18b20.c
 21  *    Description:  This file
 22  *
 23  *        Version:  1.0.0(08/08/2016)
 24  *         Author:  xiaohexiansheng <[email protected]>
 25  *      ChangeLog:  1, Release initial version on "08/08/2016 03:44:48 PM"
 26  *
 27  ********************************************************************************/
 28 #define DRV_AUTHOR                          "xiaohexiansheng <[email protected]>"
 29 #define DRV_DESC                            "S3C2440 ds18b20 driver"
 30
 31 #define DEV_NAME                            "ds18b20"
 32 #define DISABLE                             0
 33 #define DRV_MAJOR_VER                       1
 34 #define DRV_MINOR_VER                       0
 35 #define DRV_REVER_VER                       0
 36
 37 #define LOW                                 0
 38 #define HIGH                                1
 39
 40 #ifndef DEV_MAJOR
 41 #define DEV_MAJOR                           0
 42 #endif
 43
 44 int dev_major = DEV_MAJOR;
 45 int dev_minor = 0;
 46 int debug = DISABLE;
 47
 48 static struct cdev          *ds18b20_cdev;
 49
 50 typedef unsigned char BYTE;
 51 static BYTE data[2];
 52
 53 BYTE ds18b20_reset(void)
 54 {
 55     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
 56     s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
 57     udelay(480);
 58     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
 59     udelay(60);
 60
 61     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
 62     if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
 63     {
 64         printk("ds18b20 reset failed.\r\n");
 65         return 1;
 66     }
 67     udelay(240);
 68     return 0;
 69 }
 70
 71 BYTE ds18b20_read_byte(void)
 72 {
 73     BYTE i = 0;
 74     BYTE byte = 0;
 75
 76     for(i = 0; i < 8; i++)
 77     {
 78         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
 79         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
 80         udelay(1);
 81         byte >>= 1;
 82         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
 83         s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_INPUT);
 84         if(s3c2410_gpio_getpin(S3C2410_GPG(0)))
 85             byte |= 0x80;
 86         udelay(50);
 87     }
 88     return byte;
 89 }
 90
 91 BYTE ds18b20_write_byte(BYTE byte)
 92 {
 93     BYTE i;
 94     s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
 95     for(i = 0; i < 8; i++)
 96     {
 97         s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
 98         udelay(15);
 99         if(byte & HIGH)
100         {
101             s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
102         }
103         else
104         {
105             s3c2410_gpio_setpin(S3C2410_GPG(0), LOW);
106         }
107         udelay(45);
108
109         s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
110         udelay(1);
111         byte >>= 1;
112     }
113     s3c2410_gpio_setpin(S3C2410_GPG(0), HIGH);
114     return 0;
115 }
116
117 void ds18b20_proc(void)
118 {
119         while(ds18b20_reset());
120         udelay(120);
121         ds18b20_write_byte(0xcc);
122         ds18b20_write_byte(0x44);
123         udelay(5);
124
125         while(ds18b20_reset());
126         udelay(200);
127         ds18b20_write_byte(0xcc);
128         ds18b20_write_byte(0xbe);
129
130         data[0] = ds18b20_read_byte();
131         data[1] = ds18b20_read_byte();
132 }
133
134 static ssize_t s3c2440_ds18b20_read(struct file *filp, char *buff, size_t len, loff_t *off)
135 {
136         ds18b20_proc();
137
138         buff[0] = data[0];
139         buff[1] = data[1];
140
141         return 1;
142 }
143
144 static struct file_operations ds18b20_fops =
145 {
146
147     .owner = THIS_MODULE,
148     .read = s3c2440_ds18b20_read,
149 };
150
151 static int __init s3c_ds18b20_init(void)
152 {
153     int                     result;
154     dev_t                   devno;
155
156     if(0 != ds18b20_reset())
157     {
158         printk(KERN_ERR "s3c2440 ds18b20 hardware initialize failure.\n");
159         return -ENODEV;
160     }
161
162     if(0 != dev_major)
163     {
164         devno = MKDEV(dev_major, 0);
165         result = register_chrdev_region(devno, 1, DEV_NAME);
166     }
167     else
168     {
169         result = alloc_chrdev_region(&devno, dev_minor, 1, DEV_NAME);
170         dev_major = MAJOR(devno);
171     }
172
173     if(result < 0)
174     {
175         printk(KERN_ERR "s3c %s driver cannot use major %d.\n", DEV_NAME, dev_major);
176         return -ENODEV;
177     }
178     printk(KERN_DEBUG "s3c %s driver use major %d.\n", DEV_NAME, dev_major);
179
180     if(NULL == (ds18b20_cdev = cdev_alloc()))
181     {
182         printk(KERN_ERR "s3c %s driver cannot register cdev: result = %d.\n", DEV_NAME, result);
183         unregister_chrdev_region(devno, 1);
184         return -ENOMEM;
185     }
186
187     ds18b20_cdev -> owner = THIS_MODULE;
188     cdev_init(ds18b20_cdev, &ds18b20_fops);
189
190     result = cdev_add(ds18b20_cdev, devno, 1);
191     if(0 != result)
192     {
193         printk(KERN_ERR "s3c %s driver cannot register cdev: result = %d.\n", DEV_NAME, result);
194         goto ERROR;
195     }
196
197     printk(KERN_ERR "s3c %s driver[major=%d] Version %d.%d.%d installed successfully.\n",DEV_NAME, dev_major, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
198     return 0;
199
200 ERROR:
201     printk(KERN_ERR "s3c %s driver installed failure./", DEV_NAME);
202     cdev_del(ds18b20_cdev);
203     unregister_chrdev_region(devno, 1);
204     return result;
205 }
206
207 static void __exit s3c_ds18b20_exit(void)
208 {
209     dev_t devno = MKDEV(dev_major, dev_minor);
210
211     cdev_del(ds18b20_cdev);
212     unregister_chrdev_region(devno, 1);
213
214     printk(KERN_ERR "s3c %s driver version %d.%d.%d removed!\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
215     return;
216 }
217
218 module_init(s3c_ds18b20_init);
219 module_exit(s3c_ds18b20_exit);
220
221 module_param(debug, int, S_IRUGO);
222 module_param(dev_major, int ,S_IRUGO);
223
224 MODULE_AUTHOR(DRV_AUTHOR);
225 MODULE_DESCRIPTION(DRV_DESC);
226 MODULE_LICENSE("GPL");

注:cdev的驱动需要手动创建设备节点,而misc不需要

三、测试程序

 1 /*********************************************************************************
 2  *      Copyright:  (C) 2016 2013dianxin_3
 3  *                  All rights reserved.
 4  *
 5  *       Filename:  dsapp.c
 6  *    Description:  This file
 7  *
 8  *        Version:  1.0.0(08/08/2016)
 9  *         Author:  xiaohexiansheng <[email protected]>
10  *      ChangeLog:  1, Release initial version on "08/08/2016 10:19:25 AM"
11  *
12  ********************************************************************************/
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/ioctl.h>
16 #include <stdlib.h>
17 #include <termios.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <sys/time.h>
21
22 /********************************************************************************
23  *  Description:
24  *   Input Args:
25  *  Output Args:
26  * Return Value:
27  ********************************************************************************/
28 int main (int argc, char **argv)
29 {
30     int fd;
31     double result = 0;
32     unsigned char buff[2];
33     unsigned short temp = 0;
34     int flag = 0;
35
36     if ((fd=open("/dev/ds18b20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
37     {
38         perror("open device ds18b20 failed.\r\n");
39         exit(1);
40     }
41     while(1)
42     {
43         printf("open device ds18b20 success.\r\n");
44         read(fd, buff, sizeof(buff));
45         temp=((unsigned short)buff[1])<<8;
46         temp|=(unsigned short)buff[0];
47         result=0.0625*((double)temp);
48         printf("temperature is %4f \r\n", result);
49         sleep(2);
50     }
51     close(fd);
52
53     return 0;
54 } /* ----- End of main() ----- */
时间: 2024-10-24 15:25:03

ds18b20驱动及应用程序的相关文章

openwrt驱动与应用程序的联系

应用程序与驱动之间需要进行命令的传递,因而它们之间需要共同定义一套双方都可以识别的数据结构,实际使用时它们include的是名字和内容相同但位置不同的头文件. 比如spi_gpio_ad7193.h这个头文件中包含有仅给驱动所使用的结构 _mode/_conf struct _mode { // Mode Register Settings unsigned char mode:3; unsigned char dat_sta:1; unsigned char clk:2; unsigned c

级联高压载波调制以及光纤驱动的FPGA程序

级联高压载波调制以及光纤驱动的FPGA程序 2017-04-10 13:27 173人阅读 评论(0) 收藏 举报  分类: FPGA(7)  高压变频(36)  程序备忘(42)  算法(39)  版权声明:本文为博主原创文章,可以转载 注:POS,NEG,ZERO的高低电平转换时间不一样

基于Linux3.0.8+smart210的DS18B20驱动移植

Linux内核:Linux3.0.8 硬件:友善之臂smart210开发板,A8内核 编译器:arm-linux-gcc 4.5.1 DS18B20是常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点.工作电压 3.0~5.5V/DC 超低功耗静态功耗<3uA,测温范围 -55℃-+125℃, 测量结果以9~12位数字量方式串行传送. 面对着扁平的那一面,左负右正,一旦接反就会立刻发热,有可能烧毁!同时,接反也是导致该传感器总是显示85℃的原因. DS18B20实物图 DS18

input子系统——架构、驱动、应用程序

一.input子系统架构 input子系统由驱动层drivers,输入子系统核心层input core,事件处理层event handler组成. 一个输入事件,通过输入设备发给系统如鼠标移动,键盘按键按下等通过device driver->input core(handler->event函数)->event handler->user space的顺序到达用户空间传给应用程序. 一个输出事件,通过系统发给输入设备,通过user space->event handler-&

第1个linux驱动___应用程序才是大Boss

我们的驱动模块已经可以被自动分配主设备号了,可以说到目前为止,一个驱动模块所具备的一些"基础设施"它都具备了,就像是养兵前日,用兵一时,已经可以让first_drv这个驱动模块出去打仗了. 那么说是出去打仗,总得有个发号施令的首长吧,在linux系统中,这位调兵遣将的首长就是应用程序,应用程序才是大Boss,我们"一直精雕细琢的驱动模块"说白了只是个跑腿的. 这就是为什么我们的专题是第1个linux驱动却要讲应用程序的原因,因为应用程序是让驱动程序能够被应用的,而驱

Linux嵌入式学习-ds18b20驱动

ds18b20的时序图如下: 复位时序: 读写时序: 以下是程序代码: #include <linux/module.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/fs.h> #include <linux/slab.h>

liunx内核移植(三)——内核、驱动、应用程序、根文件系统的关系

一:驱动属于内核的一部分 (1)驱动就是内核中的硬件设备管理模块 (2)驱动工作在内核态. (3)驱动程序故障可能导致整个内核崩溃 (4)驱动程序漏洞会使内核不安全 二:应用程序和内核的关系 (1)应用程序不属于内核,而是在内核之上的 (2)应用程序工作在用户态,是受限制的. (3)应用程序故障不会导致内核崩溃 (4)应用程序通过内核定义的API接口来调用内核工作,也就是说应 用程序依赖于内核,比如C语言的标准库就属于一个应用程序,所以在 内核当中不能使用C标准库,而是要使用liunx内核中的库

DS18B20 驱动编写

嵌入式开发平台:mini2440 DS18B20 所用GPIO:S3C2410_GPF(3) 一.DS18B20 时序分析 DS18B20的一线工作协议流程是:初始化→ROM操作指令→存储器操作指令→数据传输,其工作时序包括:初始化时序.写时序.读时序. 1.初始化时序 主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答,若无低电平出现一直都是高电平说明总线上无器件应答.  作为从器件的DS

STM32液晶显示HT1621驱动原理及程序代码

1.HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示: 图1 与单片机相连接控制的有9脚CS,3脚WR,12脚DATA,其功能描述如下表. 图2 2.字符显示原理 液晶管点亮和熄灭原理分别为在对应的RAM地址中写1和写0.首先需要清楚所驱动控制的液晶的COM-SEG对应关系,然后需要了解HT1621的32×4RAM地址映射. 例如要控制的液晶的装脚成品图部分如下: 图