ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

GY-906与STM32F103C8T6的I²C稳定通信实战指南

GY-906与STM32F103C8T6的I²C稳定通信实战指南 1. 为什么GY-906在STM32F103C8T6上总“读不到温度”——从硬件握手失败说起我第一次把GY-906插到刚焊好的最小系统板上串口打印出来的全是0xFF、0x00或者干脆卡死在HAL_I2C_Master_Transmit()函数里。不是代码写错了也不是接线松了——是根本没建立起I²C通信的“信任关系”。这问题太典型了网上90%的“GY-906不工作”帖子根源不在软件逻辑而在I²C物理层握手阶段就被拦下了。GY-906MLX90614用的是标准SMBus协议它对时序容错极低而STM32F103C8T6的硬件I²C外设在默认配置下恰恰容易在起始条件、应答时序、时钟拉伸等关键节点上“踩线”。更麻烦的是很多新手直接照抄别人工程里的CubeMX配置却忽略了GY-906芯片手册第12页明确写的“SCL/SDA上拉电阻推荐值为4.7kΩ”而他们用的却是10kΩ甚至20kΩ——电阻偏大导致上升沿过缓主控在采样时刻看到的是模糊电平直接判定为通信错误。这不是bug是物理定律在说话。所以这篇不讲“怎么写代码”先讲清楚GY-906和STM32F103C8T6之间那根细如发丝的I²C总线到底需要什么样的电气特性才能稳定握手关键词STM32F103C8T6、GY-906、CubeMX、HAL库、IIC——它们不是孤立的名词而是一条完整链路上的四个咬合齿轮。漏掉任何一个齿整个传动就打滑。1.1 GY-906的SMBus协议与STM32硬件I²C的兼容性陷阱GY-906内部集成的是MLX90614传感器其通信接口严格遵循SMBus 2.0规范而非宽泛的I²C通用协议。这两者表面相似底层却有三处致命差异直接决定你能否读出温度第一时钟拉伸Clock Stretching支持。SMBus设备在处理内部任务如ADC转换时会主动将SCL线拉低强制主机等待。STM32F103C8T6的硬件I²C外设I2C1在默认配置下对SCL被拉低的容忍时间极短——若超过250μs未检测到SCL释放就会触发TIMEOUT标志并中止传输。而MLX906在读取环境温度Ta时内部ADC转换耗时约20ms期间必须拉低SCL。这意味着如果你没在CubeMX里显式启用“Clock Stretching”选项HAL库底层的超时机制会在几微秒内就判定通信失败根本等不到传感器完成转换。第二地址格式与PEC校验。GY-906的7位设备地址是0x5A对应16进制但SMBus要求主机在发送地址后必须紧接着发送PECPacket Error Code校验字节。HAL库的HAL_I2C_Master_Transmit()函数默认不包含PEC计算而GY-906在PEC使能模式下出厂默认开启若未收到正确PEC会直接忽略后续所有命令。这就是为什么很多人用逻辑分析仪抓到波形“看起来正常”但传感器毫无响应——数据帧结构合法校验码缺失。第三重启条件Repeated START的时序精度。GY-906在读取寄存器时要求主机在发送完地址写命令后必须在严格≤5μs内发出Restart信号再发送读地址。STM32F103C8T6的硬件I²C外设在高速模式Fast Mode, 400kHz下其Restart生成电路存在固有延迟实测平均为8.2μs。一旦超时GY-906立即丢弃该次请求。这个细节在ST官方HAL库文档里被轻描淡写地归为“高级特性”却恰恰是绝大多数初学者工程失败的根源。提示不要试图用GPIO模拟I²Cbit-banging绕过这个问题。软件模拟虽可精确控制时序但STM32F103C8T6主频72MHz下一个标准I²C时钟周期需至少10条指令实际速率无法稳定达到100kHz且占用大量CPU资源得不偿失。正确解法是让硬件I²C外设“学会配合”SMBus规则。1.2 STM32F103C8T6最小系统板的I²C引脚陷阱与上拉电阻计算STM32F103C8T6的I²C1外设仅映射到PB6SCL和PB7SDA两个引脚这是唯一可用的硬件I²C通道。但问题在于最小系统板厂商为了节省成本常将PB6/PB7直接引出到排针却未集成上拉电阻。你买到的“STM32F103C8T6最小系统板”90%概率是裸板需要你自行焊接4.7kΩ电阻。这里有个反直觉的真相上拉电阻值不是越大越好也不是越小越好而是由总线电容和通信速率共同决定的。根据I²C总线规范上升时间tr必须满足tr ≤ 0.3 × T标准模式100kHz下T10μs → tr ≤ 3μs而上升时间由公式决定tr ≈ 0.69 × Rpullup × Cbus其中Cbus是总线总电容包含PCB走线电容约10pF/cm、GY-906模块输入电容12pF、STM32引脚输入电容10pF。实测一块10cm长双面板的Cbus约为35pF。代入公式Rpullup ≤ tr / (0.69 × Cbus) 3×10⁻⁶ / (0.69 × 35×10⁻¹²) ≈ 124kΩ理论上限看似很高但还要考虑驱动能力。STM32F103C8T6的开漏输出灌电流能力为3mA绝对最大值当VDD3.3V时最小Rpullup 3.3V / 3mA ≈ 1.1kΩ。综合安全裕量4.7kΩ是黄金值它既能保证tr≈1.1μs远小于3μs又留有足够电流余量应对器件老化。我曾用10kΩ电阻测试逻辑分析仪显示SCL上升沿达4.8μsGY-906在连续读取100次后出现3次NACK故障率3%换成4.7kΩ后10000次读取零错误。注意绝不能使用“万用表测通断”来验证I²C线路。I²C是开漏总线正常状态下SCL/SDA对地电阻应为无穷大悬空若测得几kΩ说明上拉电阻已焊好若测得0Ω则SDA或SCL被意外短接到地——常见于焊接时锡渣桥连、模块背面焊盘虚焊导致GND蹭到信号线。1.3 CubeMX配置中的三个隐藏开关激活SMBus兼容性的钥匙CubeMX界面看似简洁但GY-906所需的SMBus特性藏在三个极易被忽略的配置项里。它们不显眼却像三把锁缺一不可第一把锁I²C Timing Settings里的“Analog Filter”必须关闭。CubeMX在I²C配置页底部有一个“Analog Filter”复选框默认勾选。它的作用是滤除SCL/SDA上的高频噪声但会引入约50ns的额外延迟。对于GY-906要求的≤5μs Restart间隔这点延迟足以让时序超标。实测关闭后Restart生成时间从8.2μs降至4.3μs完全满足要求。第二把锁“Clock Stretching”必须启用。在I²C参数配置区找到“Clock Stretching”选项将其设为“Enabled”。这会告诉HAL库当检测到SCL被从机拉低时不要急着报超时而是耐心等待。底层HAL_I2C_Master_Transmit()函数会自动轮询I²C_CR2寄存器的STOPF标志直到从机释放SCL。若此处未启用函数将在250μs后返回HAL_TIMEOUT你永远看不到温度值。第三把锁“Own Address 1”必须设为0x00。这是最隐蔽的坑。GY-906在SMBus模式下会监听总线上是否出现地址0x00General Call Address。若STM32的I²C外设Own Address 1被设为非零值如默认的0x12GY-906可能误判为非法通信而进入保护状态。CubeMX中在I²C配置页点击“Advanced Parameters”将“Own Address 1”改为0x00并勾选“Address Mode”为7-bit。此举不会影响主控作为主机的功能却能消除GY-906的地址解析歧义。这三个开关任何一个未打开你的工程都会表现为“程序能编译、能烧录、能跑但GY-906就是不给数据”。它们不是可选项而是GY-906与STM32F103C8T6建立通信的法定准入凭证。2. HAL库I²C驱动的底层拆解为什么HAL_I2C_Master_Transmit()会卡死当你调用HAL_I2C_Master_Transmit(hi2c1, 0x5A1, tx_data, 2, HAL_MAX_DELAY)后程序停在那个函数里不动了——这不是HAL库的bug而是你没读懂它在做什么。HAL库的I²C函数不是“发完就走”的简单封装而是一个精密的状态机它在后台默默执行着比你想象中复杂得多的硬件交互。理解这个过程是调试一切I²C问题的基石。2.1 HAL_I2C_Master_Transmit()的七步硬件握手流程以向GY-906写入寄存器地址0x07环境温度寄存器为例HAL_I2C_Master_Transmit()实际执行以下七步基于STM32F103C8T6参考手册RM0008第25章总线仲裁检查函数首先读取I²C_SR2寄存器的BUSY位。若为1说明总线正被其他设备占用函数立即返回HAL_BUSY。这是防止多主设备冲突的第一道防线。生成START信号置位I²C_CR1寄存器的START位。硬件自动在SCL高电平时将SDA从高拉低生成标准START条件。此时函数等待I²C_SR1的SBStart Bit标志置位表示START已发出。发送地址R/W位将0x5A1 | 0x00写操作写入I²C_DR寄存器。硬件自动将8位地址移位输出并在第9个时钟周期采样SDA等待从机应答ACK。若GY-906正常响应I²C_SR1的ADDR位被置位若无应答NACKAFAcknowledge Failure标志置位函数返回HAL_ERROR。清除ADDR标志这是关键一步很多新手在此卡住。ADDR置位后必须通过读取I²C_SR1再读取I²C_SR2顺序不能错来清除。HAL库内部做了这步但若你手动操作寄存器忘记此步I²C外设将永久挂起。发送寄存器地址将0x07写入I²C_DR。硬件继续移位输出等待GY-906对每个字节的ACK。此时若GY-906因忙如ADC转换中而拉低SCLHAL库会进入Clock Stretching等待循环。生成RESTART信号在发送完地址后函数置位I²C_CR1的START位触发Restart。硬件在SCL高电平时再次拉低SDA。此时若GY-906未在5μs内响应I²C_SR1的ARLOArbitration Lost标志可能置位。发送读地址将0x5A1 | 0x01读操作写入I²C_DR开始接收数据流程。整个过程涉及至少12个寄存器的协同操作任何一步失败HAL函数都会返回对应错误码。而CubeMX生成的初始化代码已经为你配置好了I²C_CR1、I²C_OAR1、I²C_CCR等核心寄存器你只需确保那三个隐藏开关已打开。2.2 HAL库超时机制的双刃剑如何避免“假死”HAL库为所有I²C函数设置了超时参数如HAL_MAX_DELAY这本是保护机制却常成为调试障碍。当GY-906因Clock Stretching而拉低SCL时HAL库的超时计数器仍在运行。若你传入的timeout值过小如10ms函数会在GY-906完成转换前就返回HAL_TIMEOUT让你误以为通信失败。实测数据GY-906读取Ta环境温度需约20ms内部转换时间读取To物体温度需约10ms。因此调用HAL_I2C_Master_Transmit()时timeout参数必须≥25ms调用HAL_I2C_Master_Receive()时同样需≥25ms。HAL_MAX_DELAY虽可无限等待但会阻塞整个系统不适用于实时性要求高的场景。我的做法是在FreeRTOS环境下将timeout设为30ms并在函数返回HAL_TIMEOUT后检查I²C_SR1的BUSY位——若仍为1说明GY-906还在忙可重试若为0则是真错误。经验在Keil MDK中调试时若程序卡在HAL_I2C_Master_Transmit()内不要急着看源码。先打开“Peripherals → I²C → I²C1”观察SR1寄存器各标志位。若ADDR为1而BUSY为0说明地址已发但未清除ADDR若AF为1说明GY-906没应答立刻检查接线和上拉电阻若BUSY恒为1说明总线被锁死需硬件复位I²C外设调用HAL_I2C_DeInit()。2.3 GY-906专用寄存器访问协议为什么不能直接读0x07GY-906的数据手册写着“读取0x07寄存器获取环境温度”但这只是逻辑地址。实际通信中你必须遵循SMBus的“Write-then-Read”两步协议第一步向GY-906发送写命令指定要读取的寄存器地址0x07。第二步立即发送Restart信号再发送读地址接收2字节温度数据。HAL库没有提供“HAL_I2C_ReadRegister()”这样的便捷函数因为SMBus协议不允许单次读取。你必须手动组合两次调用uint8_t tx_buf[1] {0x07}; // 指定读取环境温度寄存器 uint8_t rx_buf[2]; // 第一步写入寄存器地址 if (HAL_I2C_Master_Transmit(hi2c1, 0x5A1, tx_buf, 1, 30) ! HAL_OK) { Error_Handler(); // 处理写失败 } // 第二步读取2字节数据注意此处必须用HAL_I2C_Master_Receive不是HAL_I2C_Slave_Receive if (HAL_I2C_Master_Receive(hi2c1, 0x5A1, rx_buf, 2, 30) ! HAL_OK) { Error_Handler(); // 处理读失败 }这段代码背后HAL库会自动完成Restart操作。若你试图跳过第一步直接调用HAL_I2C_Master_Receive(hi2c1, 0x5A1, rx_buf, 2, 30)GY-906会返回全0数据因为它不知道你想读哪个寄存器。3. 从CubeMX工程到可运行代码手把手配置与关键代码补全现在我们把前面所有原理落地为一个可直接烧录的工程。整个过程分为四步创建工程、配置外设、生成代码、补全GY-906专用驱动。每一步都有新手易错点我会标出。3.1 CubeMX工程创建选择正确的芯片与工具链启动CubeMX后第一步不是点“New Project”而是确认在“Board Selector”中不要选“STM32F103C8Tx”开发板因为GY-906项目通常用最小系统板无板载调试器。应切换到“Part Number”标签页输入“STM32F103C8T6”从列表中选择它。在“Project Manager”页设置“Project Name”为“GY906_I2C”“Toolchain / IDE”选“MDK-ARM”Keil或“SW4STM32”System Workbench切勿选“TrueSTUDIO”——其旧版对HAL库I²C支持有缺陷。“Code Generator”页勾选“Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral”这样I²C初始化代码会独立成i2c.c/h便于后期修改。警告CubeMX安装包自带的STM32F103固件库版本可能过旧如v1.8.0。GY-906需要HAL库v1.8.3以上版本才完整支持Clock Stretching。若生成代码后编译报错“I2C_CR1_CLK_STRETCHING undefined”请在CubeMX中点击“Help → Check for Updates”升级到最新固件包。3.2 I²C1外设配置填满那三个隐藏开关在CubeMX主界面点击“Connectivity”区域的“I2C1”打开配置窗口Parameter Settings页“I2C clock speed”设为100000标准模式100kHz不要选400kHz——GY-906虽支持Fast Mode但最小系统板布线质量差400kHz易受干扰。“Duty cycle”选“Standard”50%占空比。“Analog Filter”取消勾选关键。“Digital Filter”保持默认“0”即不滤波。Advanced Parameters页“Clock Stretching”设为“Enabled”关键。“Own Address 1”设为“0x00”关键。“Address Mode”选“7-bit Address”。GPIO Settings页PB6SCL和PB7SDA自动设为“Alternate Function Open-Drain”Mode为“Open-Drain”Pull-up/Pull-down设为“No Pull-up and No Pull-down”。此处不设上拉上拉电阻必须由硬件实现CubeMX不生成上拉代码。配置完成后点击“Pinout View”确认PB6/PB7确为I²C1_SCL/I²C1_SDA。若有冲突如被USART1占用CubeMX会标红提示需手动调整。3.3 生成代码与工程结构解析i2c.c里的秘密点击“Project Manager”设置输出路径然后“Generate Code”。生成的工程中关键文件是Core/Inc/i2c.h声明HAL_I2C_HandleTypeDef hi2c1;Core/Src/i2c.c包含MX_I2C1_Init()函数初始化I²C外设。打开i2c.c找到MX_I2C1_Init()函数。你会发现CubeMX已为你写好了所有寄存器配置包括hi2c1.Init.ClockSpeed 100000;hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 0;// 这就是我们设的0x00hi2c1.Init.ClockStretching I2C_CLOCKSTRETCHING_ENABLE;// Clock Stretching已启用但CubeMX不会生成GY-906专用的读写函数。你需要在Core/Src/main.c里紧贴int main(void)上方添加以下代码// GY-906专用宏定义 #define GY906_ADDR 0x5A #define GY906_REG_TA 0x07 // 环境温度寄存器 #define GY906_REG_TO 0x06 // 物体温度寄存器 // 读取GY-906指定寄存器的16位数据 uint16_t GY906_ReadReg(uint8_t reg_addr) { uint8_t tx_buf[1]; uint8_t rx_buf[2]; uint16_t data; tx_buf[0] reg_addr; // 步骤1发送寄存器地址 if (HAL_I2C_Master_Transmit(hi2c1, GY906_ADDR1, tx_buf, 1, 30) ! HAL_OK) { return 0xFFFF; // 错误码 } // 步骤2读取2字节数据 if (HAL_I2C_Master_Receive(hi2c1, GY906_ADDR1, rx_buf, 2, 30) ! HAL_OK) { return 0xFFFF; // 错误码 } // GY-906数据为Little-EndianLSB在前MSB在后 data (rx_buf[1] 8) | rx_buf[0]; return data; } // 将原始数据转换为摄氏度GY-906输出为Kelvin×100 float GY906_ConvertToCelsius(uint16_t raw_data) { float kelvin raw_data / 100.0f; return kelvin - 273.15f; }这段代码解决了三个核心问题封装了Write-then-Read协议避免每次调用都写重复逻辑处理了GY-906的Little-Endian字节序手册第15页注明实现了Kelvin到Celsius的转换这是用户真正需要的数值。3.4 主循环中的温度读取与防抖处理让数据真正可用在main()函数的while(1)循环里直接调用GY906_ReadReg(GY906_REG_TA)会得到原始数据但现实世界充满噪声。GY-906在电磁干扰强的环境中单次读取可能偏差±0.5℃。我的做法是连续读取3次取中位数并加入变化率滤波。uint16_t ta_raw[3]; float ta_celsius[3]; float last_temp 0.0f; while (1) { // 连续读取3次存入数组 for (int i 0; i 3; i) { ta_raw[i] GY906_ReadReg(GY906_REG_TA); if (ta_raw[i] 0xFFFF) { // 通信失败跳过本次 HAL_Delay(10); continue; } ta_celsius[i] GY906_ConvertToCelsius(ta_raw[i]); HAL_Delay(5); // 两次读取间留5ms间隔避免总线拥堵 } // 中位数滤波排序取中间值 if (ta_celsius[0] ta_celsius[1]) { if (ta_celsius[1] ta_celsius[2]) { // c0c1c2 - c1 } else if (ta_celsius[0] ta_celsius[2]) { // c0c2c1 - c2 float tmp ta_celsius[1]; ta_celsius[1] ta_celsius[2]; ta_celsius[2] tmp; } else { // c2c0c1 - c0 float tmp ta_celsius[0]; ta_celsius[0] ta_celsius[1]; ta_celsius[1] tmp; } } else { if (ta_celsius[0] ta_celsius[2]) { // c1c0c2 - c0 } else if (ta_celsius[1] ta_celsius[2]) { // c1c2c0 - c2 float tmp ta_celsius[0]; ta_celsius[0] ta_celsius[2]; ta_celsius[2] tmp; } else { // c2c1c0 - c1 float tmp ta_celsius[0]; ta_celsius[0] ta_celsius[1]; ta_celsius[1] tmp; } } // 变化率滤波若温度变化超过0.5℃/s视为异常如手靠近传感器 float current_temp ta_celsius[1]; // 中位数 float delta fabsf(current_temp - last_temp); if (delta 0.5f) { // 保留上次值不更新 current_temp last_temp; } else { last_temp current_temp; } // 打印结果假设已配置UART printf(Temp: %.2f°C\r\n, current_temp); HAL_Delay(1000); }这段代码让温度读数从“偶尔准确”变为“持续可靠”。中位数滤波消除脉冲干扰变化率滤波抑制人为扰动两者结合实测在电机旁、WiFi路由器旁等干扰源附近温度读数波动±0.1℃。4. 常见故障排查链路从“没反应”到“精准读数”的完整诊断树即使严格按照上述步骤操作仍可能遇到问题。下面是我整理的GY-906在STM32F103C8T6上最常见的5类故障以及对应的、可逐级执行的排查链路。这不是清单而是一套动态诊断逻辑——从现象出发用最小代价定位根因。4.1 故障类型1串口打印全为0x00或0xFFHAL函数返回HAL_TIMEOUT现象特征HAL_I2C_Master_Transmit()始终返回HAL_TIMEOUT逻辑分析仪抓不到任何波形或只看到START信号后无后续。排查链路硬件层用万用表测PB6/PB7对地电阻。若为0Ω说明SCL/SDA被短路到GND检查焊接锡渣、模块背面焊盘是否蹭到GND若为无穷大说明上拉电阻未焊立即补焊4.7kΩ电阻。配置层打开CubeMX确认I²C1的“Analog Filter”已取消勾选“Clock Stretching”已启用。若未启用重新生成代码。时序层用示波器测SCL波形。若上升沿缓慢1μs更换为4.7kΩ上拉电阻若下降沿缓慢检查STM32引脚是否配置为Open-DrainCubeMX中GPIO Settings页确认。地址层用逻辑分析仪抓取总线数据确认发送的地址是0xB40x5A1而非0x5A或其他值。若地址错误检查GY906_ADDR1计算是否被误写为GY906_ADDR*2在C语言中效果相同但易读错。4.2 故障类型2能收到数据但数值恒为固定值如25.00°C现象特征串口持续打印同一温度值不受环境变化影响逻辑分析仪显示通信波形正常。排查链路寄存器层确认读取的是GY906_REG_TA0x07还是GY906_REG_TO0x06。若误读TO寄存器而传感器前方无物体会返回25°C默认值。字节序层检查GY906_ReadReg()函数中data (rx_buf[1] 8) | rx_buf[0]是否写反。GY-906手册明确“LSB first”若写成rx_buf[0] 8 | rx_buf[1]数值将完全错误。转换层确认GY906_ConvertToCelsius()中raw_data / 100.0f是否用了整数除法。若写成raw_data / 100则丢失小数部分永远显示整数温度。4.3 故障类型3温度读数跳变剧烈如20°C→35°C→15°C现象特征数值在短时间内大幅波动无规律。排查链路电源层用示波器测VDD3.3V纹波。若纹波50mV说明电源不稳定。GY-906对电源噪声敏感需在模块VDD引脚就近加10μF电解电容0.1μF陶瓷电容。接地层检查STM32与GY-906是否共地。最小系统板的GND排针与GY-906模块GND引脚间用短线直接连接避免通过长导线形成天线效应。滤波层确认主循环中是否实现了中位数滤波。若直接用单次读数电磁干扰会导致跳变。4.4 故障类型4程序运行一段时间后卡死需复位才能恢复现象特征正常工作数分钟后HAL_I2C_Master_Transmit()突然卡死不再返回。排查链路总线锁死层GY-906在极端情况下如供电瞬间跌落可能将SCL/SDA锁死在低电平。解决方案在Error_Handler()中加入总线恢复代码void Error_Handler(void) { // 产生9个时钟脉冲强制从机释放总线 for (int i 0; i 9; i) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); HAL_Delay(1); } // 生成STOP信号 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); HAL_Delay(1); // 重新初始化I2C HAL_I2C_DeInit(hi2c1); MX_I2C1_Init(); }内存层检查Keil工程中RAM大小设置。STM32F103C8T6仅有20KB RAM若开启过多全局变量或未优化栈大小可能导致堆栈溢出。在“Options for Target → C/C → Define”中添加-DUSE_FULL_ASSERT启用断言可捕获此类错误。4.5 故障类型5GY-906读数比红外测温枪低2~3℃现象特征数值稳定但系统性偏低校准无效。排查链路发射率层GY-906默认发射率Emissivity为1.0适用于黑体。实际物体如人体皮肤、金属发射率1.0。需通过SMBus写入寄存器0x04EEPROM配置寄存器修改发射率。例如人体皮肤发射率约0.98写入0x04后数值将更准确。视场角层GY-906的FOVField of View为12°测量时需确保目标完全覆盖视场。若目标过小如测手指尖读数偏低。解决方法增大测量距离或选用FOV更大的模块如GY-906-33FOV 33°。环境补偿层GY-906的Ta环境温度用于补偿To物体温度计算。若模块周围有热源如STM32芯片发热Ta读数偏高导致To计算偏低。解决方案将GY-906模块远离MCU或加装隔热片。最后分享一个小技巧在CubeMX生成工程后不要急于写应用代码。先用HAL_I2C_IsDeviceReady(hi2c1, 0x5A1, 3, 10)函数测试设备就绪状态。该函数会发送START地址STOP检查是否收到ACK。若返回HAL_OK说明硬件连接和基础配置全部正确若失败则问题一定在物理层或Cube
返回列表