mini2440 驱动ds18b20

http://blog.csdn.net/xgg0602/article/details/7058071

今天下午闲着蛋疼,看鸟哥实在看不进去,想着有个ds18b20,于是就写了一个18b20的驱动。是在mini2440上面实现的。

         ldd3的大师说得好,linux驱动应该尽可能多的提供机制,而不是提供策略。我觉得说得太有道理了。驱动本身就不应该涉及到太多策略问题,策略问题应该尽可能多的由应用程序去提供。作为驱动,应该尽可能多得去实现提供硬件的功能,然后留出接口给上面的应用程序调用。

         其实ds18b20驱动比较简单,无非就是在单片机驱动18b20的基础上,家里一个字符驱动设备的外套。下面直接上代码吧。

         

         驱动代码:

  1. #include <linux/init.h>   
  2. #include <linux/module.h>   
  3. #include <linux/delay.h>   
  4. #include <linux/kernel.h>   
  5. #include <linux/moduleparam.h>   
  6. #include <linux/init.h>   
  7. #include <linux/types.h>   
  8. #include <linux/fs.h>   
  9. #include <mach/regs-gpio.h>   
  10. #include <mach/hardware.h>   
  11. #include <linux/cdev.h>   
  12. #include <asm/uaccess.h>   
  13. #include <linux/errno.h>   
  14. #include <linux/gpio.h>   
  15. #include <linux/device.h> //自动创建设备需要此头文件   
  16.   
  17. #define DQ     S3C2410_GPF(3)      //mini2440里面是这样定义GPIO的   
  18. #define DQ_IN  S3C2410_GPIO_INPUT  //设置DQ为输入   
  19. #define DQ_OUT S3C2410_GPIO_OUTPUT //设置DQ为输入   
  20.   
  21. #define D_MAJOR 0                  //定义主设备号   
  22. #define D_MINOR 0                  //定义从设备号   
  23. #define DEV_NAME "ds18b20"         //定义设备名   
  24.   
  25. static int ds18b20_major = D_MAJOR;//ds18b20主设备号   
  26. static int ds18b20_minor = D_MINOR;//ds18b20从设备号   
  27. static struct class *my_class;     //定义class,用于自动挂载设备   
  28. static struct class_device *my_device; //自动挂载设备   
  29.   
  30. static struct ds18b20_dev{           //放在一个结构体中            
  31.     struct cdev cdev;                //这个结构体比较简单,但是建议以后将用户的东西都放在一个结构体中   
  32. };  
  33.   
  34. struct ds18b20_dev *ds18b20_devp;  
  35.   
  36. void ds18b20_reset(void)             //重启ds18b20   
  37. {  
  38.     s3c2410_gpio_cfgpin(DQ, DQ_OUT); //设置为输出   
  39.     s3c2410_gpio_pullup(DQ, 0);      //设置下拉   
  40.     s3c2410_gpio_setpin(DQ, 0);      //拉低总线   
  41.     udelay(500);                     //需要将总线拉低480~950us   
  42.     s3c2410_gpio_setpin(DQ, 1);      //释放总线   
  43.     udelay(60);                      //DS18B20拉低信号,60~240us表示应答   
  44.     s3c2410_gpio_cfgpin(DQ, DQ_IN);  //读入DS18B20拉低信号   
  45.     while(s3c2410_gpio_getpin(DQ));  //等待DS18B20应答   
  46.     while(!s3c2410_gpio_getpin(DQ)); //等待DS18B20释放总线       
  47. }  
  48.   
  49. void write_ds18b20(unsigned char Data)           //写命令到ds18b20   
  50. {     
  51.     unsigned char i;  
  52.     s3c2410_gpio_cfgpin(DQ, DQ_OUT);              //设置为输出   
  53.     s3c2410_gpio_pullup(DQ, 1);                   //上拉       
  54.     for(i=0;i<8;i++){  
  55.         s3c2410_gpio_setpin(DQ, 0);              //拉低总线   
  56.         udelay(10);                              //需要拉低10~15us   
  57.    
  58.         if(Data&0x01)  
  59.             s3c2410_gpio_setpin(DQ, 1);  
  60.         else  
  61.             s3c2410_gpio_setpin(DQ, 0);  
  62.         udelay(40);                             //需要拉低20~40us来写0   
  63.         s3c2410_gpio_setpin(DQ, 1);            //释放总线   
  64.         udelay(1);                            //稍微延时   
  65.         Data >>= 1;          
  66.     }  
  67. }  
  68.   
  69. static unsigned char read_ds18b20(void)    //读ds18b20   
  70. {  
  71.     unsigned char Temp=0,i;  
  72.     for(i=0;i<8;i++){  
  73.         Temp >>= 1;  
  74.         s3c2410_gpio_cfgpin(DQ, DQ_OUT);  //DQ为输出状态   
  75.         s3c2410_gpio_setpin(DQ, 0);       //拉低总线,启动输入   
  76.         udelay(1);                        //拉低总线约1us   
  77.         s3c2410_gpio_setpin(DQ, 1);       //释放总线   
  78.         s3c2410_gpio_cfgpin(DQ, DQ_IN);   //DQ为输入状态   
  79.         if(s3c2410_gpio_getpin(DQ))  
  80.           Temp |= 0x80;  
  81.         udelay(45);      //延时45us   
  82.     }  
  83.     return Temp;  
  84. }  
  85.   
  86. static int ds18b20_open(struct inode *inode,struct file *filp)  
  87. {  
  88.     filp->private_data = ds18b20_devp;  
  89.     ds18b20_reset();  
  90.     printk(KERN_NOTICE "open ds18b20 successful\n");  
  91.     return 0;  
  92. }  
  93.   
  94. static ssize_t ds18b20_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)  
  95. {  
  96.     unsigned long err;  
  97.     struct ds18b20_dev *dev = filp->private_data;  
  98.     unsigned char result[2] = {0x00, 0x00};       //这个是用来存放从ds18b20读到的值   
  99.     ds18b20_reset();                              //reset ds18b20   
  100.     write_ds18b20(0xCC);                          //跳过ROM   
  101.     write_ds18b20(0x44);                          //温度转换   
  102.     ds18b20_reset();                              //reset ds18b20   
  103.     write_ds18b20(0xCC);                          //跳过ROM   
  104.        write_ds18b20(0xbe);                          //读取RAM   
  105.     result[0] = read_ds18b20();                   //读低8位,存放在result[0]   
  106.     result[1] = read_ds18b20();                   //读高8位,存放在result[1]   
  107.     ds18b20_reset();  
  108.     err = copy_to_user(buf, &result, sizeof(result));  
  109.     return err ? -EFAULT : min(sizeof(result), size);  
  110. }  
  111.   
  112. static int ds18b20_release(struct inode *inode,struct file *filp)  
  113.   
  114. {  
  115.     return 0;  
  116. }  
  117.   
  118. static const struct file_operations ds18b20_fops={  
  119.     .owner=THIS_MODULE,   
  120.     .read=ds18b20_read,  
  121.     .open=ds18b20_open,  
  122.     .release=ds18b20_release,  
  123.   
  124. };  
  125. void ds18b20_setup_dev(struct ds18b20_dev *dev,int minor)  
  126. {  
  127.     int err;  
  128.     int devno;  
  129.     devno = MKDEV(ds18b20_major,minor);  
  130.     cdev_init(&dev->cdev,&ds18b20_fops);  
  131.     dev->cdev.owner=THIS_MODULE;  
  132.     dev->cdev.ops=&ds18b20_fops;  
  133.     err=cdev_add(&dev->cdev,devno,1);  
  134.     if(err)  
  135.         printk(KERN_NOTICE "Error %d adding %d\n",err,minor);  
  136. }  
  137.   
  138. static int  __init ds18b20_init(void)  
  139. {  
  140.     int result;  
  141.     dev_t devno = 0;  
  142.       
  143.     if(ds18b20_major){  
  144.         devno = MKDEV(ds18b20_major,ds18b20_minor);  
  145.         result = register_chrdev_region(devno,1,DEV_NAME);  
  146.     }  
  147.     else{  
  148.         result = alloc_chrdev_region(&devno,0,1,DEV_NAME);  
  149.         ds18b20_major = MAJOR(devno);  
  150.     }  
  151.     if(result < 0)  
  152.         return result;  
  153.     ds18b20_devp = kmalloc(sizeof(struct ds18b20_dev),GFP_KERNEL);  
  154.     if(ds18b20_devp){  
  155.         result = -ENOMEM;  
  156.         goto fail_malloc;  
  157.     }  
  158.     memset(ds18b20_devp,0,sizeof(struct ds18b20_dev));  
  159.     ds18b20_setup_dev(ds18b20_devp,0);  
  160.     my_class = class_create(THIS_MODULE,"ds18b20_class");  
  161.     /*在linux 2.6.27之前是:class_device_create*/  
  162.     my_device = device_create(my_class,NULL,MKDEV(ds18b20_major, ds18b20_minor),NULL,"ds18b20");  
  163.     return 0;  
  164.     fail_malloc:  
  165.         unregister_chrdev_region(devno,1);  
  166.         return result;  
  167. }  
  168.   
  169. static void __exit ds18b20_exit(void)  
  170. {  
  171.     cdev_del(&ds18b20_devp->cdev);  
  172.     kfree(ds18b20_devp);  
  173.     device_destroy(my_class, MKDEV(ds18b20_major, ds18b20_minor));//删除设备文件 /dev/ds18b20    
  174.     class_destroy(my_class);   //删除创建的bus   
  175.     unregister_chrdev_region(MKDEV(ds18b20_major,ds18b20_minor),1);  
  176. }  
  177.   
  178. module_init(ds18b20_init);  
  179. module_exit(ds18b20_exit);  
  180.   
  181. MODULE_LICENSE("GPL");  
  182. MODULE_AUTHOR("WIOT");  
  183.    
#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");
 

应用程序代码:

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <unistd.h>   
  4. #include <linux/ioctl.h>   
  5.   
  6. void ds18b20_delay(int i)  
  7. {  
  8.     int j, k;  
  9.     for (j = 0; j < i; j++)  
  10.         for(k = 0; k < 50000; k++);  
  11. }  
  12.   
  13.   
  14.   
  15. int main(int argc,char **argv)  
  16. {  
  17.     int fd, i;  
  18.     unsigned char result[2];  
  19.     unsigned int Temp;  
  20.     unsigned char Temperature[7];         //显示温度用的buffer   
  21.     fd = open("/dev/ds18b20",0);       
  22.     if(fd < 0){  
  23.         perror("open device failed!\n");  
  24.         exit(1);  
  25.     }  
  26.     while(1){  
  27.         read(fd,&result,sizeof(result));  
  28.         Temp = ((result[1]<<8)|result[0])*6.25; //这个是为了让温度后面有两位小数   
  29.         Temperature[0] = Temp/1000+48;      
  30.         Temperature[1] = Temp%1000/100+48;  
  31.         Temperature[2] = '.';  
  32.         Temperature[3] = Temp%100/10+48;  
  33.         Temperature[4] = Temp%10+48;  
  34.         Temperature[5] = ' ';  
  35.         Temperature[6] = 'C';  
  36.         printf("The temperature is:%s\n",Temperature);  
  37.         ds18b20_delay(1000);  
  38.     }  
  39.     return 0;  
  40. }    
#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;
}  
  1. 驱动放弃了好长时间了啊,要捡起来,并且深入。以后还是要坚定自己的选择。既然对这个感兴趣,就要经常的去折腾。  
     驱动放弃了好长时间了啊,要捡起来,并且深入。以后还是要坚定自己的选择。既然对这个感兴趣,就要经常的去折腾。
  1. 年轻,就是应该多折腾一下,多做自己感兴趣的事情。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值