最近想要做一个基于嵌入式Linux Qt驱动dht11温湿度传感器的实验。想要实现的功能是通过野火的imx6ull开发板控制dht11传感器,然后使用Qt做一个上位机,在上位机上面把数据显示出来。
这里把我在做的过程中遇到的一些问题先记录一下,免得日后忘记。
在网上关于这方面的资料不多,大多数都是基于stm32来控制的,所以在做的过程中遇到一些问题解决起来也比较麻烦。
下面简述一下我做的过程及遇到的问题
首先查看原理图看使用到了哪个管脚,然后在设备树里添加相应的节点。这里用到了gpio子系统和pinctrl子系统。
接着参考网上的相关代码,进行了改写,因为这个传感器的时序也比较简单,所以有关时序的部分基本上可以不用改。
遇到的第一个问题:写好驱动后,在应用程序中使用read函数来读取设备文件,如果只读取一次,可以得到结果,但是如果使用while(1)来尝试反复读取,就会失败。
按照手册来说,只要两次读取间隔超过1秒就行了,但是我使用while(1)即使休眠sleep(3)之类的依然会在第二次读取的失败,而且整个函数会卡死在读取这里,这个进程怎么也杀不死,kill -9杀不死,kill -15 也杀不死。这里很快把问题定位在了read函数。
后面,我在代码中做了如下修改:本来在驱动程序里面有使用while函数来等待管脚电平的跳变,我认为这样是不合理的,因为没有超时处理,容易卡死,所以我加了一个计数,当超过一定计数值时就跳出while循环。后来这个问题就解决了。虽然我是不确定一开始是不是因为这个原因,因为中间过了挺久的时间,我不确定有没有别的因素存在,总之后来就不会卡死了,可以使用while循环来反复读取。
遇到的第二个问题:在解决了上面的问题之后,insmod安装驱动,可以工作,然后rmmod卸载驱动,再次insmod安装驱动就会发现安装不上去。
使用dmesg命令查看内核打印的信息,比较容易猜到应该是卸载驱动的时候没有卸载干净,然后仔细看了一下驱动,在结合网上查找资料,发现我的驱动里没有写remove函数。所以我添加了remove函数,在remove函数里注销掉那些东西。而且要注意注销的顺序,和注册是相反的,比如在驱动中最先是申请设备号,在注销的时候就是最后注销它,否则会出现很多错误,包括段错误。
遇到的第三个问题:在解决了第二个问题之后,已经可以反复卸载和安装驱动了,但是发现一个问题,就是在第二次安装的时候,总是会出现gpio_request失败,按道理讲我已经在remove函数里使用gpio_free释放掉了,不应该会失败才对,后来发现是在gpio_request的时候还没拿到引脚号,全局变量没有初始化默认是0,所以request的是0,后来通过一个函数(忘记叫什么了,总之是gpio子系统的那些函数)从设备树中拿到引脚号,这个引脚号是2,所以后面free的是2,也就是说request和free的不是同一个引脚,当然会出错了。
这属于粗心的错,把这个问题解决了之后,这个驱动总算可以正常工作了,也完全可以反复卸载和安装。
遇到的第四个问题:在第一个问题里提到我在while里加了超时处理,防止一直死等卡死。最开始我是这样写的
代码语言:javascript复制
while(gpio_get_value(gpio)==0 &&cnt<6)< span="">
{
cnt ;
udelay(10);
}
这里通过cnt来防止while死掉,也就是说最多等待60微秒就退出循环。但是直觉告诉我这样不好,因为中间延时10个微秒太长了,导致响应性不好。所以我改成了这样:
代码语言:javascript复制
while(gpio_get_value(gpio)==0 &&cnt<60)< span="">
{
cnt ;
udelay(1);
}
这样的实时响应性好多了,测出的数据也更准确了。
到这里为止,驱动就基本没有问题了,使用应用程序来读取设备文件,也基本没问题,就是有时数据校验会失败,但是测出的数据基本可以,而且是有变化的,说明还是比较可靠的。
接下来是把在Qt里把数据读出来并且显示,下面说一下调试Qt遇到的问题。
在写完驱动之后,很自然会写一个.c的测试程序,用来验证驱动是否能正常工作,很幸运,一下子就成功了,于是我认为在Qt中也是类似,直接用Qt里的read相关的函数去读取设备文件就好了,但是没想到在这个环节卡了我最久
起初,我使用Qfile 里的readAll方法去读,发现控制台会刷屏(刷屏就是驱动中的read一直被调用而打印出的信息刷屏),一读就停不下来,而且后面的程序也执行不了,也就是说函数没有返回。
我不太清楚是什么原因,只能换一个函数,接着我尝试了readLine方法,一样刷屏,接着尝试read方法,这个方法和C语言的read类似,参数里要填读几个字节,这和前面两个不太一样,所以我想,这回应该不会刷屏了吧。
结果确实没有刷屏,但是读取的数据是错的,体现出来的就是从机无响应(这时我还没有注意这个问题)。
虽然说数据是错的,但是好歹没有刷屏了,只要再想一想为什么会读出错的数据就行了。
我想到Qt里还有一种读文件的方式,就是使用数据流Datastream,但是效果和上面的read一样。
接着我开始思考刷屏的原因,百度了一下,有人说要在末尾加一个"