mini2440 驱动ds18b20
来源:互联网 发布:php去除重复数组值 编辑:程序博客网 时间:2024/05/22 18:20
http://blog.csdn.net/xgg0602/article/details/7058071
今天下午闲着蛋疼,看鸟哥实在看不进去,想着有个ds18b20,于是就写了一个18b20的驱动。是在mini2440上面实现的。
ldd3的大师说得好,linux驱动应该尽可能多的提供机制,而不是提供策略。我觉得说得太有道理了。驱动本身就不应该涉及到太多策略问题,策略问题应该尽可能多的由应用程序去提供。作为驱动,应该尽可能多得去实现提供硬件的功能,然后留出接口给上面的应用程序调用。
其实ds18b20驱动比较简单,无非就是在单片机驱动18b20的基础上,家里一个字符驱动设备的外套。下面直接上代码吧。
驱动代码:
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/delay.h>
- #include <linux/kernel.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <linux/cdev.h>
- #include <asm/uaccess.h>
- #include <linux/errno.h>
- #include <linux/gpio.h>
- #include <linux/device.h> //自动创建设备需要此头文件
- #define DQ S3C2410_GPF(3) //mini2440里面是这样定义GPIO的
- #define DQ_IN S3C2410_GPIO_INPUT //设置DQ为输入
- #define DQ_OUT S3C2410_GPIO_OUTPUT //设置DQ为输入
- #define D_MAJOR 0 //定义主设备号
- #define D_MINOR 0 //定义从设备号
- #define DEV_NAME "ds18b20" //定义设备名
- static int ds18b20_major = D_MAJOR;//ds18b20主设备号
- static int ds18b20_minor = D_MINOR;//ds18b20从设备号
- static struct class *my_class; //定义class,用于自动挂载设备
- static struct class_device *my_device; //自动挂载设备
- static struct ds18b20_dev{ //放在一个结构体中
- struct cdev cdev; //这个结构体比较简单,但是建议以后将用户的东西都放在一个结构体中
- };
- struct ds18b20_dev *ds18b20_devp;
- void ds18b20_reset(void) //重启ds18b20
- {
- s3c2410_gpio_cfgpin(DQ, DQ_OUT); //设置为输出
- s3c2410_gpio_pullup(DQ, 0); //设置下拉
- s3c2410_gpio_setpin(DQ, 0); //拉低总线
- udelay(500); //需要将总线拉低480~950us
- s3c2410_gpio_setpin(DQ, 1); //释放总线
- udelay(60); //DS18B20拉低信号,60~240us表示应答
- s3c2410_gpio_cfgpin(DQ, DQ_IN); //读入DS18B20拉低信号
- while(s3c2410_gpio_getpin(DQ)); //等待DS18B20应答
- while(!s3c2410_gpio_getpin(DQ)); //等待DS18B20释放总线
- }
- void write_ds18b20(unsigned char Data) //写命令到ds18b20
- {
- unsigned char i;
- s3c2410_gpio_cfgpin(DQ, DQ_OUT); //设置为输出
- s3c2410_gpio_pullup(DQ, 1); //上拉
- for(i=0;i<8;i++){
- s3c2410_gpio_setpin(DQ, 0); //拉低总线
- udelay(10); //需要拉低10~15us
- if(Data&0x01)
- s3c2410_gpio_setpin(DQ, 1);
- else
- s3c2410_gpio_setpin(DQ, 0);
- udelay(40); //需要拉低20~40us来写0
- s3c2410_gpio_setpin(DQ, 1); //释放总线
- udelay(1); //稍微延时
- Data >>= 1;
- }
- }
- static unsigned char read_ds18b20(void) //读ds18b20
- {
- unsigned char Temp=0,i;
- for(i=0;i<8;i++){
- Temp >>= 1;
- s3c2410_gpio_cfgpin(DQ, DQ_OUT); //DQ为输出状态
- s3c2410_gpio_setpin(DQ, 0); //拉低总线,启动输入
- udelay(1); //拉低总线约1us
- s3c2410_gpio_setpin(DQ, 1); //释放总线
- s3c2410_gpio_cfgpin(DQ, DQ_IN); //DQ为输入状态
- if(s3c2410_gpio_getpin(DQ))
- Temp |= 0x80;
- udelay(45); //延时45us
- }
- return Temp;
- }
- static int ds18b20_open(struct inode *inode,struct file *filp)
- {
- filp->private_data = ds18b20_devp;
- ds18b20_reset();
- printk(KERN_NOTICE "open ds18b20 successful\n");
- return 0;
- }
- static ssize_t ds18b20_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
- {
- unsigned long err;
- struct ds18b20_dev *dev = filp->private_data;
- unsigned char result[2] = {0x00, 0x00}; //这个是用来存放从ds18b20读到的值
- ds18b20_reset(); //reset ds18b20
- write_ds18b20(0xCC); //跳过ROM
- write_ds18b20(0x44); //温度转换
- ds18b20_reset(); //reset ds18b20
- write_ds18b20(0xCC); //跳过ROM
- write_ds18b20(0xbe); //读取RAM
- result[0] = read_ds18b20(); //读低8位,存放在result[0]
- result[1] = read_ds18b20(); //读高8位,存放在result[1]
- ds18b20_reset();
- err = copy_to_user(buf, &result, sizeof(result));
- return err ? -EFAULT : min(sizeof(result), size);
- }
- static int ds18b20_release(struct inode *inode,struct file *filp)
- {
- return 0;
- }
- static const struct file_operations ds18b20_fops={
- .owner=THIS_MODULE,
- .read=ds18b20_read,
- .open=ds18b20_open,
- .release=ds18b20_release,
- };
- void ds18b20_setup_dev(struct ds18b20_dev *dev,int minor)
- {
- int err;
- int devno;
- devno = MKDEV(ds18b20_major,minor);
- cdev_init(&dev->cdev,&ds18b20_fops);
- dev->cdev.owner=THIS_MODULE;
- dev->cdev.ops=&ds18b20_fops;
- err=cdev_add(&dev->cdev,devno,1);
- if(err)
- printk(KERN_NOTICE "Error %d adding %d\n",err,minor);
- }
- static int __init ds18b20_init(void)
- {
- int result;
- dev_t devno = 0;
- if(ds18b20_major){
- devno = MKDEV(ds18b20_major,ds18b20_minor);
- result = register_chrdev_region(devno,1,DEV_NAME);
- }
- else{
- result = alloc_chrdev_region(&devno,0,1,DEV_NAME);
- ds18b20_major = MAJOR(devno);
- }
- if(result < 0)
- return result;
- ds18b20_devp = kmalloc(sizeof(struct ds18b20_dev),GFP_KERNEL);
- if(ds18b20_devp){
- result = -ENOMEM;
- goto fail_malloc;
- }
- memset(ds18b20_devp,0,sizeof(struct ds18b20_dev));
- ds18b20_setup_dev(ds18b20_devp,0);
- my_class = class_create(THIS_MODULE,"ds18b20_class");
- /*在linux 2.6.27之前是:class_device_create*/
- my_device = device_create(my_class,NULL,MKDEV(ds18b20_major, ds18b20_minor),NULL,"ds18b20");
- return 0;
- fail_malloc:
- unregister_chrdev_region(devno,1);
- return result;
- }
- static void __exit ds18b20_exit(void)
- {
- cdev_del(&ds18b20_devp->cdev);
- kfree(ds18b20_devp);
- device_destroy(my_class, MKDEV(ds18b20_major, ds18b20_minor));//删除设备文件 /dev/ds18b20
- class_destroy(my_class); //删除创建的bus
- unregister_chrdev_region(MKDEV(ds18b20_major,ds18b20_minor),1);
- }
- module_init(ds18b20_init);
- module_exit(ds18b20_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("WIOT");
#include <linux/init.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/kernel.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/types.h>#include <linux/fs.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include <linux/errno.h>#include <linux/gpio.h>#include <linux/device.h> //自动创建设备需要此头文件#define DQ S3C2410_GPF(3) //mini2440里面是这样定义GPIO的#define DQ_IN S3C2410_GPIO_INPUT //设置DQ为输入#define DQ_OUT S3C2410_GPIO_OUTPUT //设置DQ为输入#define D_MAJOR 0 //定义主设备号#define D_MINOR 0 //定义从设备号#define DEV_NAME "ds18b20" //定义设备名static int ds18b20_major = D_MAJOR;//ds18b20主设备号static int ds18b20_minor = D_MINOR;//ds18b20从设备号static struct class *my_class; //定义class,用于自动挂载设备static struct class_device *my_device; //自动挂载设备static struct ds18b20_dev{ //放在一个结构体中 struct cdev cdev; //这个结构体比较简单,但是建议以后将用户的东西都放在一个结构体中};struct ds18b20_dev *ds18b20_devp;void ds18b20_reset(void) //重启ds18b20{s3c2410_gpio_cfgpin(DQ, DQ_OUT); //设置为输出s3c2410_gpio_pullup(DQ, 0); //设置下拉s3c2410_gpio_setpin(DQ, 0); //拉低总线udelay(500); //需要将总线拉低480~950uss3c2410_gpio_setpin(DQ, 1); //释放总线udelay(60); //DS18B20拉低信号,60~240us表示应答s3c2410_gpio_cfgpin(DQ, DQ_IN); //读入DS18B20拉低信号while(s3c2410_gpio_getpin(DQ)); //等待DS18B20应答 while(!s3c2410_gpio_getpin(DQ)); //等待DS18B20释放总线}void write_ds18b20(unsigned char Data) //写命令到ds18b20{unsigned char i;s3c2410_gpio_cfgpin(DQ, DQ_OUT); //设置为输出s3c2410_gpio_pullup(DQ, 1); //上拉 for(i=0;i<8;i++){ s3c2410_gpio_setpin(DQ, 0); //拉低总线 udelay(10); //需要拉低10~15us if(Data&0x01) s3c2410_gpio_setpin(DQ, 1); else s3c2410_gpio_setpin(DQ, 0); udelay(40); //需要拉低20~40us来写0 s3c2410_gpio_setpin(DQ, 1); //释放总线 udelay(1); //稍微延时 Data >>= 1; }}static unsigned char read_ds18b20(void) //读ds18b20{unsigned char Temp=0,i;for(i=0;i<8;i++){ Temp >>= 1; s3c2410_gpio_cfgpin(DQ, DQ_OUT); //DQ为输出状态 s3c2410_gpio_setpin(DQ, 0); //拉低总线,启动输入 udelay(1); //拉低总线约1us s3c2410_gpio_setpin(DQ, 1); //释放总线 s3c2410_gpio_cfgpin(DQ, DQ_IN); //DQ为输入状态 if(s3c2410_gpio_getpin(DQ)) Temp |= 0x80; udelay(45); //延时45us } return Temp;}static int ds18b20_open(struct inode *inode,struct file *filp){filp->private_data = ds18b20_devp;ds18b20_reset();printk(KERN_NOTICE "open ds18b20 successful\n");return 0;}static ssize_t ds18b20_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos){unsigned long err;struct ds18b20_dev *dev = filp->private_data;unsigned char result[2] = {0x00, 0x00}; //这个是用来存放从ds18b20读到的值ds18b20_reset(); //reset ds18b20write_ds18b20(0xCC); //跳过ROMwrite_ds18b20(0x44); //温度转换ds18b20_reset(); //reset ds18b20write_ds18b20(0xCC); //跳过ROM write_ds18b20(0xbe); //读取RAMresult[0] = read_ds18b20(); //读低8位,存放在result[0]result[1] = read_ds18b20(); //读高8位,存放在result[1]ds18b20_reset();err = copy_to_user(buf, &result, sizeof(result)); return err ? -EFAULT : min(sizeof(result), size);}static int ds18b20_release(struct inode *inode,struct file *filp){return 0;}static const struct file_operations ds18b20_fops={.owner=THIS_MODULE,.read=ds18b20_read,.open=ds18b20_open,.release=ds18b20_release,};void ds18b20_setup_dev(struct ds18b20_dev *dev,int minor){int err;int devno;devno = MKDEV(ds18b20_major,minor);cdev_init(&dev->cdev,&ds18b20_fops);dev->cdev.owner=THIS_MODULE;dev->cdev.ops=&ds18b20_fops;err=cdev_add(&dev->cdev,devno,1);if(err)printk(KERN_NOTICE "Error %d adding %d\n",err,minor);}static int __init ds18b20_init(void){int result;dev_t devno = 0;if(ds18b20_major){devno = MKDEV(ds18b20_major,ds18b20_minor);result = register_chrdev_region(devno,1,DEV_NAME);}else{result = alloc_chrdev_region(&devno,0,1,DEV_NAME);ds18b20_major = MAJOR(devno);}if(result < 0)return result;ds18b20_devp = kmalloc(sizeof(struct ds18b20_dev),GFP_KERNEL);if(ds18b20_devp){result = -ENOMEM;goto fail_malloc;}memset(ds18b20_devp,0,sizeof(struct ds18b20_dev));ds18b20_setup_dev(ds18b20_devp,0);my_class = class_create(THIS_MODULE,"ds18b20_class");/*在linux 2.6.27之前是:class_device_create*/ my_device = device_create(my_class,NULL,MKDEV(ds18b20_major, ds18b20_minor),NULL,"ds18b20");return 0;fail_malloc:unregister_chrdev_region(devno,1);return result;}static void __exit ds18b20_exit(void){cdev_del(&ds18b20_devp->cdev);kfree(ds18b20_devp);device_destroy(my_class, MKDEV(ds18b20_major, ds18b20_minor));//删除设备文件 /dev/ds18b20 class_destroy(my_class); //删除创建的busunregister_chrdev_region(MKDEV(ds18b20_major,ds18b20_minor),1);}module_init(ds18b20_init);module_exit(ds18b20_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("WIOT");
应用程序代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <linux/ioctl.h>
- void ds18b20_delay(int i)
- {
- int j, k;
- for (j = 0; j < i; j++)
- for(k = 0; k < 50000; k++);
- }
- int main(int argc,char **argv)
- {
- int fd, i;
- unsigned char result[2];
- unsigned int Temp;
- unsigned char Temperature[7]; //显示温度用的buffer
- fd = open("/dev/ds18b20",0);
- if(fd < 0){
- perror("open device failed!\n");
- exit(1);
- }
- while(1){
- read(fd,&result,sizeof(result));
- Temp = ((result[1]<<8)|result[0])*6.25; //这个是为了让温度后面有两位小数
- Temperature[0] = Temp/1000+48;
- Temperature[1] = Temp%1000/100+48;
- Temperature[2] = '.';
- Temperature[3] = Temp%100/10+48;
- Temperature[4] = Temp%10+48;
- Temperature[5] = ' ';
- Temperature[6] = 'C';
- printf("The temperature is:%s\n",Temperature);
- ds18b20_delay(1000);
- }
- return 0;
- }
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <linux/ioctl.h>void ds18b20_delay(int i){ int j, k; for (j = 0; j < i; j++) for(k = 0; k < 50000; k++);}int main(int argc,char **argv){int fd, i;unsigned char result[2];unsigned int Temp;unsigned char Temperature[7]; //显示温度用的bufferfd = open("/dev/ds18b20",0); if(fd < 0){perror("open device failed!\n");exit(1);}while(1){read(fd,&result,sizeof(result));Temp = ((result[1]<<8)|result[0])*6.25; //这个是为了让温度后面有两位小数Temperature[0] = Temp/1000+48; Temperature[1] = Temp%1000/100+48;Temperature[2] = '.';Temperature[3] = Temp%100/10+48;Temperature[4] = Temp%10+48;Temperature[5] = ' ';Temperature[6] = 'C';printf("The temperature is:%s\n",Temperature);ds18b20_delay(1000);}return 0;}
- 驱动放弃了好长时间了啊,要捡起来,并且深入。以后还是要坚定自己的选择。既然对这个感兴趣,就要经常的去折腾。
驱动放弃了好长时间了啊,要捡起来,并且深入。以后还是要坚定自己的选择。既然对这个感兴趣,就要经常的去折腾。
- 年轻,就是应该多折腾一下,多做自己感兴趣的事情。
- mini2440 驱动ds18b20
- mini2440 驱动ds18b20
- mini2440的ds18b20驱动和测试程序
- mini2440的ds18b20驱动和测试程序
- DS18B20驱动
- DS18B20 驱动
- DS18B20驱动
- DS18B20驱动
- 简单、规范的Linux下的ds18b20驱动(基于mini2440开发板,2.6.29内核)
- DS18B20的驱动过程
- 单片机驱动DS18B20
- ds18b20 驱动测试程序
- OK6410 Linux DS18B20驱动
- 关于STC89C52驱动DS18B20
- linux ds18b20 温度传感器驱动
- 驱动——DS18B20
- OK6410的ds18b20驱动
- STM32驱动DS18B20
- LeetCode OJ | Two Sum(java版)
- 把自己做的程序放在Tomcat里面的3种方法
- FPGA设计略讲
- Android核心分析 之二方法论探讨之概念空间篇
- Knockout.js随手记(2)
- mini2440 驱动ds18b20
- Web Service
- opencv 宏
- 在StringGrid中每行添加一个选择框(checkbox)
- 谷歌技术"三宝"之BigTable
- 【android开发】手机应用管理器的实现之获取应用列表(一)
- 机器学习入门
- Uninstall Trillian with WindowsUninstaller.Org Removal Tips
- 搜狗曝重大安全漏洞 大量用户隐私被泄露