Funpack5-4 -基于FRDM-MCXN236实现环境数据采集与显示
项目介绍
基于 FRDM-MCXN236 开发板,连接 I2C 传感器,实现环境数据采集与实时显示。
功能要求:
通过 I2C 读取传感器数据
周期性采集环境信息
通过串口输出采集结果
使用 LED 指示系统运行状态
数据刷新周期不大于1秒
简短的所有使用到的硬件介绍

核心部件:FRDM-MCXN236 开发板(串口+ RGB LED灯)+ I2C温湿度传感器(AHT20)
FRDM-MCXN236开发板:FRDM-MCXN236 是恩智浦(NXP)推出的一款紧凑型、可扩展的高性价比开发板,专为基于 MCX N23x 系列微控制器的快速原型设计而打造。该开发板的核心是一颗 MCX N236 微控制器,搭载 Arm Cortex-M33 内核,主频最高可达 150 MHz,配备 1MB 双组闪存(支持完整 ECC RAM)和 352KB ECC RAM,并集成 SmartDMA 加速器,能够高效地将工作负载分配到模拟与数字外设上。
AHT20温湿度传感器:AHT20 是奥松电子推出的高精度电容式数字温湿度传感器,采用 I2C 通信接口,7 位从机地址为 0x38,内置 20 位 ADC,湿度测量范围 0~100% RH,典型精度 ±2% RH,温度测量范围 - 40~85℃,25℃下典型精度 ±0.3℃;传感器上电后需执行一次校准初始化,发送测量命令后约 75ms 完成一次采集,可通过状态字节 bit7 判断是否测量完成,读取 6 字节原始数据后经公式换算得到温湿度,自带 CRC8 校验,供电电压 2.0~5.5V,功耗低,适合智能家居、室内环境监测等场景。
方案框图和项目设计思路介绍

设计思路介绍:使用FRDM-MCXN236官方例程lpi2c_polling_b2b_master,核心是使用LPI2C模块,MCU作为主机,读取从机(温湿度传感器)的数据。
如果在读取过程中发生错误,则亮板载红灯,如果没有错误就亮红灯。
调试软件介绍、软件流程图及关键代码介绍
本项目使用NXP的官方IDE: MCUXpresso IDE
软件流程图:

关键代码介绍
核心代码是读取温湿度原始数据,并通过移位运算、数据拼接等运算转换成实际读值。
* @note AHT20返回6字节数据排布:
* buf[0] : 状态字节
* buf[1] : 湿度 [19:12]
* buf[2] : 湿度 [11:4]
* buf[3] : 湿度 [3:0] | 温度 [19:16]
* buf[4] : 温度 [15:8]
* buf[5] : 温度 [7:0]
status_t AHT20_ReadTH(uint8_t *rxBuf, uint32_t *hum, uint32_t *temp)
{
status_t reVal;
/* 读取AHT20的6字节原始数据到外部传入buffer */
reVal = AHT20_ReadData(rxBuf, 6);
if (reVal != kStatus_Success)
{
return reVal;
}
/* 拼接20bit湿度原始值 */
*hum = ((uint32_t)rxBuf[1] << 12) |
((uint32_t)rxBuf[2] << 4) |
(rxBuf[3] >> 4);
/* 拼接20bit温度原始值 */
*temp = ((uint32_t)(rxBuf[3] & 0x0F) << 16) |
((uint32_t)rxBuf[4] << 8) |
rxBuf[5];
return kStatus_Success;
}
上面获得的温湿度原始数据还不是最终显示的温湿度,还需要进行换算,最后通过PRINTF函数,格式化输出。
* AHT20计算公式:
* RH(%) = raw_hum / 2^20 * 100%
* T(℃) = raw_temp / 2^20 * 200 - 50
* 使用uint64_t防止乘法溢出,结果放大100倍保留小数点后两位
*/
hum_x100 = ( (uint64_t)raw_hum * 10000UL ) / 0x100000UL;
temp_x100 = (int32_t)( ((uint64_t)raw_temp * 20000UL ) / 0x100000UL ) - 5000;
/* 串口打印,拆分整数部分和小数部分 */
PRINTF("RH: %d.%02d %%RH, Temp: %d.%02d C\r\n",
hum_x100 / 100, hum_x100 % 100,
temp_x100 / 100, temp_x100 % 100);
另外,项目的一个重要功能,是使用 LED 指示系统运行状态。
在while(1)函数中,有3个位置需获取程序运行结果,如果返回结果是失败的,则亮红灯、灭绿灯,如果返回结果是正常的,则亮绿灯、灭红灯。
第1个位置:获取触发测量的执行状态
/* 1. 发送测量命令,触发AHT20进行一次AD转换 */
reVal = AHT20_TriggerMeasure();
if (reVal != kStatus_Success)
{
PRINTF("Send Measure Cmd Fail:%d\r\n", reVal);
SDK_DelayAtLeastUs(1000000, SystemCoreClock);
GPIO_PortClear(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN_MASK);
GPIO_PortSet(BOARD_INITPINS_LED_GREEN_GPIO, BOARD_INITPINS_LED_GREEN_PIN_MASK);
continue;
}
else
{
GPIO_PortSet(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN_MASK);
GPIO_PortClear(BOARD_INITPINS_LED_GREEN_GPIO, BOARD_INITPINS_LED_GREEN_PIN_MASK);
}
第2个位置:等待传感器空闲就绪的状态
reVal = AHT20_WaitReady(100);
if (reVal != kStatus_Success)
{
PRINTF("AHT20 Measure Timeout!\r\n");
SDK_DelayAtLeastUs(1000000, SystemCoreClock);
GPIO_PortClear(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN_MASK);
GPIO_PortSet(BOARD_INITPINS_LED_GREEN_GPIO, BOARD_INITPINS_LED_GREEN_PIN_MASK);
continue;
}
else
{
GPIO_PortSet(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN_MASK);
GPIO_PortClear(BOARD_INITPINS_LED_GREEN_GPIO, BOARD_INITPINS_LED_GREEN_PIN_MASK);
}
第3个位置:读取并解析原始数据的状态
reVal = AHT20_ReadTH(rxBuf, &raw_hum, &raw_temp);
if (reVal != kStatus_Success)
{
PRINTF("Read AHT20 Data Fail:%d\r\n", reVal);
SDK_DelayAtLeastUs(1000000, SystemCoreClock);
GPIO_PortClear(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN_MASK);
GPIO_PortSet(BOARD_INITPINS_LED_GREEN_GPIO, BOARD_INITPINS_LED_GREEN_PIN_MASK);
continue;
}
else
{
GPIO_PortSet(BOARD_INITPINS_LED_RED_GPIO, BOARD_INITPINS_LED_RED_PIN_MASK);
GPIO_PortClear(BOARD_INITPINS_LED_GREEN_GPIO, BOARD_INITPINS_LED_GREEN_PIN_MASK);
}
功能展示图及说明
程序正常运行,上位机串口每秒收到温湿度数据:
RH: 83.13 %RH, Temp: 27.45 C

对应的,板载RGB LED灯绿灯亮。

如果这时拔掉SDA信号线,板载RGB LED灯红灯亮,同时串口输出报错信息。

项目中遇到的难题及解决方法:无。
心得体会:
本项目是典型的MCU通过通信总线(IIC)采集传感器信号,经过运算处理,将结果通过通信总线(UART)输出到上位机的项目,同时正常亮绿灯,出错亮红灯。
通过本项目,我掌握了基本的IIC通信技巧,并实现完整项目逻辑。