RDA8910(4GCAT1)CSDK二次开发:15、通过OneWire驱动库获取DS18B20/DHT11的数据

目录

点击这里查看所有博文

  本系列博客所述资料均来自合宙官方,并不是本人原创(只有博客是自己写的),csdk只是得到了口头的允许公开授权。出于热心,本人将自己的所学笔记整理并推出相对应的使用教程,方面其他人学习。为国内的物联网事业发展尽自己的一份绵薄之力,没有为自己谋取私利的想法。若出现侵权现象,请告知本人,本人会立即停止更新,并删除相应的文章和代码。

  本系列博客基于紫光展锐的RDA8910 LTE Cat 1 bis芯片平台开发。理论上适用于合宙的Air720U、Air724U、广和通L610以及安信可的cat-01模块。

  各个厂家的部分配置文件可能不一样,也许会导致设备出现奇怪的问题,其他的模块我也不确定能不能用,自行测试。但是有一点编译下载和监视流程基本一样,可供参考。

  先不管支不支持,如果你用的模块是是紫光展锐的RDA8910,那都不妨一试,也许会有意外收获(也有可能变砖,慎重!!!)。

  我使用的是Air724UG开发板,如果在其他模块上不能用,那也不要强怼,也许是开发包不兼容吧。这里的代码是没有问题的。例程仅供参考!

一、前言

  大概在一个月之前吧,群里就有小伙伴问:“咱们的CAT1能不能读取到单总线数据啊?比如说DS18B20这些传感器”。当时我就说这些传感器对时序的要求比较高,都是us级别的。驱动放在lua层还真不一定行,csdk的问题应该不大。

  又问:“那小哥哥什么时候安排一波呢?”

  答:“别别别,我可是钢铁直男,对男的没兴趣。要不这样吧,我周末看看吧,有时间的话搞一下”
在这里插入图片描述
  然而这一个周末看看,就鸽了将近一个月。
在这里插入图片描述
  想了想就这么一直鸽下去也不是个事情。于是乎最近几天抽时间看了下,虽然中间也遇到了一点波折。但是这都不影响结果,好在是搞出来了。既然搞出来了那好东西就要和大家分享。

二、单总线时序

  虽然DS18B20和DHT11都叫做单总线通讯,但是他们的时序要求却不太一样,包括读时序的位置也不一样。不过好在它们基本的交互逻辑都是差不多的,这里就拿ds18b20的驱动时序随便讲一下。

2.1、初始化时序

  在初始化序列期间,总线控制器拉低总线并保持 480us 以发出(TX)一个复位脉冲,然后释放总线,进入接收状态(RX)。单总线由 5K 上拉电阻拉到高电平。当DS18B20 探测到 I/O 引脚上的上升沿后,等待 15-60us,然后发出一个由 60-240us低电平信号构成的存在脉冲。
在这里插入图片描述
在这里插入图片描述

2.2、写时序

  ds18b20的写时序又分为写0时序和写1时序,总线控制器通过写 1 时序写逻辑 1 到DS18B20,写 0 时序写逻辑 0 到 DS18B20。所有写时序必须最少持续 60us,包括两个写周期之间至少1us 的恢复时间。当总线控制器(单片机)把数据线从逻辑高电平拉到低电平的时候,写时序开始。

  总控制器要生成一个写 0 时序,必须把数据线拉到低电平并持续保持(至少 60us)。然后释放。

  总控制器要生成一个写 1时序,必须把数据线拉到低电平,然后在15us内释放总线,并持续保持(至少 60us)。然后释放。
在这里插入图片描述

在这里插入图片描述

2.3、读时序

  ds18b20的读时序又分为读0时序和读1时序,总线控制器在发出读暂存器指令[BEh]或读电源模式指令[B4H]后必须立刻开始读时序。所有读时序必须最少 60us,包括两个读周期间至少 1us 的恢复时间。当总线控制器把数据线从高电平拉到低电平时(数据线必须至少保持 1us),读时序开始。

  当传输逻辑 0 结束后,总线将被释放,通过上拉电阻回到上升沿状态。从 DS18B20 输出的数据在读时序的下降沿出现后 15us 内有效。因此,总线控制器在读时序开始后必须停止把 I/O 脚驱动为低电平 15us,以读取I/O 脚状态。
在这里插入图片描述

在这里插入图片描述

三、OneWire驱动库

  学习完ds18b20的读时序后,介绍下本文开头提到的OneWire库。

  在编写DS18B20和DHT11驱动后,发现类似这种的单总线传感器。都有一个共同的特点,想要完成它们的读取过程,那就需要有us级别的延时,需要能够快速切换gpio的输入/输出状态以及读取/设置gpio的状态。单个操作都必须在极短的时间内完成。整个读取过程中除了需要操作gpio就不依赖任何其他的库函数。

3.1、基础库

  我将这些共同点整理了下,提供了OneWire库,其中包含基础库函数6个,分别是:

/**
@description: 输出调试信息
*/

  • OneWire_printf(fmt,…);

/**
*@description: 设置单总线信号线为输入。默认上拉
*@param :pin{uint8}:要操作的引脚
*@return: TRUE:正确
    FALSE:引脚不在允许范围
*/

  • OneWire_IO_IN(uint8 pin);

/**
*@description: 设置单总线信号线为输出。默认输出高定平
*@param :pin{uint8}:要操作的引脚
*@return: 无
*/

  • OneWire_IO_OUT(uint8 pin);

/**
*@description: 单总线输出高低电平
*@param : pin{uint8}:要操作的引脚
    level{uint8}}:要输出的电平。0或者1
*@return: 无
*/

  • OneWire_DQ_OUT(uint8 pin, uint8 level);

/**
*@description: 读取单总线的高低电平信号
*@param : pin{uint8}:要操作的引脚
*@return: 0或者1
*/

  • OneWire_DQ_IN(uint8 pin);

/**
*@description: 单总线1us延时函数
*@param : us{uint32}:调用的次数。
*@return: 无
*/

  • OneWire_Delay_1us(volatile uint32 us);

3.2、扩展库

  然后又在RDA8910平台上,基于OneWire库开发了DS18B20的驱动以及DHT11的驱动。这两个驱动完全依赖于OneWire库函数,不依赖其他文件,整个驱动基于platform提供的6个函数制作。
在这里插入图片描述
  移植在不同的平台只需要修改这上图所示的六个函数,即可直接调用扩展库中提供的ds18b20和dht11的驱动。

3.2.1、DS18B20

  其中DS18B20提供了两个读取函数,分别是:

/**
*@description: 从ds18b20得到温度值数字,精确到0.0625。结果被扩大10000倍
*@param : pin{uint8}:要操作的引脚
    TempNum{int *}:输出温度值
*@return 0:正常获取
    2:传入的pin不在允许范围
    3:未检测到ds18b20
*/

  • uint8 DS18B20_GetTemp_Num(uint8 pin, int *TempNum);

/**
*@description: 从ds18b20得到温度值字符串
*@param : pin{uint8}:要操作的引脚
    TempNum{char *}:输出温度字符串
*@return 0:正常获取
    1:TempStr=NULL
    2:传入的pin不在允许范围
    3:未检测到ds18b20
*/

  • uint8 DS18B20_GetTemp_String(uint8 pin, char *TempStr);

3.2.2、DHT11

  其中DHT11提供了两个读取函数,分别是:

/**
*@description: 从dht11得到温/湿度值数字
*@param : pin{uint8}:要操作的引脚
    HumNum{uint8 *}:输出温度值
    TemNum{uint8 *}:输出湿度值
*@return 0:正常获取
    2:传入的pin不在允许范围
    3:未检测到dht11
    4:数据校验错误
*/

  • uint8 DHT11_GetData_Num(uint8 pin, uint8 *HumNum, uint8 *TemNum);

/**
*@description: 从dht11得到温/湿度值字符串
*@param : pin{uint8}:要操作的引脚,可选范围0、1、2、3、7
    HumStr{char *}:输出温度值字符串
    TemStr{char *}:输出湿度值字符串
*@return 0:正常获取
    1:HumStr == NULL || TemStr == NULL
    2:传入的pin不在允许范围
    3:未检测到dht11
    4:数据校验错误
*/

  • uint8 DHT11_GetData_String(uint8 pin, char *HumStr, char *TemStr);

  主要是我手上就只有这两种传感器,只能在初始版本内置两个驱动的具体实现。有兴趣的同学可以一起来参与此仓库的贡献。

  上述OneWire操作库,已经在码云开源,获取地址:

git clone https://gitee.com/chenxiahuaxu/onewire_driver_library

四、测试DS18B20驱动

4.1、编写程序

  这一部分是本例程的核心,目的是读取DS18B20的值。

static void ds18b20_task(PVOID pParameter)
{
    iot_os_sleep(3000);
    while (1)
    {
        if (DS18B20_GetTemp_Num(7, &TempNum) == 0)
        {
            iot_debug_print("[ds18b20]DS18B20_GetTemp_Num : %d", TempNum);
        }
        iot_os_sleep(1000);
        if (DS18B20_GetTemp_String(7, &TempStr[0]) == 0)
        {
            iot_debug_print("[ds18b20]DS18B20_GetTemp_String : %s", TempStr);
        }
        iot_os_sleep(1000);
    }
}

  这一部分是本例程的彩蛋,将读取到的值显示在OLED-SSD1306上。

static void oled_task(PVOID pParameter)
{

    if (OLED_Init() == FALSE) //初始化OLED
    {
        while (1)
        {
            iot_debug_print("[oled]OLED_Init FALSE!");
            iot_os_sleep(1000);
        }
    }
    OLED_ShowString(0, 0, "LUAT CSDK", 24);
    OLED_ShowString(0, 24, "DEMO DS18B20", 16);
    OLED_ShowString(0, 40, "Tempera:", 12);
    OLED_ShowString(0, 52, "num:", 12);

    while (1)
    {
        OLED_ShowString(50, 40, TempStr, 12); //显示ASCII字符
        OLED_ShowNum(50, 52, TempNum, 6, 12); //显示ASCII字符
        OLED_Refresh_Gram();                  //更新显示到OLED
        iot_os_sleep(1000);
        iot_debug_print("[oled]demo_oled run!");
    }
}

4.2、完整程序

  完整的demo在这里,可以复制直接用。

/***************
	demo_ds18b20
****************/

#include "iot_debug.h"
#include "iot_os.h"
#include "am_openat.h"
#include "oled.h"
#include "ds18b20.h"

int TempNum = 0;
char TempStr[10] = {0};

static void oled_task(PVOID pParameter)
{

    if (OLED_Init() == FALSE) //初始化OLED
    {
        while (1)
        {
            iot_debug_print("[oled]OLED_Init FALSE!");
            iot_os_sleep(1000);
        }
    }
    OLED_ShowString(0, 0, "LUAT CSDK", 24);
    OLED_ShowString(0, 24, "DEMO DS18B20", 16);
    OLED_ShowString(0, 40, "Tempera:", 12);
    OLED_ShowString(0, 52, "num:", 12);

    while (1)
    {
        OLED_ShowString(50, 40, TempStr, 12); //显示ASCII字符
        OLED_ShowNum(50, 52, TempNum, 6, 12); //显示ASCII字符
        OLED_Refresh_Gram();                  //更新显示到OLED
        iot_os_sleep(1000);
        iot_debug_print("[oled]demo_oled run!");
    }
}

static void ds18b20_task(PVOID pParameter)
{
    iot_os_sleep(3000);
    while (1)
    {
        if (DS18B20_GetTemp_Num(7, &TempNum) == 0)
        {
            iot_debug_print("[ds18b20]DS18B20_GetTemp_Num : %d", TempNum);
        }
        iot_os_sleep(1000);
        if (DS18B20_GetTemp_String(7, &TempStr[0]) == 0)
        {
            iot_debug_print("[ds18b20]DS18B20_GetTemp_String : %s", TempStr);
        }
        iot_os_sleep(1000);
    }
}

int appimg_enter(void *param)
{
    iot_os_sleep(2000);
    iot_debug_print("[oled]appimg_enter");

    iot_os_create_task(oled_task, NULL, 1024, 1, OPENAT_OS_CREATE_DEFAULT, "oled_task");
    iot_os_create_task(ds18b20_task, NULL, 1024, 1, OPENAT_OS_CREATE_DEFAULT, "ds18b20_task");
    return 0;
}

void appimg_exit(void)
{
    iot_debug_print("[oled]appimg_exit");
}

4.3、下载测试

  传感器信号线接在了GPIO7。可以通过程序设定。

在这里插入图片描述

五、测试DHT11驱动

4.1、编写程序

  这一部分是本例程的核心,目的是读取DHT11的值。

static void dht11_task(PVOID pParameter)
{
    iot_os_sleep(3000);
    while (1)
    {
        if (DHT11_GetData_String(7, &HumStr, &TemStr) == 0)
        {
            iot_debug_print("[dht11]HumStr: %s,TemStr: %s", HumStr, TemStr);
        }
        iot_os_sleep(3000);
    }
}

4.2、完整程序

  完整的demo在这里,可以复制直接用。

/***************
	demo_dht11
****************/

#include "iot_debug.h"
#include "iot_os.h"
#include "am_openat.h"
#include "oled.h"
#include "dht11.h"

char HumStr[10] = {0};
char TemStr[10] = {0};

static void oled_task(PVOID pParameter)
{

    if (OLED_Init() == FALSE) //初始化OLED
    {
        while (1)
        {
            iot_debug_print("[oled]OLED_Init FALSE!");
            iot_os_sleep(1000);
        }
    }
    OLED_ShowString(0, 0, "LUAT CSDK", 24);
    OLED_ShowString(0, 24, "DEMO DHT11", 16);
    OLED_ShowString(0, 40, "Humidity:", 12);
    OLED_ShowString(0, 52, "Tempera:", 12);

    uint8 t = 0;
    while (1)
    {
        OLED_ShowString(60, 40, HumStr, 12); //显示ASCII字符
        OLED_ShowString(60, 52, TemStr, 12); //显示ASCII字符
        OLED_Refresh_Gram();                 //更新显示到OLED
        iot_os_sleep(1000);
        iot_debug_print("[oled]demo_oled run!");
    }
}

static void dht11_task(PVOID pParameter)
{
    iot_os_sleep(3000);
    while (1)
    {
        if (DHT11_GetData_String(7, &HumStr, &TemStr) == 0)
        {
            iot_debug_print("[dht11]HumStr: %s,TemStr: %s", HumStr, TemStr);
        }
        iot_os_sleep(3000);
    }
}

int appimg_enter(void *param)
{
    iot_os_sleep(2000);
    iot_debug_print("[oled]appimg_enter");

    iot_os_create_task(oled_task, NULL, 1024, 1, OPENAT_OS_CREATE_DEFAULT, "oled_task");
    iot_os_create_task(dht11_task, NULL, 1024, 1, OPENAT_OS_CREATE_DEFAULT, "dht11_task");
    return 0;
}

void appimg_exit(void)
{
    iot_debug_print("[oled]appimg_exit");
}

4.3、下载测试

  传感器信号线也接在了GPIO7。可以通过程序设定。

在这里插入图片描述

不会下载的点击这里,进去查看我的RDA8910 CSDK二次开发入门教程专题第一篇博文1、RDA8910CSDK二次开发:环境搭建里面讲了怎么下载
这里只是我的学习笔记,拿出来给大家分享,欢迎大家批评指正,本篇教程到此结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遇雪长安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值