最烂的英语 × 最野的代码 = 能亮的屏幕:论工业开发中的“屎山动力学”

本文记录了一个英语六级压线过的工业程序员,如何用三件套(翻译+示波器+玄学改参)征服全英文datasheet,最终在老板期待的目光中让OLED显示出第一个汉字—“'艹”的完整过程。

文章封面

文章标题

  • 1 “菜鸟程序员”的“摆烂”哲学
  • 2 从时序图到代码:SPI党对8080接口的屈服
  • 3 CV大法好?手册初始化代码的“甜蜜陷阱”
  • 4 从雪花到空白:被遗忘的写RAM命令引发的血案
  • 5 从ASCII到汉字:一个OLED码农的造字运动
  • 6 开发总结:学会了很多,但下次别学了

1 “菜鸟程序员”的“摆烂”哲学

就在前几天,老板神秘兮兮地扔给我一块裸屏:“这可是高端货,工业级OLED!”我接过来一看,心凉了半截——没有配套PCB,没有转接板,连个螺丝孔都没有,就一块光秃秃的玻璃片,价格标签上的数字倒是格外醒目。

作为资深“摆烂”程序员,我的标准开发流程向来简单粗暴:买模块→要例程→复制粘贴→完工收钱。但这次,当我满怀期待地向供应商索要参考代码时,对方热情地发来了两个文件——SSD1322-Revision 0.10 to Univision.pdf和GME240128-01.pdf,全是英文的,连个"Hello World"的示例都没有!

[我]:您好,请问有参考代码吗
[商家]:有的(啪地甩过来两个PDF)
[我]:好的,谢谢(直接两眼一黑)

不死心的我又联系了五六个供应商,结果收到的回复出奇地一致:“资料已发,请查收附件”,点开一看,还是那两份熟悉的手册。那一刻我终于明白,这次是真的要自己动手写驱动了——对于一个连datasheet目录都懒得看的人来说,这简直是职场生涯的最大挑战!

2 从时序图到代码:SPI党对8080接口的屈服

OK,事到如今只能靠自己了,我先打开了来自硬件同事的原理图,仔细对照英文手册看了一下,硬件设计上使用的是8080接口,我的内心是崩溃的——这都2025年了,为什么不用SPI!(摔)。但抱怨归抱怨,活还是要干的。仔细研究了下关键引脚:

引脚名称功能描述(翻译成人话)
E(RD)在8080模式下,该引脚接收读信号,当该引脚被拉低且芯片被选择时,将启动读操作。
R/W(WR)在8080模式下,该引脚作为写输入,当该引脚被拉低且芯片被选择时,启动写操作。
DC该引脚是数据/指令控制引脚,与微控制器相连。当该引脚被拉高时,D0到D7中的内容将被解读为数据。当该引脚被拉低时,D0到D7中的内容将被解读为指令。
CS该引脚是连接到MCU的芯片选择输入。只有当该引脚被拉低时,芯片才在MCU通信中启用。
RES该引脚为复位信号输入。当该引脚被拉低时,芯片将执行初始化操作。在正常工作期间,请保持该引脚悬空或高电平。

OK,了解了这些功能之后我们看一下时序图,这是我们程序设计的关键!

写时序图
这是一个写的时序图,作为显示器件,很少会用到读功能,所以我们只分析写时序,大概是这么个流程顺序

  • 先给DC引脚"打暗号"(高低电平决定发数据还是指令)
  • 把CS引脚按在地上(拉低表示"我要开始表演了")
  • 在D0~D7上摆好"八仙过海"(并行数据必须同时到位)
  • 给WR引脚来个"摸头杀"(拉低再拉高完成写入)

正当我感叹英文手册看得眼冒金星时,突然发现附录里居然有初始化代码!这感觉就像在泡面桶底发现了“再来一桶”——直到后来我才明白,这个“惊喜”其实是厂商埋的雷…

3 CV大法好?手册初始化代码的“甜蜜陷阱”

看到原理图的瞬间我直接破防了——PB2这不是BOOT1引脚吗?!(设计同事你认真的吗.jpg)赶紧翻开芯片手册查证,结果发现:只要BOOT0老实接地,BOOT1确实可以“改行”当普通IO用,连特殊配置都不需要。行吧,硬件大佬永远是对的…

部分硬件原理图

接下来就是见证玄学的时刻——手搓8080时序!经过反复研读那张堪比藏宝图的时序图,终于写出了灵魂写命令函数:

/*
 *==============================================================================
 *函数名称:Med_Oled_WriteCmd
 *函数功能:OLED写命令函数
 *输入参数:cmd - 要写入的命令(1字节)
 *返回值:无
 *备  注:严格遵循8080接口时序,延时满足SSD1322规格书要求
 *==============================================================================
*/
void Med_Oled_WriteCmd (u8 cmd)
{
	OLED_DC = 0;        // 命令模式
	OLED_CS = 0;        // 片选使能
	// 设置好数据
	OLED_RW = 0;        // WR 拉低(开始写周期)
	delay_us(1);        // 保持低电平时间(>50ns)
	OLED_RW = 1;        // WR 上升沿(锁存数据)
	OLED_CS = 1;        // 片选禁用
}

OK,设计完基本的发送数据/命令函数之后,我们就开始设计初始化函数,刚好手册给出来了!直接开启CV大法,虽然看不懂每个寄存器在搞什么行为艺术,但手册总不会骗人吧?

通电瞬间——亮了!虽然满屏雪花像极了90年代电视机,但至少证明芯片还活着!此刻的我仿佛已经看到胜利曙光!只要再加个清屏函数,就能…等等,这个雪花怎么清不掉?!

4 从雪花到空白:被遗忘的写RAM命令引发的血案

当我终于搞明白SSD1322的像素结构时,差点把咖啡喷在手册上——这货居然用4bit表示一个像素,而且最大只能控制120×128区域!而我手上的屏幕是240×128

SSD1322手册截图

这意味着我至少需要分上下两个区域控制,也就是分成两个60*128,上下两部分,OK,我们来设计一下清屏函数

void Med_Oled_Clear(u8 color)
{
	u8 x, y;
	
	/* 设置显示范围:240列(60地址×4像素) × 128行 */
	Med_Oled_SetColumnAddress(0, 59);   // 设置列地址范围0-59(对应240像素)
	Med_Oled_SetRowAddress(0, 127);     // 设置行地址范围0-127(128行)
	
	/* 全屏填充 */
	for(y = 0; y < 128; y++)   // 行循环
	{                   
		for(x = 0; x < 60; x++) // 列循环(60地址×4像素=240列)
		{
			/* 
			 * 写入格式说明:
			 * - 每个字节包含2个相同4bit像素
			 * - 例如color=0xF → 写入0xFF
			 * - 60次写入=120字节=240像素
			 */
		}
	}
}

信心满满地烧录测试…结果屏幕依然倔强地展示着它的雪花艺术!啊?还是满屏雪花点!此时我开始觉得有点不对劲,不得不开启“侦探模式”,然后开始对照手册疯狂翻,硬着头皮去对照寄存器表挨个查看初始化程序中的配置!

终于!功夫不负有心人!我发现初始化程序里却掉了关键一步,开启写RAM命令!

Med_Oled_WriteCmd(0x5C);  // 开启RAM写入

终于!雪花屏变成了期待已久的"黑洞屏"!这感觉就像终于让傲娇的OLED开口说了第一句人话…

5 从ASCII到汉字:一个OLED码农的造字运动

当清屏函数终于驯服了那块倔强的OLED,我以为胜利在望——直到意识到还要手搓字库、字符显示、字符串显示,甚至汉字显示!这感觉就像好不容易造好了笔,却发现还得自己发明文字系统…(╯°□°)╯

此时我的精神状态

转机出现在我掘地三尺找到的某商家SPI参考代码!虽然通信协议不同,但字库设计和显示逻辑简直就是救命稻草。

由于初始化配置了列行式+从下到上扫描+COM分割,连显示8×16字符都要分成上下两场“演出”,先显示上半部分8×8,再蹦跶到下半部分8×8

// 伪代码:分裂的字符人生
void ShowChar(u8 x, u8 y, char c)
{
    ShowUpperPart(x, y, c);  // 上半场
    ShowLowerPart(x, y+8, c); // 下半场
}

好不容易搞定基础字符,主管却表示:“这字小得要用显微镜看!”,于是开启了32×64大字模式:重新取模32*64点阵,分8次处理数据块。

最后是移植汉字显示函数,商家给出的参考代码在调用汉字显示函数时传入的是指针

// 原版:每次调用都要算偏移量
OLED_ShowCHinese(10, 0, HZ+32*5); // 显示第5个汉字

我的优化版让函数自己做数学题

// 进化版:传入索引自动计算
void ShowChinese(u8 x, u8 y, u8 index)
{
    u8 *font_ptr = HZ + index * 32; // 自动定位字库
    // ...显示逻辑...
}

// 调用时清爽如风:
ShowChinese(10, 0, 5); // 直接传序号!

6 开发总结:学会了很多,但下次别学了

看着终于正常工作的OLED屏幕,我的心情复杂得像这个4bit灰度显示——既有完成挑战的淡淡成就感,更多的是“再也不想碰”的强烈解脱感。

这场底层驱动开发确实学到了8080时序、显存管理、字库设计…但下次如果还有选择,我一定选带现成驱动的TFT屏或者商家提供完整SDK的OLED!

作为一个资深“摆烂”的开发者,我认为能用现成轮子就不要自己造!能专注业务层就不要碰底层!除非…老板给的实在太多了(苦笑)

最后声明:本文来自一个被硬件折磨到摆烂的软件工程师,所有“浪费生命”的吐槽都是——

while(1)
{
    printf("个人观点,大佬轻喷\n");
    delay(1000);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二土电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值