OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5559|回复: 9

关于设备树仅仅修改了引脚就无法使用的问题

[复制链接]

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
发表于 2020-3-24 22:33:25 | 显示全部楼层 |阅读模式
常逛论坛的朋友可能还记得我之前写了一个dht11的驱动,源码已经上传,当时的DATA线是使用GPIO4,也就是GPIO1的4脚。
之前做摄像头,用了这个4脚,而且内核也变了一点,今天重新修改设备树,把这个DATA线移到了GPIO0,也就是1的0脚,发现又不行了。花了一下午,怎么也没发现问题,因为都是普通IO输出,我就直接改了,PAD寄存器的值没有改,其他参数是用宏定义的。

如果有朋友可以帮忙解决,非常非常感谢,真的!


设备树的修改
  1.   pinctrl_dht11:dht11grp {
  2.                         fsl,pins = <
复制代码
  1. dht11 {
  2.                 #address-cells = <1>;
  3.                 #size-cells = <1>;
  4.                 compatible = "atkalpha-dht11";
  5.                 pinctrl-names = "default";
  6.                 pinctrl-0 = <&pinctrl_dht11>;
  7.                 //dht11-gpio = <&gpio1 4 GPIO_ACTIVE_LOW>;      //follow KEY0
  8.                 dht11-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
  9.                 status = "okay";
  10.         };       
复制代码
驱动和测试代码都没有改,我等会附上。



先放一个之前成功的时候的结果:
  1. /project # insmod dht11.ko

  2. dht11 node find!
  3. dht11-gpio num = 4
  4. dht11 major=249,minor=0
  5. /project # ./dht11App
  6. <4>45.0,21.6——72ansewr is right!
  7. ======================
  8. H = 45.0
  9. T = 21.6
  10. <4>45.0,21.1——67cheak = 72ansewr is right!
  11. ======================
  12. H = 45.0
  13. T = 21.1
  14. <4>47.0,42.2——234cheak = 67wrong answer
  15. ======================
  16. H = 47.0
  17. T = 42.2
  18. <4>47.0,21.1——69cheak = 234ansewr is right!
  19. ======================
  20. H = 47.0
  21. T = 21.1
  22. <4>47.0,21.1——69cheak = 69ansewr is right!
  23. ======================
  24. H = 47.0
  25. T = 21.1
  26. ^C
  27. /project #
复制代码




下面是驱动代码和应用程序代码:


驱动代码:
  1. #include <linux/types.h>
  2. #include <linux/kernel.h>
  3. #include <linux/delay.h>
  4. #include <linux/ide.h>
  5. #include <linux/init.h>
  6. #include <linux/module.h>
  7. #include <linux/errno.h>
  8. #include <linux/gpio.h>
  9. #include <linux/cdev.h>
  10. #include <linux/device.h>
  11. #include <linux/of.h>
  12. #include <linux/of_address.h>
  13. #include <linux/of_gpio.h>
  14. #include <asm/mach/map.h>
  15. #include <asm/uaccess.h>
  16. #include <linux/semaphore.h>
  17. #include <asm/io.h>

  18. #define DHT11_CNT                        1                /* 设备号个数 */
  19. #define DHT11_NAME                        "dht11"        /* 名字 */

  20. /* dht11设备结构体 */


  21. struct dht11_dev{

  22.         dev_t devid;                        /* 设备号          */
  23.         struct cdev cdev;                /* cdev         */
  24.         struct class *class;        /* 类                 */
  25.         struct device *device;        /* 设备          */
  26.         int major;                                /* 主设备号          */
  27.         int minor;                                /* 次设备号   */
  28.         struct device_node        *nd; /* 设备节点 */
  29.         int dht11_gpio;                        /* dht11所使用的GPIO编号                */
  30.         //struct mutex dht11_mutex;        //定义一个互斥锁的结构体
  31. };


  32. struct dht11_dev dht11;                /* dht11设备 */


  33. /*

  34. * @description                : 打开设备
  35. * @param - inode         : 传递给驱动的inode
  36. * @param - filp         : 设备文件,file结构体有个叫做private_data的成员变量
  37. *                                           一般在open的时候将private_data指向设备结构体。
  38. * @return                         : 0 成功;其他 失败
  39. */



  40. static int dht11_open(struct inode *inode, struct file *filp)
  41. {
  42.         filp->private_data = &dht11; /* 设置私有数据 */
  43.         return 0;
  44. }



  45. /*

  46. *@description                :根据原理编写启动信号

  47. *@description                :使用gpio的API函数

  48. */

  49. static int Dht11_Start(struct dht11_dev *dev)
  50. {
  51.         unsigned int t =0,ret =0;        //用于计算超时
  52.         
  53.         //先设置为输出,初值先设置为1吧,因为是有上拉电阻

  54.         ret = gpio_direction_output(dev->dht11_gpio, 1);
  55.         if(ret < 0) {           

  56.                 printk("can't set output!\r\n");

  57.             }        

  58.         //启动信号
  59.         gpio_set_value(dev->dht11_gpio, 1);        /* 高电平持续5us */
  60.         udelay(5);

  61.         gpio_set_value(dev->dht11_gpio, 0);        /* 低电平持续18【ms】 */
  62.         //udelay(20);
  63.         mdelay(20);                //应该是拉低18ms以上啊
  64.         
  65.         gpio_set_value(dev->dht11_gpio, 1);        /* 高电平持续30us */
  66.         udelay(30);

  67.         //【G9设置为输入】-----接收响应信号
  68.         gpio_direction_input(dev->dht11_gpio);
  69.         
  70.         t =0;
  71.         while(gpio_get_value(dev->dht11_gpio)!= 0)
  72.         {
  73.                 udelay(1);
  74.                 t++;        
  75.                
  76.                 if(t>100)
  77.                         return -1;
  78.         }
  79.         
  80.         
  81.         
  82.         //过滤低电平
  83.         t = 0;
  84.         while(gpio_get_value(dev->dht11_gpio) == 0)
  85.         {
  86.                 udelay(1);
  87.                 t++;               

  88.                 if(t>100)
  89.                         return -2;
  90.         }

  91.         

  92.         //过滤高电平
  93.         t = 0;
  94.         while(gpio_get_value(dev->dht11_gpio) == 1)
  95.         {
  96.                 udelay(1);
  97.                 t++;        

  98.                 if(t>100)
  99.                         return -3;
  100.         }


  101.         //如果都正常,返回0,走人
  102.         //上面其实是在接收模块传回来的反馈信号
  103.         return 0;

  104. }



  105. /*

  106.   * @description        : 读取一个字节
  107.   
  108.   * @return                 : 读取到的字节数据

  109. */

  110. //返回0为异常
  111. static unsigned char Dht11_Read_Byte(struct dht11_dev *dev)
  112. {
  113.         //上锁
  114.         //mutex_lock(&dev->dht11_mutex);
  115.         
  116.         
  117.         unsigned char i, t = 0, data = 0;

  118.         
  119.         for(i=0; i<8; i++)
  120.         {
  121.                 //过渡低电平
  122.         //无论是【0】还是【1】,【一开始都是低电平】
  123.                 t = 0;

  124.                 while(gpio_get_value(dev->dht11_gpio) == 0)
  125.                 {
  126.                         udelay(1);
  127.                         t++;
  128.                         if(t>100)
  129.                         {
  130.                                 //mutex_unlock(&dev->dht11_mutex);
  131.                                 return -EINVAL;
  132.                         }

  133.                 }        
  134.                 //高电平出现,退出上面的循环

  135.                 //延时45us,再判断电平,就可以知道是1还是0
  136.                 udelay(45);

  137.                 //延时之后还是高电平,就说明是“1”
  138.                 if(gpio_get_value(dev->dht11_gpio) == 1)                //表示收到1
  139.                 {
  140.                         data |= 1<<(7-i);

  141.                         //过滤掉剩下的高电平
  142.                         t = 0;
  143.                         while( gpio_get_value(dev->dht11_gpio) == 1)
  144.                         {
  145.                                 udelay(1);
  146.                                 t++;               

  147.                                 if(t>100)
  148.                                 {
  149.                                         //mutex_unlock(&dev->dht11_mutex);
  150.                                         return -EINVAL;
  151.                                 }
  152.                         }        

  153.                 }               
  154.                 //如果是0,不用处理,本来初值就是0

  155.         }        
  156.         //mutex_unlock(&dev->dht11_mutex);
  157.         return data;
  158. }



  159. /*

  160. * @description                : 读函数

  161. * @param - filp         : 要关闭的设备文件(文件描述符)

  162. * @return                         : 0 成功;其他 失败

  163. */

  164. static ssize_t dht11_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
  165. {

  166.          int ret = 0;

  167.          unsigned char value[5]={0,0,0,0,0};
  168.         
  169.          
  170.          struct dht11_dev *dev = filp->private_data;

  171.          ret = Dht11_Start(dev);
  172.                
  173.          //读取4个值
  174.          gpio_direction_input(dev->dht11_gpio);
  175.          if(ret == 0)
  176.          {
  177.                 //printk("<4>""kernel_read\r\n");
  178.                 value[0] = Dht11_Read_Byte(dev);
  179.                 value[1] = Dht11_Read_Byte(dev);

  180.                 value[2] = Dht11_Read_Byte(dev);
  181.                 value[3] = Dht11_Read_Byte(dev);

  182.                 value[4] = Dht11_Read_Byte(dev);

  183.                 printk("<4>""%d.%d,%d.%d——%d",value[0],value[1],value[2],value[3],value[4]);

  184.                 //把这5个值返回给应用程序

  185.                 ret = copy_to_user(buf, &value, sizeof(value));
  186.         }
  187.         else
  188.                 printk("<4>""start error.number:%d,\r\n",ret);

  189.         return ret;
  190. }




  191. /*

  192. * @description                : 关闭/释放设备

  193. * @param - filp         : 要关闭的设备文件(文件描述符)

  194. * @return                         : 0 成功;其他 失败

  195. */
  196. static int dht11_release(struct inode *inode, struct file *filp)
  197. {

  198.         return 0;

  199. }


  200. /* 设备操作函数 */
  201. static struct file_operations dht11_fops = {
  202.         .owner = THIS_MODULE,

  203.         .open = dht11_open,

  204.         .read = dht11_read,

  205.         .release =         dht11_release,
  206. };







  207. /*
  208. * @description        : 驱动入口函数

  209. * @param                 : 无

  210. * @return                 : 无
  211. */

  212. static int __init dht11_init(void)
  213. {

  214.         int ret = 0;

  215.         
  216.         
  217.         
  218.         /* 设置DHT11所使用的GPIO */

  219.         /* 1、获取设备节点:dht11 */

  220.         dht11.nd = of_find_node_by_path("/dht11");

  221.         if(dht11.nd == NULL) {

  222.                 printk("dht11 node not find!\r\n");

  223.                 return -EINVAL;

  224.         } else {

  225.                 printk("dht11 node find!\r\n");

  226.         }

  227.         /* 2、 获取设备树中的gpio属性,得到DHT11所使用的DHT11编号 */

  228.         dht11.dht11_gpio = of_get_named_gpio(dht11.nd, "dht11-gpio", 0);

  229.         if(dht11.dht11_gpio < 0) {

  230.                 printk("can't get dht11-gpio");
  231.                 return -EINVAL;

  232.         }

  233.         printk("dht11-gpio num = %d\r\n", dht11.dht11_gpio);

  234.         /* 3、设置GPIO为输出,并且输出高电平 */

  235.         ret = gpio_direction_output(dht11.dht11_gpio, 1);



  236.         if(ret < 0) {

  237.                 printk("can't set gpio!\r\n");
  238.         }


  239.         /* 注册字符设备驱动 */

  240.         /* 1、创建设备号 */
  241.         if (dht11.major) {                /*  定义了设备号 */
  242.                 dht11.devid = MKDEV(dht11.major, 0);

  243.                 register_chrdev_region(dht11.devid, DHT11_CNT, DHT11_NAME);

  244.         } else {                                                /* 没有定义设备号 */

  245.                 alloc_chrdev_region(&dht11.devid, 0, DHT11_CNT, DHT11_NAME);        /* 申请设备号 */

  246.                 dht11.major = MAJOR(dht11.devid);        /* 获取分配号的主设备号 */

  247.                 dht11.minor = MINOR(dht11.devid);        /* 获取分配号的次设备号 */
  248.         }

  249.         printk("dht11 major=%d,minor=%d\r\n",dht11.major, dht11.minor);        


  250.         /* 2、初始化cdev */
  251.         dht11.cdev.owner = THIS_MODULE;
  252.         
  253.         cdev_init(&dht11.cdev, &dht11_fops);


  254.         /* 3、添加一个cdev */

  255.         cdev_add(&dht11.cdev, dht11.devid, DHT11_CNT);

  256.         /* 4、创建类 */
  257.         dht11.class = class_create(THIS_MODULE, DHT11_NAME);

  258.         if (IS_ERR(dht11.class)) {
  259.                 return PTR_ERR(dht11.class);
  260.         }


  261.         /* 5、创建设备 */
  262.         dht11.device = device_create(dht11.class, NULL, dht11.devid, NULL, DHT11_NAME);

  263.         if (IS_ERR(dht11.device)) {
  264.                 return PTR_ERR(dht11.device);
  265.         }

  266.         
  267.         //mutex_init(&dht11.dht11_mutex);                        //利用初始化函数,初始化这个结构体
  268.         
  269.         
  270.         
  271.         return 0;

  272. }



  273. /*

  274. * @description        : 驱动出口函数

  275. * @param                 : 无

  276. * @return                 : 无

  277. */


  278. static void __exit dht11_exit(void)
  279. {

  280.         /* 注销字符设备驱动 */

  281.         cdev_del(&dht11.cdev);/*  删除cdev */

  282.         unregister_chrdev_region(dht11.devid, DHT11_CNT); /* 注销设备号 */

  283.         device_destroy(dht11.class, dht11.devid);

  284.         class_destroy(dht11.class);
  285. }

  286. module_init(dht11_init);
  287. module_exit(dht11_exit);
  288. MODULE_LICENSE("GPL");
  289. MODULE_AUTHOR("zuozhongkai");
复制代码




应用程序代码:
  1. #include "stdio.h"
  2. #include "unistd.h"
  3. #include "sys/types.h"
  4. #include "sys/stat.h"
  5. #include "fcntl.h"
  6. #include "stdlib.h"
  7. #include "string.h"


  8. /*
  9. * @description                : main主程序

  10. * @param - argc         : argv数组元素个数

  11. * @param - argv         : 具体参数

  12. * @return                         : 0 成功;其他 失败

  13. */

  14. int main(int argc, char *argv[])
  15. {
  16.         int fd, retvalue;

  17.         unsigned char databuf[5]={0,0,0,0,0};
  18.         
  19.         
  20.         char *filename = "/dev/dht11";

  21.         /* 打开dht11驱动 */
  22.         fd = open(filename, O_RDWR);

  23.         if(fd < 0){

  24.                 printf("file %s open failed!\r\n", filename);
  25.                 return -1;
  26.         }

  27.         while(1)
  28.         {
  29.                 /* 向/dev/dht11文件写入数据 */
  30.                 retvalue = read(fd, databuf, sizeof(databuf));
  31.                 if(retvalue < 0){
  32.                         printf("DHT11 Read Failed!\r\n");
  33.                         
  34.                         close(fd);
  35.                         return -1;
  36.                 }

  37.                 if(databuf[4] == databuf[0]+databuf[1]+databuf[2]+databuf[3])
  38.                         printf("ansewr is right!\n");
  39.                 else
  40.                         printf("wrong answer\n");
  41.                
  42.                 printf("======================\n");
  43.         
  44.                 printf("H = %d.%d\n",databuf[0],databuf[1]);
  45.                 printf("T = %d.%d\n",databuf[2],databuf[3]);
  46.                 printf("cheak = %d",databuf[4]);
  47.                
  48.                
  49.                 //每隔两秒采集一次
  50.                 sleep(2);

  51.         }

  52.         retvalue = close(fd); /* 关闭文件 */
  53.         if(retvalue < 0){
  54.                 printf("file %s close failed!\r\n", argv[1]);
  55.                 return -1;
  56.         }

  57.         return 0;

  58. }
复制代码



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
 楼主| 发表于 2020-3-24 22:44:42 | 显示全部楼层
这是错误信息。

在启动信号的时候就有问题了
  1. root@ALIENTEK-IMX6U:/myproject# insmod dht11.ko
  2. dht11 node find!
  3. dht11-gpio num = 0
  4. dht11 major=249,minor=0
  5. root@ALIENTEK-IMX6U:/myproject# ./dht11App
  6. <4>start error.number:-2,
  7. DHT11 Read Failed!
复制代码
回复 支持 反对

使用道具 举报

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
 楼主| 发表于 2020-3-24 23:24:15 | 显示全部楼层
不好意思,没看到设备树那里少给了点信息,这个完整的,大家帮帮忙看看吧,真的有点焦急

  1.                 pinctrl_dht11:dht11grp {
  2.                         fsl,pins = <
  3.                         MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 0xF0B0        // dht11
  4.                         >;                       
  5.                 };
复制代码
回复 支持 反对

使用道具 举报

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
 楼主| 发表于 2020-3-25 09:44:17 | 显示全部楼层
顶一下
回复 支持 反对

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2020-3-25 10:09:11 | 显示全部楼层

回帖奖励 +10 金钱

绑定,看看有没有哪个朋友做过
开往春天的手扶拖拉机
回复 支持 反对

使用道具 举报

14

主题

83

帖子

0

精华

初级会员

Rank: 2

积分
167
金钱
167
注册时间
2019-7-11
在线时间
42 小时
发表于 2020-3-25 18:13:17 | 显示全部楼层

回帖奖励 +10 金钱

是不是引脚冲突?
回复 支持 反对

使用道具 举报

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
 楼主| 发表于 2020-3-25 18:39:36 | 显示全部楼层
casy99 发表于 2020-3-25 18:13
是不是引脚冲突?

不是,已经在设备树反复确认了
回复 支持 反对

使用道具 举报

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
 楼主| 发表于 2020-3-27 11:25:18 | 显示全部楼层
未解决,顶一下
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

高级会员

Rank: 4

积分
657
金钱
657
注册时间
2018-5-29
在线时间
70 小时
发表于 2020-3-27 15:50:17 | 显示全部楼层
设备树 有没有 更新啊
回复 支持 反对

使用道具 举报

5

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-5-26
在线时间
27 小时
 楼主| 发表于 2020-3-28 00:45:16 | 显示全部楼层
yipingfing 发表于 2020-3-27 15:50
设备树 有没有 更新啊

有的有的,还特意试了其他设备
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 09:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表