在线时间212 小时
UID3467032
注册时间2018-4-10
NXP金币36
TA的每日心情 | 开心 2024-3-12 16:11 |
---|
签到天数: 818 天 连续签到: 1 天 [LV.10]以坛为家III
金牌会员
 
- 积分
- 2759
- 最后登录
- 2025-5-22
|
本帖最后由 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 集成了湿度和温度传感器,以极低的功耗提供了高精度的测量。其框图如下:
3.1 HDC2010 的 I2C 总线读写操作
3.2 HDC2010 寄存器映射
4.开发步骤
4.1 创建开发环境- 下载安装 MCUXPresso
- 注册 NXP 官网并下载 SDK
- 安装 SDK
4.2 基于 SDK 创建新的工程
4.2.1 创建工程
4.2.2 选择开发板
4.2.3 配置工程
4.2.4 修改工程设置
我要吐槽:基于 MCUXPresso SDK 生成的项目中如果有FreeRTOS组件,则FreeRTOS的配置文件中的一个宏需要修改一下,否则不能成功创建task并且运行。我经过设置断点跟踪到prot.c的355行,发现在这里configASSERT了。NXP会不会因为我发现的这个bug送给我一份神秘的礼物呢?
左边是例程工程配置,右边是自动生成工程的配置
4.3 Flexcomm1引脚分配
4.3.1 打开引脚配置工具
4.3.2 使用引脚配置工具分配引脚并生成初始化代码
4.4 初始化
4.4.1 Flexcomm1 硬件初始化
4.4.2 创建task
- void HDC2010_test(void)
- {
- PRINTF("HDC2010_test start\n");
- if (xTaskCreate(master_task, "Master_task", configMINIMAL_STACK_SIZE + 134, NULL, master_task_PRIORITY, NULL) !=
- pdPASS)
- {
- PRINTF("Failed to create master task");
- while (1)
- ;
- }
- vTaskStartScheduler();
- for (;;)
- ;
- }
复制代码
4.4.3 HDC2010初始化
4.4.3.1 主机 I2C 初始化
- NVIC_SetPriority(EXAMPLE_I2C_MASTER_IRQ, I2C_NVIC_PRIO + 1);
- EnableIRQ(EXAMPLE_I2C_MASTER_IRQ);
- /*
- * masterConfig.baudRate_Bps = 100000U;
- * masterConfig.enableStopHold = false;
- * masterConfig.glitchFilterWidth = 0U;
- * masterConfig.enableMaster = true;
- */
- I2C_MasterGetDefaultConfig(&masterConfig);
- masterConfig.baudRate_Bps = I2C_BAUDRATE;
- sourceClock = I2C_MASTER_CLOCK_FREQUENCY;
- status = I2C_RTOS_Init(&master_rtos_handle, EXAMPLE_I2C_MASTER, &masterConfig, sourceClock);
- if (status != kStatus_Success)
- {
- PRINTF("I2C master: error during init, %d", status);
- }
复制代码
4.4.3.2 HDC2010_init()
初始化从机 HDC2010 的地址。
- static int _addr; // Address of sensor
- void HDC2010_init(uint8_t addr)
- {
- _addr = addr;
- }
复制代码
4.4.3.3 HDC2010 配置
- HDC2010_init(I2C_MASTER_SLAVE_ADDR_7BIT);
- HDC2010_reset(&master_rtos_handle);
- HDC2010_setHighTemp(&master_rtos_handle, 28);
- HDC2010_setLowTemp(&master_rtos_handle, 22);
- HDC2010_setHighHumidity(&master_rtos_handle, 55);
- HDC2010_setLowHumidity(&master_rtos_handle, 44);
- HDC2010_enableInterrupt(&master_rtos_handle);
- HDC2010_enableThresholdInterrupt(&master_rtos_handle);
- HDC2010_setInterruptPolarity(&master_rtos_handle, ACTIVE_HIGH);
- HDC2010_setInterruptMode(&master_rtos_handle, COMPARATOR_MODE);
- HDC2010_setMeasurementMode(&master_rtos_handle, TEMP_AND_HUMID);
- HDC2010_setRate(&master_rtos_handle, ONE_HZ);
- HDC2010_setTempRes(&master_rtos_handle, FOURTEEN_BIT);
- HDC2010_setHumidRes(&master_rtos_handle, FOURTEEN_BIT);
- 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 软件复位
- /* Bit 7 of the CONFIG register can be used to trigger a
- soft reset */
- void HDC2010_reset(i2c_rtos_handle_t *handle)
- {
- i2c_master_transfer_t masterXfer;
- uint8_t buff[4];
- status_t status;
- memset(&masterXfer, 0, sizeof(masterXfer));
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Write;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 0;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- buff[0] = CONFIG;
- masterXfer.dataSize ++;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
- }
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Read;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 1;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during read transaction, %d\n", __func__, __LINE__, status);
- }
- buff[1] = (buff[0] | 0x80);
- buff[0] = CONFIG;
- memset(&masterXfer, 0, sizeof(masterXfer));
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Write;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 2;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
- }
- vTaskDelay(pdMS_TO_TICKS(50));
- }
复制代码
4.5.2 读取温度
- float HDC2010_readTemp(i2c_rtos_handle_t *handle)
- {
- i2c_master_transfer_t masterXfer;
- uint8_t buff[4];
- status_t status;
- uint8_t byte[2];
- uint16_t temp;
- memset(&masterXfer, 0, sizeof(masterXfer));
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Write;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 0;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- buff[0] = TEMP_LOW;
- masterXfer.dataSize ++;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
- }
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Read;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 1;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during read transaction, %d\n", __func__, __LINE__, status);
- }
- byte[0] = buff[0];
- memset(&masterXfer, 0, sizeof(masterXfer));
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Write;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 0;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- buff[0] = TEMP_HIGH;
- masterXfer.dataSize ++;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during write transaction, %d\n", __func__, __LINE__, status);
- }
- masterXfer.slaveAddress = _addr;
- masterXfer.direction = kI2C_Read;
- masterXfer.subaddress = 0;
- masterXfer.subaddressSize = 0;
- masterXfer.data = buff;
- masterXfer.dataSize = 1;
- masterXfer.flags = kI2C_TransferDefaultFlag;
- status = I2C_RTOS_Transfer(handle, &masterXfer);
- if (status != kStatus_Success)
- {
- PRINTF("%s() line=%d=>error during read transaction, %d\n", __func__, __LINE__, status);
- }
- byte[1] = buff[0];
- temp = (unsigned int)byte[1] << 8 | byte[0];
- return (float)(temp)*165 / 65536 - 40;
- }
复制代码
4.6 主任务代码
- static void master_task(void *pvParameters)
- {
- i2c_rtos_handle_t master_rtos_handle;
- i2c_master_config_t masterConfig;
- // i2c_master_transfer_t masterXfer;
- uint32_t sourceClock;
- status_t status;
- PRINTF("master task start\n");
- NVIC_SetPriority(EXAMPLE_I2C_MASTER_IRQ, I2C_NVIC_PRIO + 1);
- EnableIRQ(EXAMPLE_I2C_MASTER_IRQ);
- /*
- * masterConfig.baudRate_Bps = 100000U;
- * masterConfig.enableStopHold = false;
- * masterConfig.glitchFilterWidth = 0U;
- * masterConfig.enableMaster = true;
- */
- I2C_MasterGetDefaultConfig(&masterConfig);
- masterConfig.baudRate_Bps = I2C_BAUDRATE;
- sourceClock = I2C_MASTER_CLOCK_FREQUENCY;
- status = I2C_RTOS_Init(&master_rtos_handle, EXAMPLE_I2C_MASTER, &masterConfig, sourceClock);
- if (status != kStatus_Success)
- {
- PRINTF("I2C master: error during init, %d", status);
- }
- PRINTF("I2C master init OK");
- PRINTF("\r\n");
- g_m_handle = &master_rtos_handle.drv_handle;
- HDC2010_init(I2C_MASTER_SLAVE_ADDR_7BIT);
- HDC2010_reset(&master_rtos_handle);
- HDC2010_setHighTemp(&master_rtos_handle, 28);
- HDC2010_setLowTemp(&master_rtos_handle, 22);
- HDC2010_setHighHumidity(&master_rtos_handle, 55);
- HDC2010_setLowHumidity(&master_rtos_handle, 44);
- HDC2010_enableInterrupt(&master_rtos_handle);
- HDC2010_enableThresholdInterrupt(&master_rtos_handle);
- HDC2010_setInterruptPolarity(&master_rtos_handle, ACTIVE_HIGH);
- HDC2010_setInterruptMode(&master_rtos_handle, COMPARATOR_MODE);
- HDC2010_setMeasurementMode(&master_rtos_handle, TEMP_AND_HUMID);
- HDC2010_setRate(&master_rtos_handle, ONE_HZ);
- HDC2010_setTempRes(&master_rtos_handle, FOURTEEN_BIT);
- HDC2010_setHumidRes(&master_rtos_handle, FOURTEEN_BIT);
- HDC2010_triggerMeasurement(&master_rtos_handle);
- while (true)
- {
- float t = HDC2010_readTemp(&master_rtos_handle);
- float h = HDC2010_readHumidity(&master_rtos_handle);
- PRINTF("%s() line=%d=>t=%.1f h=%.1f\n", __func__, __LINE__, t, h);
- vTaskDelay(pdMS_TO_TICKS(1000));
- }
-
- vTaskSuspend(NULL);
- }
复制代码
主任务进行如下循环操作,读取温度和湿度数据,并将读取到的数据打印到调试串口,休眠1秒钟。
4.7 温湿度显示
打开串口接收数据,如下:
代码地址:http://github.com/iDiy/LPC54608J512_HDC2010
|
|