踩坑记录:我们遇到的那些邪门问题与解决方案

举报
JN-liu 发表于 2026/04/30 21:57:27 2026/04/30
【摘要】 上篇回顾:我们抱着设备走进三间教室,连续监测了五场2小时的课。数据证明趋势预警确实有效——VENTIL总在MUGGY!前20到40分钟出现。但说出来你可能不信,这台机器在诞生过程中,差点被三个邪门问题逼到绝路。今天不讲成功学,只讲我们是怎么掉坑里、又是怎么爬出来的。坑一:AM2320的“起床气”现象程序写好,烧录,上电。LCD亮了,但第二行显示的不是温湿度数值,而是两个巨大的感叹号——“!!...

上篇回顾:我们抱着设备走进三间教室,连续监测了五场2小时的课。数据证明趋势预警确实有效——VENTIL总在MUGGY!前20到40分钟出现。但说出来你可能不信,这台机器在诞生过程中,差点被三个邪门问题逼到绝路。今天不讲成功学,只讲我们是怎么掉坑里、又是怎么爬出来的。

坑一:AM2320的“起床气”

现象

程序写好,烧录,上电。LCD亮了,但第二行显示的不是温湿度数值,而是两个巨大的感叹号——“!!”。

我们检查了接线,没问题。检查了代码逻辑,没问题。重新上电,依然是“!!”。偶尔会正常显示一组数据,然后下一轮又变“!!”。

这就很诡异了。传感器分明连着,供电也正常,为什么它时灵时不灵?

排查

翻AM2320的数据手册(说实话,这是整个项目中我们翻得最仔细的一份文档),找到了一段容易被忽略的描述:

“传感器在完成一次测量后会自动进入休眠状态,需由主机发送起始信号唤醒。”

原来如此。AM2320是个“节能主义者”,每次干完活就倒头睡觉。我们第一次读取数据时,传感器还醒着,所以读到了正确的数值;但读完之后它睡着了,而我们的程序没有做唤醒动作,直接发起下一次读取——传感器根本没理我们,返回了错误码,于是显示“!!”。

解决

很简单:每次读取数据前,先发I2C起始信号,然后等2毫秒

void wake_AM2320() {
    I2C_Start();           // 发送起始信号
    I2C_SendByte(0xB8);    // 发送器件地址
    delay_ms(2);           // 留2ms让传感器苏醒并完成测量
}

这2毫秒是给传感器从休眠中爬起来、完成内部测量的时间。加上之后,传感器再也没有闹过“起床气”,“!!”彻底消失。

教训

读数据手册时,别只盯着电气参数和通信时序看,“工作模式”和“功耗管理”这类看似软性的内容,往往藏着最大的坑。传感器的省电策略,恰恰可能成为实时监测系统最大的绊脚石。


坑二:单片机“精神分裂”,LCD显示乱码

现象

第二个坑出现在一次烧录之后。上电后LCD显示的不是我们设定的“T:--.-C H:--.-%”,而是一堆乱码——有的字符在闪烁,有的完全认不出,整体就像一台坏掉的电子表。

我们第一反应:代码写错了。于是改代码,重新编译,重新烧录。乱码依旧。

再改,再烧,还是乱码。前后烧了四五次,每次修改不同的初始化时序和延时参数,毫无改善。有人开始怀疑是LCD1602本身坏了——毕竟这玩意娇贵,静电都能打坏。

排查

用万用表测LCD各个引脚的电压。对比度调节脚正常,背光正常,但数据脚上的电压一直在小幅抖动——不对劲,正常情况下应该是稳定的TTL电平。

顺着电源线往回查。STC89C52的供电电压也在抖。

最终发现:单片机芯片在烧录座上没有卡紧。那个烧录座的卡扣略有松脱,芯片的VCC脚和烧录座的触点之间有时接触、有时断开,导致供电时断时续。单片机在这种“吃不饱”的状态下勉强工作,就像人发着高烧还要算数学题——别说不正常了,能亮屏都算它顽强。

解决

把芯片重新用力按进烧录座,听到“咔哒”一声卡紧。上电,LCD规规整整地显示出“T:22.0C H:43.0%”,一切正常。

那一刻的心情很复杂——改了四五轮代码,最后发现是物理接触问题。想抽自己,也想笑。

教训

嵌入式开发是软硬一体的世界。当软件逻辑反复检查都正确时,不要只盯着代码看,去摸一摸电路板,量一量电压,摁一摁芯片。很多时候,Bug不在代码里,在物理世界里。


坑三:LCD单位神秘失踪

现象

前两个坑解决后,系统终于能稳定工作了。温湿度数值正确,状态判断正确,蜂鸣器也响得准。但仔细一看,LCD的显示有点不对劲——

第一行显示的是 T:22.0 H:43.0,而不是 T:22.0C H:43.0%。

摄氏度的“C”和湿度的“%”凭空消失了。

数值是对的,但不知道单位,这让人怎么看?22.0是度还是华氏度?43.0是百分比还是什么别的?

排查

回到代码里查LCD显示函数。我们用的是字符定位写入的方法:

LCD_SetCursor(0, 6);    // 定位到第一行第7列
LCD_WriteChar('C');     // 写入℃符号

LCD_SetCursor(0, 14);   // 定位到第一行第15列
LCD_WriteChar('%');     // 写入%符号

逻辑看起来没问题。但实际显示时,C和%都没有出现。

仔细核对坐标后发现:温度数值“T:22.0”占用了7个字符位置(T、:、2、2、.、0、空格),而我们设定的光标位置是第7列——但实际上应该在第8列。差了一格。这个偏差让C被写到了屏幕显示区域之外(或者覆盖了其它字符),而%符号也因为类似的计算错误,被安排到了错误的位置。

问题根源是:写代码时心算了一下坐标,没有逐个字符数清屏幕位置,结果偏了一位。

解决

重新梳理第一行的字符布局。

修正坐标参数,把C写在第6列(0起始计数),%写在第14列。烧录后,T:22.0C H:43.0%完整呈现。

教训

屏幕显示无小事。看起来只是少了一个小小的“C”,但对用户来说,没有单位的数字就是废数。写界面时,拿一张纸把每个字符的位置画出来再编码,比脑子心算靠谱十倍。


这三个坑教会我们什么

项目做完了再回头看,这三个坑看似低级,但每一个都恰好卡在嵌入式开发最容易被绊倒的地方:

  • 坑一是“软件与器件特性的脱节”——不知道传感器会睡觉,因为没仔细读手册里那段不起眼的描述。

  • 坑二是“软件与硬件的边界模糊”——代码看起来全对,但问题出在物理连接上,不摸一摸永远找不到。

  • 坑三是“细节精度掉链子”——系统都能算趋势了,差点因为一个单位字符错位让显示失去意义。

做嵌入式,永远是在跟现实世界打交道。传感器会睡觉,芯片会接触不良,你的眼睛会数错坐标——把这些都算进开发过程,才是真正的工程思维。


下一篇预告

坑爬完了,项目也做完了。在最后一篇里,我会做一个完整的复盘:这个项目给了我们什么?如果再做一遍会怎么改进?那套趋势预警的思路,还能用在哪些地方?

下一篇:《复盘与展望——这个项目带给我们什么?》,给整个系列一个收尾。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。