ds18b20 Linux驱动
2016-05-20 09:55
399 查看
DS18B20是常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。工作电压 3.0~5.5V/DC
超低功耗静态功耗<3uA,测温范围 -55℃~+125℃,
测量结果以9~12位数字量方式串行传送。
面对着扁平的那一面,左负右正,一旦接反就会立刻发热,有可能烧毁!同时,接反也是导致该传感器总是显示85℃的原因。
DS18B20实物图
![](http://www.myexception.cn/img/2015/05/25/1214141731.jpg)
DS18B20电路如图如下
![](http://www.myexception.cn/img/2015/05/25/1214141732.jpg)
驱动代码如下
DS18B20_driver.c
Makefile
应用程序如下
在这里用的是misc杂项设备的,#make之后,会生成DS18B20_driver.ko,然后#insmod DS18B20_driver.ko加载模块,执行#cat /proc/devices 发现并没有DS18B20这个驱动模块啊,而多了一个主设备号为10的misc,同时,#ls /dev 会发现自动生成了DS18B20设备文件,为什么呢?因为misc杂项设备驱动共用一个主设备号,区分不同设备的依据是次设备号,这里共用的是主设备号是10,次设备号是系统自动分配的。当#insmod后,系统会自动在/dev目录下创建设备文件,不需要手动mknod创建。
超低功耗静态功耗<3uA,测温范围 -55℃~+125℃,
测量结果以9~12位数字量方式串行传送。
面对着扁平的那一面,左负右正,一旦接反就会立刻发热,有可能烧毁!同时,接反也是导致该传感器总是显示85℃的原因。
DS18B20实物图
![](http://www.myexception.cn/img/2015/05/25/1214141731.jpg)
DS18B20电路如图如下
![](http://www.myexception.cn/img/2015/05/25/1214141732.jpg)
驱动代码如下
DS18B20_driver.c
#include <linux/kernel.h> #include <linux/module.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/delay.h> #include <asm/uaccess.h> //其中copy_to*在其中 #include <mach/gpio.h> #include <mach/regs-gpio.h> #include <plat/gpio-cfg.h> /*基于友善之臂smart210开发板,DS18B20数据引脚GPH2(0),位于开发板左上角GPIO,第二排排针倒数第五引脚*/ spinlock_t lock; //不用也行 unsigned int tmp_wendu ; #define DEVICE_NAME "DS18B20" #define NODE_NAME "DS18B20" //******************************** //功能:设置引脚为输入功能 //******************************** void set_con_in(void) { s3c_gpio_cfgpin(S5PV210_GPH2(0), S3C_GPIO_INPUT); //gpio_set_value(S5PV210_GPH2(0), 1); } //******************************** //功能:设置引脚为输出功能 //******************************** void set_con_out(void) { s3c_gpio_cfgpin(S5PV210_GPH2(0), S3C_GPIO_OUTPUT); } //******************************** //功能:引脚输出高或低电平功能,i=1(高) //******************************** void set_output_data(int i) { if (i == 0) { gpio_set_value(S5PV210_GPH2(0), 0); } else if(i == 1) { gpio_set_value(S5PV210_GPH2(0), 1); } } //******************************** //功能:ds18b20复位 //******************************** int init_DS18B20(void) { int result = 10; set_con_out(); __udelay(3); //短时间延迟 set_output_data(1); __udelay(3); //短时间延迟 set_output_data(0); __udelay(550); //480-960us set_output_data(1); __udelay(20); //15-60us,最好大于15us set_con_in(); __udelay(100); //60-240us, ds18b20回应值保持时间 result = gpio_get_value(S5PV210_GPH2(0)); printk("init_DS18B20--result:%d\n", result); set_con_out(); __udelay(3); set_output_data(1); //__udelay(300); return result; } //************************************* //功能:从ds18b20读一个字节的数据 //************************************* unsigned char read_one_char(void) { unsigned char i = 0; unsigned char dat = 0; unsigned char temp = 0; spin_lock(&lock); for(i=0; i<8; i++) { set_con_out(); __udelay(3); set_output_data(1); dat >>= 1; set_output_data(0); //该行与下行等效该行上面的4行 __udelay(18); //按时序来延时,不能太小或太大 set_con_in(); __udelay(1); temp = gpio_get_value(S5PV210_GPH2(0)) & 0x01; if (temp) dat |= 0x80; else dat |= 0x00; printk("read_one_char--temp: %d\n", temp); __udelay(65); } spin_unlock(&lock); printk("read_one_char--dat: %d\n", dat); return dat; } //************************************* //功能:向ds18b20写一个字节的数据 //************************************* void write_one_char(unsigned char dat) { //printk("write_one_char--dat: %d\n", dat); unsigned char i = 0; spin_lock(&lock); set_con_out(); for(i=0; i<8; i++) { set_output_data(1); __udelay(1); set_output_data(0); __udelay(5); set_output_data(dat & 0x01); __udelay(55); set_output_data(1); __udelay(2); dat >>= 1; } spin_unlock(&lock); __udelay(30); } //******************************** //功能:读取ds18b20的温度 //******************************** unsigned int read_wendu(void) { unsigned char dat_L = 0, dat_H = 0; unsigned int wendu_value; int ds18b20_back_value; ds18b20_back_value = init_DS18B20(); if (ds18b20_back_value) printk("ds18b20 init error!!!\n"); else printk("ds18b20_back_value %d\n", ds18b20_back_value); write_one_char(0xCC); write_one_char(0x44); if (init_DS18B20()) printk("ds18b20 init error!!!\n"); else printk("ds18b20 init ok \n"); write_one_char(0xcc); write_one_char(0xBE); dat_L = read_one_char(); dat_H = read_one_char(); if((dat_H & 0xf8) != 0x00) { dat_L = (~dat_L) + 1; if (dat_L > 255) dat_H = (~dat_H) + 1; } wendu_value = (dat_H * 16 + dat_L/16) * 10 +((dat_L%16)*10/16); printk("read_wendu--dat_L: %d dat_H: %d wendu: %d.%d\n",dat_L, dat_H, \ wendu_value/10, wendu_value%10); return(wendu_value); } static int ds18b20_open(struct inode *inode, struct file *filp) { printk (KERN_INFO "Device opened\n"); spin_lock_init(&lock); return 0; } /*读取数据*/ static int ds18b20_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { unsigned int wendu_value = 0; int res = 0; wendu_value = read_wendu(); if (wendu_value>2000) { wendu_value = tmp_wendu; } tmp_wendu = wendu_value; printk("wendu_valu is %d\n", wendu_value); res=copy_to_user(buffer, &wendu_value, sizeof(wendu_value)); if (res < 0) { printk("copy_to_user error! "); } printk("copy_to_user len! %d\n ", res); return 0; } /*写命令,在此置空*/ static int ds18b20_write(struct file *file, const char *buffer, size_t count, loff_t * ppos) { return 0; } static int ds18b20_release(struct inode *inode,struct file *filp) { printk (KERN_INFO "device closed\n"); return 0; } static long ds18b20_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { return 0; } static struct file_operations ds18b20_fops = { .owner = THIS_MODULE, .open = ds18b20_open, .read = ds18b20_read, .write = ds18b20_write, .unlocked_ioctl = ds18b20_ioctl, .release = ds18b20_release, }; static struct miscdevice ds18b20_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .nodename = NODE_NAME, .fops = &ds18b20_fops, }; static int __init ds18b20_dev_init(void) { int ret; ret = gpio_request(S5PV210_GPH2(0), "DS18B20"); if (ret) { printk("%s: request GPIO %d for GPE0 failed, ret = %d\n", DEVICE_NAME, S5PV210_GPH2(0), ret); return ret; s3c_gpio_cfgpin(S5PV210_GPH2(0), S3C_GPIO_OUTPUT); gpio_set_value(S5PV210_GPH2(0), 1); } ret = misc_register(&ds18b20_dev);//注册杂设备驱动 printk(DEVICE_NAME"\tinitialized\n"); return ret; } static void __exit ds18b20_dev_exit(void) { int i; for (i = 0; i < 1; i++) { gpio_free(S5PV210_GPH2(0)); } misc_deregister(&ds18b20_dev); } module_init(ds18b20_dev_init); module_exit(ds18b20_dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GaoZhe.");
Makefile
ifneq ($(KERNELRELEASE),) obj-m := DS18B20_driver.o else PWD := $(shell pwd) KDIR:= /home/bishe/kernel/linux-3.0.8 all: make -C $(KDIR) M=$(PWD) clean: rm -rf *.o *.order *.ko *.mod.c *.symvers *.c~ *~ endif
应用程序如下
#include <fcntl.h> #include <stdio.h> #include <string.h> #include <sys/select.h> int main(int argc, char *argv[]) { int fd, i; char *buf; unsigned int a=0; fd = open("/dev/DS18B20", O_RDWR); if(-1 == fd) { perror("open file error\r\n"); exit(-1); } printf("open /dev/DS18B20 success!\n"); while(1) { int i=read(fd,&a,5); if(i<0) { printf("read tempture is error!\n"); } printf("test_temptureis:%d.%d\n",a/10,a%10); sleep(1); } close(fd); return 0; }
在这里用的是misc杂项设备的,#make之后,会生成DS18B20_driver.ko,然后#insmod DS18B20_driver.ko加载模块,执行#cat /proc/devices 发现并没有DS18B20这个驱动模块啊,而多了一个主设备号为10的misc,同时,#ls /dev 会发现自动生成了DS18B20设备文件,为什么呢?因为misc杂项设备驱动共用一个主设备号,区分不同设备的依据是次设备号,这里共用的是主设备号是10,次设备号是系统自动分配的。当#insmod后,系统会自动在/dev目录下创建设备文件,不需要手动mknod创建。
相关文章推荐
- Linux C下的线程操作函数笔记及实例代码
- 在Linux下安装Django
- linux配置web服务器常用命令
- centOS6.5中安装KVM
- 操作系统知识(4)--Linux 用户和用户组管理
- 命令行快捷方式
- linux 下权限问题
- Linux的find命令实例详解和mtime ctime atime
- linux五个查找命令
- 如何将在Linux下导出的db2数据库还原到windows下
- Windows平台SSH登录Linux并使用图形化界面
- linux中ssh使用rsa免密码登录和下载文件的方法
- Linux ./configure --prefix 命令是什么意思?
- Linux 标准 输入 输出 重定向. printf 不输出到屏幕的解决办法
- centos6.5 64bit 实现root开机自动登录X桌面
- 安装win10和archlinux双系统
- Linux获取/dev/input目录下的event对应的设备
- 《Linux驱动》iTop4412开发板LCD驱动 详细分析 (二)
- 《Linux驱动》iTop4412开发板LCD驱动 详细分析 (一)
- Linux 中如何使用 gThumb 批量调整图片大小