查看: 5968|回复: 0

[原创] LPC54608 + HDC2010 + 环境温湿度监测

[复制链接]
  • TA的每日心情
    开心
    2024-3-12 16:11
  • 签到天数: 818 天

    连续签到: 1 天

    [LV.10]以坛为家III

    3

    主题

    860

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2759
    最后登录
    2025-5-22
    发表于 2019-10-25 23:13:30 | 显示全部楼层 |阅读模式
    本帖最后由 idiy 于 2019-11-13 16:44 编辑

    1.软件开发环境
    • IDE: MCUXPresso
    • SDK: MCUXPresso SDK
      • FreeRTOS
      • I2C 驱动
      • I2C FreeRTOS 驱动
      • USART 驱动
      • 调试接口
    2.硬件及连接
    • MCU: LPC54608
    • 温湿度传感器: HDC2010
    • 通信接口: I2C
      • MCU Flexcomm1
      • 通信速率: 100 kbps
    • Flexcomm0: 调试串口
    3.HDC2010 简单介绍

    HDC2010 集成了湿度和温度传感器,以极低的功耗提供了高精度的测量。其框图如下:

    hdc2010-block-diagram.png

    3.1 HDC2010 的 I2C 总线读写操作
    hdc2010-i2c-rdwr.png
    3.2 HDC2010 寄存器映射
    hdc2010-register-maps.png
    4.开发步骤
    4.1 创建开发环境
    • 下载安装 MCUXPresso
    • 注册 NXP 官网并下载 SDK
    • 安装 SDK

    4.2 基于 SDK 创建新的工程

    4.2.1 创建工程
    MCUXPresso-create-new-project.png
    4.2.2 选择开发板
    MCUXPresso-select-boards.png
    4.2.3 配置工程
    MCUXPresso-configure-project.png

    4.2.4 修改工程设置
    MCUXPresso-project-settings.png


    我要吐槽:基于 MCUXPresso SDK 生成的项目中如果有FreeRTOS组件,则FreeRTOS的配置文件中的一个宏需要修改一下,否则不能成功创建task并且运行。我经过设置断点跟踪到prot.c的355行,发现在这里configASSERT了。NXP会不会因为我发现的这个bug送给我一份神秘的礼物呢?
    port_c_355.png

    左边是例程工程配置,右边是自动生成工程的配置
    difference-demo-generate.png
    4.3 Flexcomm1引脚分配
    4.3.1 打开引脚配置工具
    MCUXPresso-pins-start.png

    4.3.2 使用引脚配置工具分配引脚并生成初始化代码
    MCUXPresso-pins-assign.png
    4.4 初始化
    4.4.1 Flexcomm1 硬件初始化
    flexcomm1-hw-init.png

    4.4.2 创建task
    1. void HDC2010_test(void)
    2. {
    3.     PRINTF("HDC2010_test start\n");
    4.     if (xTaskCreate(master_task, "Master_task", configMINIMAL_STACK_SIZE + 134, NULL, master_task_PRIORITY, NULL) !=
    5.         pdPASS)
    6.     {
    7.         PRINTF("Failed to create master task");
    8.         while (1)
    9.             ;
    10.     }
    11.     vTaskStartScheduler();
    12.     for (;;)
    13.         ;
    14. }
    复制代码

    4.4.3 HDC2010初始化
    4.4.3.1 主机 I2C 初始化
    1.     NVIC_SetPriority(EXAMPLE_I2C_MASTER_IRQ, I2C_NVIC_PRIO + 1);
    2.     EnableIRQ(EXAMPLE_I2C_MASTER_IRQ);

    3.     /*
    4.      * masterConfig.baudRate_Bps = 100000U;
    5.      * masterConfig.enableStopHold = false;
    6.      * masterConfig.glitchFilterWidth = 0U;
    7.      * masterConfig.enableMaster = true;
    8.      */
    9.     I2C_MasterGetDefaultConfig(&masterConfig);
    10.     masterConfig.baudRate_Bps = I2C_BAUDRATE;
    11.     sourceClock               = I2C_MASTER_CLOCK_FREQUENCY;

    12.     status = I2C_RTOS_Init(&master_rtos_handle, EXAMPLE_I2C_MASTER, &masterConfig, sourceClock);
    13.     if (status != kStatus_Success)
    14.     {
    15.         PRINTF("I2C master: error during init, %d", status);
    16.     }
    复制代码


    4.4.3.2 HDC2010_init()

    初始化从机 HDC2010 的地址。
    1. static int _addr;                                        // Address of sensor

    2. void HDC2010_init(uint8_t addr)
    3. {
    4.     _addr = addr;
    5. }
    复制代码


    4.4.3.3 HDC2010 配置
    1.     HDC2010_init(I2C_MASTER_SLAVE_ADDR_7BIT);
    2.     HDC2010_reset(&master_rtos_handle);
    3.     HDC2010_setHighTemp(&master_rtos_handle, 28);
    4.     HDC2010_setLowTemp(&master_rtos_handle, 22);
    5.     HDC2010_setHighHumidity(&master_rtos_handle, 55);
    6.     HDC2010_setLowHumidity(&master_rtos_handle, 44);
    7.     HDC2010_enableInterrupt(&master_rtos_handle);
    8.     HDC2010_enableThresholdInterrupt(&master_rtos_handle);
    9.     HDC2010_setInterruptPolarity(&master_rtos_handle, ACTIVE_HIGH);
    10.     HDC2010_setInterruptMode(&master_rtos_handle, COMPARATOR_MODE);
    11.     HDC2010_setMeasurementMode(&master_rtos_handle, TEMP_AND_HUMID);
    12.     HDC2010_setRate(&master_rtos_handle, ONE_HZ);
    13.     HDC2010_setTempRes(&master_rtos_handle, FOURTEEN_BIT);
    14.     HDC2010_setHumidRes(&master_rtos_handle, FOURTEEN_BIT);
    15.     HDC2010_triggerMeasurement(&master_rtos_handle);
    复制代码


    4.5 HDC2010驱动代码

    MUCXPresso SDK 提供了丰富的 I2C 驱动 API,有主机 API, 从机API, DMA API已经 FreeRTOS API。在这里,我采用了 主机 API 和 FreeRTOS API。FreeRTOS API及其简单,只有 3个 API:I2C_RTOS_Init(),I2C_RTOS_Deinit(),I2C_RTOS_Transfer()。在实际使用过程中,只用2个 API 就可以进行 I2C 传输操作了。没错,只要I2C_RTOS_Init() 和 I2C_RTOS_Transfer()就可以了。使用I2C_RTOS_Init() 初始化主机之后,每次数据传输只需要调用I2C_RTOS_Transfer()就可以了。

    再来看看 HDC 的读写操作,只有4种操作:单字节写,多字节写,单字节读,多字节读。利用FreeRTOS API可以轻易完成这4种操作。

    我给出软件复位和读取温度的操作,其余操作可模仿完成。关键的地方在于 HDC2010的寄存器的不同以及读取/写入数据的处理不同。


    4.5.1 软件复位

    1. /*  Bit 7 of the CONFIG register can be used to trigger a
    2.     soft reset  */
    3. void HDC2010_reset(i2c_rtos_handle_t *handle)
    4. {
    5.     i2c_master_transfer_t masterXfer;
    6.     uint8_t buff[4];
    7.     status_t status;

    8.     memset(&masterXfer, 0, sizeof(masterXfer));
    9.     masterXfer.slaveAddress   = _addr;
    10.     masterXfer.direction      = kI2C_Write;
    11.     masterXfer.subaddress     = 0;
    12.     masterXfer.subaddressSize = 0;
    13.     masterXfer.data           = buff;
    14.     masterXfer.dataSize       = 0;
    15.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    16.     buff[0] = CONFIG;
    17.     masterXfer.dataSize ++;

    18.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    19.     if (status != kStatus_Success)
    20.     {
    21.         PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
    22.     }

    23.     masterXfer.slaveAddress   = _addr;
    24.     masterXfer.direction      = kI2C_Read;
    25.     masterXfer.subaddress     = 0;
    26.     masterXfer.subaddressSize = 0;
    27.     masterXfer.data           = buff;
    28.     masterXfer.dataSize       = 1;
    29.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    30.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    31.     if (status != kStatus_Success)
    32.     {
    33.         PRINTF("%s() line=%d=>error during read transaction, %d\n", __func__, __LINE__, status);
    34.     }

    35.     buff[1] = (buff[0] | 0x80);
    36.     buff[0] = CONFIG;
    37.     memset(&masterXfer, 0, sizeof(masterXfer));
    38.     masterXfer.slaveAddress   = _addr;
    39.     masterXfer.direction      = kI2C_Write;
    40.     masterXfer.subaddress     = 0;
    41.     masterXfer.subaddressSize = 0;
    42.     masterXfer.data           = buff;
    43.     masterXfer.dataSize       = 2;
    44.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    45.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    46.     if (status != kStatus_Success)
    47.     {
    48.         PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
    49.     }

    50.     vTaskDelay(pdMS_TO_TICKS(50));
    51. }
    复制代码


    4.5.2 读取温度

    1. float HDC2010_readTemp(i2c_rtos_handle_t *handle)
    2. {
    3.     i2c_master_transfer_t masterXfer;
    4.     uint8_t buff[4];
    5.     status_t status;
    6.     uint8_t byte[2];
    7.     uint16_t temp;

    8.     memset(&masterXfer, 0, sizeof(masterXfer));
    9.     masterXfer.slaveAddress   = _addr;
    10.     masterXfer.direction      = kI2C_Write;
    11.     masterXfer.subaddress     = 0;
    12.     masterXfer.subaddressSize = 0;
    13.     masterXfer.data           = buff;
    14.     masterXfer.dataSize       = 0;
    15.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    16.     buff[0] = TEMP_LOW;
    17.     masterXfer.dataSize ++;

    18.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    19.     if (status != kStatus_Success)
    20.     {
    21.         PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
    22.     }

    23.     masterXfer.slaveAddress   = _addr;
    24.     masterXfer.direction      = kI2C_Read;
    25.     masterXfer.subaddress     = 0;
    26.     masterXfer.subaddressSize = 0;
    27.     masterXfer.data           = buff;
    28.     masterXfer.dataSize       = 1;
    29.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    30.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    31.     if (status != kStatus_Success)
    32.     {
    33.         PRINTF("%s() line=%d=>error during read transaction, %d\n", __func__, __LINE__, status);
    34.     }

    35.     byte[0] = buff[0];

    36.     memset(&masterXfer, 0, sizeof(masterXfer));
    37.     masterXfer.slaveAddress   = _addr;
    38.     masterXfer.direction      = kI2C_Write;
    39.     masterXfer.subaddress     = 0;
    40.     masterXfer.subaddressSize = 0;
    41.     masterXfer.data           = buff;
    42.     masterXfer.dataSize       = 0;
    43.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    44.     buff[0] = TEMP_HIGH;
    45.     masterXfer.dataSize ++;

    46.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    47.     if (status != kStatus_Success)
    48.     {
    49.         PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
    50.     }

    51.     masterXfer.slaveAddress   = _addr;
    52.     masterXfer.direction      = kI2C_Read;
    53.     masterXfer.subaddress     = 0;
    54.     masterXfer.subaddressSize = 0;
    55.     masterXfer.data           = buff;
    56.     masterXfer.dataSize       = 1;
    57.     masterXfer.flags          = kI2C_TransferDefaultFlag;

    58.     status = I2C_RTOS_Transfer(handle, &masterXfer);
    59.     if (status != kStatus_Success)
    60.     {
    61.         PRINTF("%s() line=%d=>error during read transaction, %d\n", __func__, __LINE__, status);
    62.     }

    63.     byte[1] = buff[0];

    64.     temp = (unsigned int)byte[1] << 8 | byte[0];

    65.     return (float)(temp)*165 / 65536 - 40;
    66. }
    复制代码


    4.6 主任务代码
    1. static void master_task(void *pvParameters)
    2. {
    3.     i2c_rtos_handle_t master_rtos_handle;
    4.     i2c_master_config_t masterConfig;
    5.     // i2c_master_transfer_t masterXfer;
    6.     uint32_t sourceClock;
    7.     status_t status;

    8.     PRINTF("master task start\n");

    9.     NVIC_SetPriority(EXAMPLE_I2C_MASTER_IRQ, I2C_NVIC_PRIO + 1);
    10.     EnableIRQ(EXAMPLE_I2C_MASTER_IRQ);

    11.     /*
    12.      * masterConfig.baudRate_Bps = 100000U;
    13.      * masterConfig.enableStopHold = false;
    14.      * masterConfig.glitchFilterWidth = 0U;
    15.      * masterConfig.enableMaster = true;
    16.      */
    17.     I2C_MasterGetDefaultConfig(&masterConfig);
    18.     masterConfig.baudRate_Bps = I2C_BAUDRATE;
    19.     sourceClock               = I2C_MASTER_CLOCK_FREQUENCY;

    20.     status = I2C_RTOS_Init(&master_rtos_handle, EXAMPLE_I2C_MASTER, &masterConfig, sourceClock);
    21.     if (status != kStatus_Success)
    22.     {
    23.         PRINTF("I2C master: error during init, %d", status);
    24.     }
    25.     PRINTF("I2C master init OK");
    26.     PRINTF("\r\n");

    27.     g_m_handle = &master_rtos_handle.drv_handle;

    28.     HDC2010_init(I2C_MASTER_SLAVE_ADDR_7BIT);
    29.     HDC2010_reset(&master_rtos_handle);
    30.     HDC2010_setHighTemp(&master_rtos_handle, 28);
    31.     HDC2010_setLowTemp(&master_rtos_handle, 22);
    32.     HDC2010_setHighHumidity(&master_rtos_handle, 55);
    33.     HDC2010_setLowHumidity(&master_rtos_handle, 44);
    34.     HDC2010_enableInterrupt(&master_rtos_handle);
    35.     HDC2010_enableThresholdInterrupt(&master_rtos_handle);
    36.     HDC2010_setInterruptPolarity(&master_rtos_handle, ACTIVE_HIGH);
    37.     HDC2010_setInterruptMode(&master_rtos_handle, COMPARATOR_MODE);
    38.     HDC2010_setMeasurementMode(&master_rtos_handle, TEMP_AND_HUMID);
    39.     HDC2010_setRate(&master_rtos_handle, ONE_HZ);
    40.     HDC2010_setTempRes(&master_rtos_handle, FOURTEEN_BIT);
    41.     HDC2010_setHumidRes(&master_rtos_handle, FOURTEEN_BIT);
    42.     HDC2010_triggerMeasurement(&master_rtos_handle);

    43.     while (true)
    44.     {
    45.         float t = HDC2010_readTemp(&master_rtos_handle);
    46.         float h = HDC2010_readHumidity(&master_rtos_handle);
    47.         PRINTF("%s() line=%d=>t=%.1f h=%.1f\n", __func__, __LINE__, t, h);
    48.         vTaskDelay(pdMS_TO_TICKS(1000));
    49.     }
    50.    
    51.     vTaskSuspend(NULL);
    52. }
    复制代码


    主任务进行如下循环操作,读取温度和湿度数据,并将读取到的数据打印到调试串口,休眠1秒钟。

    4.7 温湿度显示

    打开串口接收数据,如下:
    serial-terminal-show-temp-humid.png

    代码地址:http://github.com/iDiy/LPC54608J512_HDC2010
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-10-6 06:47 , Processed in 0.093971 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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