当前位置: 首页 > 文档资料 > YoC 编程基础 >

DHT11 传感器数据采集例程

优质
小牛编辑
116浏览
2023-12-01

本文介绍如何使用YoC传感驱动框架开发传感器驱动,实现数据采集。

本例程可以运行在CB2201开发板上。

本章节介绍传感数据采集例程的开发流程,包括应用初始化、驱动初始化及传感驱动的开发。

3.1 应用初始化

应用入口函数为app_main,主要实现板级初始化、传感驱动初始化及传感数据的获取。

/* 传感器引脚配置 */
static sensor_pin_config_t dht11_config = {PA4};

void main()
{
     /* 板级初始化 */
    board_yoc_init();
    LOGI(TAG, "dht11 sensor demo\n");

    /* 注册DHT11传感驱动 */
    app_sensor_dht11_register(&dht11_config, 0);

    int temperature = 0, humidity = 0;

    /* 定时读取传感值并打印输出结果 */
    while (1) {
        get_sensor_value("dht", &temperature, &humidity);
        LOGI(TAG, "temperature=%d humidity=%d", temperature, humidity);
        aos_msleep(10000);
    }
}

3.2 板级初始化

板级初始化的入口为board_yoc_init,主要完成硬件初始化以及OS组件的初始化,由app_main函数调用。

void board_yoc_init(void)
{
    /* 初始化console驱动 */
#ifdef CONSOLE_ID
    console_init(CONSOLE_ID, 115200, 128);
#else
    console_init(0, 115200, 128);
#endif

    /* 初始化出厂配置Flash分区 */
    nvram_init("factory");

    /* 创建CLI任务 */
    utask_t *task = utask_new("at&cli", 2 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI);

    /* CLI初始化及系统命令注册 */
    board_cli_init(task);
}

3.3 传感驱动的开发

驱动的实现在dht11_drv.c中

  • 驱动框架实例
/* 定义驱动框架实例 */
static sensor_driver_t sensor_driver = {
    .drv = {
        .name   = "dht",
        .type   = "sensor",
        .init   = dht11_init,
        .uninit = dht11_uninit,
        .lpm    = dht11_lpm,
        .open   = dht11_open,
        .close  = dht11_close,
    },
    .fetch      = dht11_fetch, /* 数据采集接口 */
    .getvalue   = dht11_get,   /* 数据获取接口 */
};

/* 应用注册接口 */
void app_sensor_dht11_register(void *config, int idx)
{
    driver_register(&sensor_driver.drv, config, idx);
}
  • 接口实现
static int dht11_fetch(dev_t *dev)
{
    int ret;

    /* 根据DHT11接口规范获取传感数据 */
    ret = read_data(dev);
    if (ret == 0) {
        /* 获取到的数据进行校验 */
        ret = data_check(dev);
    }

    if (ret < 0) {
        return -1;
    }

    return 0;
}

static int dht11_get(dev_t *dev, void *value, size_t size)
{
    sensor_dev_t *sensor = (sensor_dev_t*)dev;

    if ((size < sizeof (sensor_dht11_t)) || (value == NULL)) {
        return -EINVAL;
    }

    /* 湿度数据,接口输出位整数,单位是0.1相对湿度*/
    ((sensor_dht11_t *)value)->rh = sensor->recv_buf[0] * 10 + sensor->recv_buf[1];

    /* 温度数据,接口输出位整数,单位是0.1摄氏度*/
    ((sensor_dht11_t *)value)->degree = sensor->recv_buf[2] * 10 + sensor->recv_buf[3];

    return 0;
}
  • 接口规范实现
static int read_data(dev_t *dev)
{
    sensor_dev_t *sensor = (sensor_dev_t*)dev;
    int i = 0;
    int j = 0;

    memset(sensor->recv_buf, 0, sizeof(sensor->recv_buf));

    /* 设置GPIO输出模式,输出一个脉冲,启动采集 */
    csi_gpio_pin_config(sensor->handle, GPIO_MODE_OPEN_DRAIN, GPIO_DIRECTION_OUTPUT);

    csi_gpio_pin_write(sensor->handle, 0);
    udelay(20000);

    csi_gpio_pin_write(sensor->handle, 1);
    udelay(40);

    /* 设置GPIO输入模式,等待起始bit */
    csi_gpio_pin_config(sensor->handle, GPIO_MODE_PULLUP, GPIO_DIRECTION_INPUT);

    if (read_level(dev, DHT_SENSOR_COUNTS, 0) < 0) {
        LOGE(TAG, "wait high err");
        return -1;
    }

    /* 按协议读取所有bit */
    for (i = 0; i < SENSOR_DATA_LEN; i++) {
        // 等待低电平
        if (read_level(dev, DHT_SENSOR_COUNTS, 1) < 0) {
            LOGE(TAG, "wait data low err, %d\n", i);
            return -1;
        }
        // 等待高电平
        if (read_level(dev, DHT_SENSOR_COUNTS, 0) < 0) {
            LOGE(TAG, "wait data high err, %d\n", i);
            return -1;
        }

        udelay(50);

        // 读取一个bit
        if (get_level(dev) == 0) {
            sensor->recv_buf[j] = sensor->recv_buf[j] << 1;
        } else {
            sensor->recv_buf[j] = (sensor->recv_buf[j] << 1) | 1;
        }

        if (i % 8 == 7) {
            j++;
        }
    }

    /* 切换到输出模式,结束采集 */
    csi_gpio_pin_config(sensor->handle, GPIO_MODE_OPEN_DRAIN, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_write(sensor->handle, 1);

    return 0;
}

3.4 获取传感数据

注册传感器驱动后,应用可以调用传感器API来获取数据。以下是读取传感器的代码,实现在sensor_data.c中。

int get_sensor_value(char *name, int *temperature, int *humidity)
{
    dev_t *sensor_dev;
    sensor_dht11_t sval;
    int ret, i;

    /* 打开设备 */
    sensor_dev = sensor_open(name);
    if (sensor_dev == NULL) {
        LOGE(TAG, "no %s driver", name);
        return -1;
    }

    /* 采集数据 */
    for (i = 0; i < 3; i++) {
        ret = sensor_fetch(sensor_dev);

        if (ret == 0) {
            break;
        }

        LOGE(TAG, "retry");
        aos_msleep(50);
    }

    if (ret) {
        sensor_close(sensor_dev);
        return -1;
    }

    /* 读取数据 */
    if (sensor_getvalue(sensor_dev, (void *)&sval, sizeof(sensor_dht11_t)) < 0) {
        sensor_close(sensor_dev);
        return -1;
    }

    sensor_close(sensor_dev);

    /* 单位转化,传感框架规定温湿度单位是0.1 */
    *temperature = sval.degree / 10;
    *humidity = sval.rh / 10;

    return 0;
}
  • 烧写编译好的例程
  • 连接传感器 参考下图连接传感器和开发板引脚 img

  • 连接串口调试工具, 配置为 波特率: 115200, 数据位: 8, 校验位: None, 停止位: 1, 流控: None

  • 按RESET按键,复位开发板
boot1.1
Tee v2.0.1 Initliaze done, Dec 19 2018 11:44:54
Welcome to CLI...
> [     0.316347][I][app     ]dht11 sensor demo

[     2.345625][I][app     ]temperature=26 humidity=61
[    14.375363][I][app     ]temperature=26 humidity=62
[    26.405365][I][app     ]temperature=26 humidity=62
[    38.435363][I][app     ]temperature=26 humidity=62