打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
基于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实物图

DS18B20电路如图如下

驱动代码如下

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.oelsePWD := $(shell pwd)KDIR:= /home/bishe/kernel/linux-3.0.8all:    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创建。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
字符设备驱动之LED-平台设备驱动(platform设备驱动)
手把手带你写一个中断输入设备驱动
linux下使用mmap控制GPIO
led灯驱动测试
Linux 2.6.37内核移植到Mini2440(四)
使用input输入子系统实现对tiny6410LED灯的控制
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服