龙芯技术社区
直播中

马博

13年用户 71经验值
擅长:操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟
私信 关注
[2K系列]

【龙芯2K0300蜂鸟板试用】第七篇 龙芯2K0300蜂鸟板--驱动DHT11

改版后的DHT11

距离第六篇发布差不多两周时间,这期间一直再捣腾DHT11,真的很痛苦(加之孩子开学,本人开学),试了各种方法,从相对简单的python,到驱动模块,再到GPIO直接驱动,一直没有成功,直到潜下心来,仔细看了看源码以及相关的设备树,总算解决了。距离总目标又进一步,现在总结一下。

  1. 源码里面已经编制好了DHT11相应的驱动(我之前按照stm32思路编写了相应驱动,一直没有加载成功),用户只需要确认一下即可,如图1所示。
    1.png

    图1 选择DTH11模块

  2. 在设备树里,修改相应说明,增加DHT11的说明(如图2),因为这里用到了引脚61(该引脚默认是SPI的,所以注释掉使其作为GPIO引脚使用,如图3所示)。
    2.png

    图2 增加设备树中DHT11的说明代码
    3.png

    图3 注释掉设备树中SPI的说明代码

  3. 对应源码中DHT11代码。经验证,发现运行时,会有错误发生,不像裸机那样稳定。其实,这个也是我自行编写相应DHT11驱动时一直没有成功的原因之一--为了保证这个单总线方式通信的成功率,尤其像这种有时序要求的通信,在基于OS运行机制下进行通信时需要添加开关中断操作(过去在UCOS-II做项目时被类似相应模块折磨过,记忆犹新),但在蜂鸟板对应源码中没有找到(我将尝试对应添加),错误如图4所示。
    4.png

    图4 运行错误提示

  4. 测试用例,具体运行情况,如视频所示。这里我同时还用stm32裸机跑了一个程序,来对比查看和蜂鸟板上运行的情况。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

int main(void) {
    int  fd;
    char buf[5];
    int j;

    fd = open("/dev/dht11", O_RDONLY);

    while(1)
    {
	temp = read(fd, buf, sizeof(buf));
	
        if( buf[4] == (buf[0]+buf[1]+buf[2]+buf[3]) )
	{
		printf("read sucessful!\\n");
		printf("humi is %d.%d,  temp is %d.%d \\n", buf[0],buf[1], buf[2],buf[3]);
	}
	else
	{	
		j++;
		if(j == 10)
		{
   			close(fd);
			return -1;
		}
		printf("read failed!\\n");
	}
       sleep(1);    	
    }
    return 0;
}

DHT11

回帖(1)

马博

2024-9-3 11:14:44

今天抽空按照我的理解对内核的dht11.c代码进行了修改,并进行了测试(测试代码还是沿用之前的,没有修改),明显效果要好得多,运行了近10分钟,没有出现error的情况。

主要修改的就是下面dht11_read函数


ssize_t dht11_read(struct file *file, char __user * user_buf, size_t size, loff_t * loff)
{
        volatile int max_wait;
        int err;
        unsigned long flags;  
        unsigned char dht11_data[5];

        local_irq_save(flags);  // 关中断  

        //mdelay(5); //拉低5ms 以免过快检测导致读取数据失败
        gpio_set_value(dht11_GPIO, LOW);
        mdelay(20); //拉低20ms
        /*拉高20-40us*/
        gpio_set_value(dht11_GPIO, HIGH);
        udelay(30); //拉高30us       

        //设置为输入
        gpio_direction_input(dht11_GPIO);
        /*DHT11响应信号*/
        udelay(10);
        if (gpio_get_value(dht11_GPIO) == LOW) {
                //80us 低电平
               
                while(gpio_get_value(dht11_GPIO) == LOW);
        }

        if (gpio_get_value(dht11_GPIO) == HIGH) {
                //80us 高电平
                err = 0;
                while(gpio_get_value(dht11_GPIO) == HIGH);  
        }               

        dht11_data[0] = get_dht11_value();        //湿度整数数据
        dht11_data[1] = get_dht11_value();        //湿度小数数据  
        dht11_data[2] = get_dht11_value();        //温度整数数据
        dht11_data[3] = get_dht11_value();        //温度小数数据
        dht11_data[4] = get_dht11_value();        //校验和

        if (copy_to_user(user_buf, dht11_data, size) != 0)
                ERROR_PRINT("dht11 date copy_to_user failed");
        //恢复为输出模式高电平
        end();

        local_irq_restore(flags); // 恢复中断
       
        return 0;
}

举报

更多回帖

发帖
×
20
完善资料,
赚取积分