初级会员
- 积分
- 76
- 金钱
- 76
- 注册时间
- 2019-5-26
- 在线时间
- 27 小时
|
楼主 |
发表于 2020-3-11 11:36:01
|
显示全部楼层
以下是驱动源码
使用的DATA线接的是GPIO1的4引脚,也就是Linux开发板的GPIO4
关于设备树的配置,按我上面的就可以了
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/gpio.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/of_gpio.h>
- #include <asm/mach/map.h>
- #include <asm/uaccess.h>
- #include <linux/semaphore.h>
- #include <asm/io.h>
- #define DHT11_CNT 1 /* 设备号个数 */
- #define DHT11_NAME "dht11" /* 名字 */
- /* dht11设备结构体 */
- struct dht11_dev{
- dev_t devid; /* 设备号 */
- struct cdev cdev; /* cdev */
- struct class *class; /* 类 */
- struct device *device; /* 设备 */
- int major; /* 主设备号 */
- int minor; /* 次设备号 */
- struct device_node *nd; /* 设备节点 */
- int dht11_gpio; /* dht11所使用的GPIO编号 */
-
- //struct mutex dht11_mutex; //定义一个互斥锁的结构体
- };
- struct dht11_dev dht11; /* dht11设备 */
- /*
- * @description : 打开设备
- * @param - inode : 传递给驱动的inode
- * @param - filp : 设备文件,file结构体有个叫做private_data的成员变量
- * 一般在open的时候将private_data指向设备结构体。
- * @return : 0 成功;其他 失败
- */
- static int dht11_open(struct inode *inode, struct file *filp)
- {
- filp->private_data = &dht11; /* 设置私有数据 */
- return 0;
- }
- /*
- *@description :根据原理编写启动信号
- *@description :使用gpio的API函数
- */
- static int Dht11_Start(struct dht11_dev *dev)
- {
- unsigned int t =0,ret =0; //用于计算超时
-
- //先设置为输出,初值先设置为1吧,因为是有上拉电阻
- ret = gpio_direction_output(dev->dht11_gpio, 1);
- if(ret < 0) {
- printk("can't set output!\r\n");
- }
- //启动信号
- gpio_set_value(dev->dht11_gpio, 1); /* 高电平持续5us */
- udelay(5);
- gpio_set_value(dev->dht11_gpio, 0); /* 低电平持续18【ms】 */
- //udelay(20);
- mdelay(20); //应该是拉低18ms以上啊
-
- gpio_set_value(dev->dht11_gpio, 1); /* 高电平持续30us */
- udelay(30);
- //【G9设置为输入】-----接收响应信号
- gpio_direction_input(dev->dht11_gpio);
-
- t =0;
- while(gpio_get_value(dev->dht11_gpio)!= 0)
- {
- udelay(1);
- t++;
-
- if(t>100)
- return -1;
- }
-
-
-
- //过滤低电平
- t = 0;
- while(gpio_get_value(dev->dht11_gpio) == 0)
- {
- udelay(1);
- t++;
- if(t>100)
- return -2;
- }
-
- //过滤高电平
- t = 0;
- while(gpio_get_value(dev->dht11_gpio) == 1)
- {
- udelay(1);
- t++;
- if(t>100)
- return -3;
- }
- //如果都正常,返回0,走人
- //上面其实是在接收模块传回来的反馈信号
- return 0;
- }
- /*
- * @description : 读取一个字节
-
- * @return : 读取到的字节数据
- */
- //返回0为异常
- static unsigned char Dht11_Read_Byte(struct dht11_dev *dev)
- {
- //上锁
- //mutex_lock(&dev->dht11_mutex);
-
-
- unsigned char i, t = 0, data = 0;
-
- for(i=0; i<8; i++)
- {
- //过渡低电平
- //无论是【0】还是【1】,【一开始都是低电平】
- t = 0;
- while(gpio_get_value(dev->dht11_gpio) == 0)
- {
- udelay(1);
- t++;
- if(t>100)
- {
- //mutex_unlock(&dev->dht11_mutex);
- return -EINVAL;
- }
- }
- //高电平出现,退出上面的循环
- //延时45us,再判断电平,就可以知道是1还是0
- udelay(45);
- //延时之后还是高电平,就说明是“1”
- if(gpio_get_value(dev->dht11_gpio) == 1) //表示收到1
- {
- data |= 1<<(7-i);
- //过滤掉剩下的高电平
- t = 0;
- while( gpio_get_value(dev->dht11_gpio) == 1)
- {
- udelay(1);
- t++;
- if(t>100)
- {
- //mutex_unlock(&dev->dht11_mutex);
- return -EINVAL;
- }
- }
- }
- //如果是0,不用处理,本来初值就是0
- }
- //mutex_unlock(&dev->dht11_mutex);
- return data;
- }
- /*
- * @description : 读函数
- * @param - filp : 要关闭的设备文件(文件描述符)
- * @return : 0 成功;其他 失败
- */
- static ssize_t dht11_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
- {
- int ret = 0;
- unsigned char value[5]={0,0,0,0,0};
-
-
- struct dht11_dev *dev = filp->private_data;
- ret = Dht11_Start(dev);
-
- //读取4个值
- gpio_direction_input(dev->dht11_gpio);
- if(ret == 0)
- {
- //printk("<4>""kernel_read\r\n");
- value[0] = Dht11_Read_Byte(dev);
- value[1] = Dht11_Read_Byte(dev);
- value[2] = Dht11_Read_Byte(dev);
- value[3] = Dht11_Read_Byte(dev);
- value[4] = Dht11_Read_Byte(dev);
- printk("<4>""%d.%d,%d.%d——%d",value[0],value[1],value[2],value[3],value[4]);
- //把这5个值返回给应用程序
- ret = copy_to_user(buf, &value, sizeof(value));
- }
- else
- printk("<4>""start error.number:%d,\r\n",ret);
- return ret;
- }
- /*
- * @description : 关闭/释放设备
- * @param - filp : 要关闭的设备文件(文件描述符)
- * @return : 0 成功;其他 失败
- */
- static int dht11_release(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- /* 设备操作函数 */
- static struct file_operations dht11_fops = {
- .owner = THIS_MODULE,
- .open = dht11_open,
- .read = dht11_read,
- .release = dht11_release,
- };
- /*
- * @description : 驱动入口函数
-
- * @param : 无
- * @return : 无
- */
- static int __init dht11_init(void)
- {
- int ret = 0;
-
-
-
- /* 设置DHT11所使用的GPIO */
- /* 1、获取设备节点:dht11 */
- dht11.nd = of_find_node_by_path("/dht11");
- if(dht11.nd == NULL) {
- printk("dht11 node not find!\r\n");
- return -EINVAL;
- } else {
- printk("dht11 node find!\r\n");
- }
- /* 2、 获取设备树中的gpio属性,得到DHT11所使用的DHT11编号 */
- dht11.dht11_gpio = of_get_named_gpio(dht11.nd, "dht11-gpio", 0);
- if(dht11.dht11_gpio < 0) {
- printk("can't get dht11-gpio");
- return -EINVAL;
- }
- printk("dht11-gpio num = %d\r\n", dht11.dht11_gpio);
- /* 3、设置GPIO为输出,并且输出高电平 */
- ret = gpio_direction_output(dht11.dht11_gpio, 1);
- if(ret < 0) {
- printk("can't set gpio!\r\n");
- }
- /* 注册字符设备驱动 */
- /* 1、创建设备号 */
- if (dht11.major) { /* 定义了设备号 */
- dht11.devid = MKDEV(dht11.major, 0);
- register_chrdev_region(dht11.devid, DHT11_CNT, DHT11_NAME);
- } else { /* 没有定义设备号 */
- alloc_chrdev_region(&dht11.devid, 0, DHT11_CNT, DHT11_NAME); /* 申请设备号 */
- dht11.major = MAJOR(dht11.devid); /* 获取分配号的主设备号 */
- dht11.minor = MINOR(dht11.devid); /* 获取分配号的次设备号 */
- }
- printk("dht11 major=%d,minor=%d\r\n",dht11.major, dht11.minor);
- /* 2、初始化cdev */
- dht11.cdev.owner = THIS_MODULE;
-
- cdev_init(&dht11.cdev, &dht11_fops);
- /* 3、添加一个cdev */
- cdev_add(&dht11.cdev, dht11.devid, DHT11_CNT);
- /* 4、创建类 */
- dht11.class = class_create(THIS_MODULE, DHT11_NAME);
- if (IS_ERR(dht11.class)) {
- return PTR_ERR(dht11.class);
- }
- /* 5、创建设备 */
- dht11.device = device_create(dht11.class, NULL, dht11.devid, NULL, DHT11_NAME);
- if (IS_ERR(dht11.device)) {
- return PTR_ERR(dht11.device);
- }
-
- //mutex_init(&dht11.dht11_mutex); //利用初始化函数,初始化这个结构体
-
-
-
- return 0;
- }
- /*
- * @description : 驱动出口函数
- * @param : 无
- * @return : 无
- */
- static void __exit dht11_exit(void)
- {
- /* 注销字符设备驱动 */
- cdev_del(&dht11.cdev);/* 删除cdev */
- unregister_chrdev_region(dht11.devid, DHT11_CNT); /* 注销设备号 */
- device_destroy(dht11.class, dht11.devid);
- class_destroy(dht11.class);
- }
- module_init(dht11_init);
- module_exit(dht11_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("zuozhongkai");
复制代码 |
|