初级会员
- 积分
- 76
- 金钱
- 76
- 注册时间
- 2019-5-26
- 在线时间
- 27 小时
|
常逛论坛的朋友可能还记得我之前写了一个dht11的驱动,源码已经上传,当时的DATA线是使用GPIO4,也就是GPIO1的4脚。
之前做摄像头,用了这个4脚,而且内核也变了一点,今天重新修改设备树,把这个DATA线移到了GPIO0,也就是1的0脚,发现又不行了。花了一下午,怎么也没发现问题,因为都是普通IO输出,我就直接改了,PAD寄存器的值没有改,其他参数是用宏定义的。
如果有朋友可以帮忙解决,非常非常感谢,真的!
设备树的修改
- pinctrl_dht11:dht11grp {
- fsl,pins = <
复制代码- dht11 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "atkalpha-dht11";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_dht11>;
- //dht11-gpio = <&gpio1 4 GPIO_ACTIVE_LOW>; //follow KEY0
- dht11-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
- status = "okay";
- };
复制代码 驱动和测试代码都没有改,我等会附上。
先放一个之前成功的时候的结果:
- /project # insmod dht11.ko
- dht11 node find!
- dht11-gpio num = 4
- dht11 major=249,minor=0
- /project # ./dht11App
- <4>45.0,21.6——72ansewr is right!
- ======================
- H = 45.0
- T = 21.6
- <4>45.0,21.1——67cheak = 72ansewr is right!
- ======================
- H = 45.0
- T = 21.1
- <4>47.0,42.2——234cheak = 67wrong answer
- ======================
- H = 47.0
- T = 42.2
- <4>47.0,21.1——69cheak = 234ansewr is right!
- ======================
- H = 47.0
- T = 21.1
- <4>47.0,21.1——69cheak = 69ansewr is right!
- ======================
- H = 47.0
- T = 21.1
- ^C
- /project #
复制代码
下面是驱动代码和应用程序代码:
驱动代码:
- #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");
复制代码
应用程序代码:
- #include "stdio.h"
- #include "unistd.h"
- #include "sys/types.h"
- #include "sys/stat.h"
- #include "fcntl.h"
- #include "stdlib.h"
- #include "string.h"
- /*
- * @description : main主程序
-
- * @param - argc : argv数组元素个数
-
- * @param - argv : 具体参数
-
- * @return : 0 成功;其他 失败
- */
- int main(int argc, char *argv[])
- {
- int fd, retvalue;
- unsigned char databuf[5]={0,0,0,0,0};
-
-
- char *filename = "/dev/dht11";
- /* 打开dht11驱动 */
- fd = open(filename, O_RDWR);
- if(fd < 0){
- printf("file %s open failed!\r\n", filename);
- return -1;
- }
- while(1)
- {
- /* 向/dev/dht11文件写入数据 */
- retvalue = read(fd, databuf, sizeof(databuf));
- if(retvalue < 0){
- printf("DHT11 Read Failed!\r\n");
-
- close(fd);
- return -1;
- }
- if(databuf[4] == databuf[0]+databuf[1]+databuf[2]+databuf[3])
- printf("ansewr is right!\n");
- else
- printf("wrong answer\n");
-
- printf("======================\n");
-
- printf("H = %d.%d\n",databuf[0],databuf[1]);
- printf("T = %d.%d\n",databuf[2],databuf[3]);
- printf("cheak = %d",databuf[4]);
-
-
- //每隔两秒采集一次
- sleep(2);
- }
- retvalue = close(fd); /* 关闭文件 */
- if(retvalue < 0){
- printf("file %s close failed!\r\n", argv[1]);
- return -1;
- }
- return 0;
- }
复制代码
|
|