智能手环 DIY 调试记:踩坑字符库、I2C 与 OLED 显示
承接之前的开箱,这周正式进入开发调试阶段,没想到刚上手就接连遇到三个小坑,好在逐一解决后,终于让 OLED 屏正常显示数据,也算收获满满。
第一个坑出在字符库编译上。写 SSD1306 的 8x8 字库时,给反斜杠(\)字符加注释时,直接写了// 92: \,结果编译器把注释里的 \ 当成续行符,哪怕在注释里也生效了,导致后续字符的点阵数据被误判为多行注释的一部分,OLED 显示时后面的数字和符号全错位。查资料才发现 C 语言的这个 “特性”,赶紧把注释改成/* 92: \*/,用块注释包裹反斜杠,重新编译后果然正常了,这个细节真是第一次注意到。
const uint8_t font8x8[][8] = { … {0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00}, /* 92: \ */ … }
接着是硬件连接的 I2C 问题。一开始把 MAX78000 评估板、MAX30102 传感器和 SSD1306 屏分散放在面包板不同区域,杜邦线拉得很长,结果 I2C 传输出错,OLED 频繁闪屏、传感器数据读不到。想起之前查的 I2C 优化方案,赶紧重新布局 —— 把作为主设备的 MAX78000 放在中间,SSD1306 和 MAX30102 紧贴着它插在同一排面包板上,避免跨板跳线,缩短 SDA/SCL 线到 5cm 以内,再上电后 I2C 通信瞬间稳定,数据再也没丢过。
最后是 OLED 显示翻转的问题,刚点亮屏幕时,字符上下左右全是反的,像照镜子。翻 SSD1306 的初始化代码,发现SSD1306_Init里的列地址映射用了0xA1(左右翻转)、行扫描方向用了0xC0(正常),赶紧改成0xA0(列正常)和0xC8(上下翻转纠正),重新下载程序后,“Hello World” 终于正过来了。
void SSD1306_Init(void) { uint8_t cmd[] = { 0xAE, // 关闭显示 0x00, 0x10, // 列地址低/高位 0x40, // 起始行 0xB0, // 页地址 0x81, 0xCF, // 对比度 0xA1, // 段重映射 左右翻转 0xA6, // 正常显示 0xA8, 0x3F, // 多路复用率 0xD3, 0x00, // 显示偏移 0xD5, 0x80, // 震荡频率 0xD9, 0xF1, // 预充电周期 0xDA, 0x12, // COM引脚配置 0xDB, 0x40, // VCOMH设置 0xC8, // 行扫描方向 上下翻转 0x8D, 0x14, // 启用电荷泵 0xAF // 开启显示 }; MXC_Delay(MXC_DELAY_MSEC(10)); OLED_Write(SSD1306_CMD, cmd, sizeof(cmd)); }
现在各模块终于协同工作,下一步就能把 MAX30102 的心率数据显示到 OLED 上了。不得不说,调试过程虽然踩坑,但解决问题的过程反而让我对硬件细节和编译规则理解更透彻,也多亏了 EEPW 活动里的技术文档,帮我少走不少弯路~