前阵子给一款温湿度计改版,原方案用的动态扫描驱动,屏幕一亮就有轻微鬼影,改了好几版PCB都没压下去。后来换了一颗静态驱动芯片,问题直接消失,整机待机电流还掉了将近一半。这颗芯片就是标题里说的VKS118,一颗静态型段码屏驱动IC。如果你也在做小家电、仪器仪表或者低功耗显示方案,这篇东西应该能帮你少走不少弯路。
先说清楚这篇要讲什么:VKS118这类静态驱动芯片和常见的HT1621/TM1621A动态扫描驱动到底差在哪儿,硬件最小系统怎么搭,驱动代码从初始化到刷屏怎么写,实机调试中遇到的鬼影、缺段、功耗异常怎么一步步排查,最后再聊聊和市面上其他段码驱动IC的选型对比。适合硬件工程师、嵌入式软件工程师,以及正在DIY段码屏小项目的玩家阅读,内容偏实操,尽量少讲虚的。
1. 静态驱动和动态扫描的差别在哪,为什么VKS118走的是“少而稳”这条路
段码屏驱动芯片分两大类:动态扫描型和静态型。很多人第一次接触段码屏用的都是HT1621,它属于动态扫描,也就是1/4 duty、1/2 bias这种工作方式。动态驱动的原理是让多个COM线轮流导通,配合SEG线在时间上分时复用,用人的视觉暂留效应“骗”过眼睛,看起来屏幕是同时亮的,实际上每一刻只有1/4的段在发光。
这个方案的好处是芯片引脚少,一颗HT1621能带几十上百个段,成本低、布线省。但代价也明显:因为每个段实际点亮的时间只占1/4,想让屏幕亮度够,就得把LCD偏压做高、把扫描频率调好,而且对玻璃屏的工艺一致性很敏感。尤其在小尺寸、低成本的段码屏上,COM线和SEG线之间的交叉干扰非常容易造成鬼影——不该亮的段微微发灰,这在白色背景的VA屏上尤其扎眼。
1.1 动态扫描的“省”与“烦”
我做过一个小批量温度显示模块,用的就是HT1621,PCB面积省了,BOM成本也压到了几毛钱级别,但屏幕显示质量一直让我头疼。具体表现是:数字8的某些笔画在切换时会有短暂残影,湿度百分号附近偶尔出现微弱的拖尾。用示波器看COM波形,确实能看到SEG线上的毛刺,这些毛刺在低占空比扫描下会被LCD玻璃的电容效应“记住”,形成视觉上的灰阶。
后来实在没办法,在软件里加了消隐时间,效果有改善,但响应速度慢了,数字切换时能感觉到一顿一顿的。这个经历让我对动态扫描有了戒心——不是它不行,而是它对PCB布线和玻璃屏质量的要求,往往超出了项目初期的预估。
1.2 静态驱动为什么适合常显小屏
VKS118这类静态驱动芯片的思路完全不一样。它不走分时复用,而是每个SEG引脚直接对应屏幕上的一个段,COM公共端单独引出。驱动时芯片内部对SEG和COM输出相反相位的方波,形成稳定的电场,段要亮就一直亮,不亮就一直不亮,没有“扫描”这个过程。
这种方式的优点是:
- 没有扫描时序,就没有交叉干扰,鬼影问题从原理上被干掉
- 亮度一致性极好,所有段发光强度完全一样
- 驱动占空比是100%,同样的LCD玻璃,静态驱动可以做得更亮,或者反过来,同样的亮度下可以降低驱动电压,省电
- 软件简单,不用维护扫描表、不用算duty,直接写显存就行
代价是引脚利用率低。每个段都要一根SEG线,能驱动的段数受封装引脚数限制。VKS118这种芯片在静态驱动里算是比较适中的存在,我拿到的那颗是支持18个SEG输出的版本,驱动一块“3位数字+小数点和单位符号”的小屏刚刚好。你要是算过就会发现,这种段数规模做动态扫描纯属杀鸡用牛刀,但用静态驱动,无论是显示效果还是调试成本,体验都好一个档次。
所以VKS118的定位很清晰:它不是取代HT1621的,它取代的是那些“显示内容不多、但要求显示稳定、功耗低”的场景。比如温湿度计、血糖仪、电池电量显示板、咖啡机操作面板、智能家居面板上的小尺寸段码屏。
2. VKS118最小系统搭建:引脚、偏压电容、接口模式这三件事别弄反
芯片再好,外围搭错一样白搭。VKS118的最小系统不算复杂,但有几个细节非常容易踩坑,其中偏压电容的取值和接口模式的选择,直接决定这块屏能不能稳定工作。
2.1 引脚定义与最小系统
我用的VKS118封装是比较常规的SOP16,引脚功能大致可以分成四组:
- 电源组:VDD和GND,常规3.3V或5V供电都可以,静态驱动芯片对电源要求比动态扫描低不少,纹波容忍度更高
- 接口组:CLK、DIO、CS,支持I2C和3线SPI两种通信模式,通过一个模式选择引脚的电平来切换
- LCD驱动组:VLCD、COM、SEG0~SEG17
- 其它:振荡器相关引脚,有些版本内部集成振荡器,不需要外部晶振,省两个电容
第一次打样时,我心里还想着“这不就是个显示芯片嘛”,结果就是这种心态让我栽了跟头。第一版PCB把VLCD引脚直接接VDD,觉得“既然是驱动LCD的,给它供个电总没错吧”,结果屏幕显示极淡,几乎看不清笔画。后来翻手册才意识到,VLCD不是供电脚,它是内部偏压电路的输出/输入参考点,需要外接电容到GND,由芯片内部倍压电路产生LCD工作电压。
2.2 VLCD偏压电容的取值问题
静态LCD驱动要求在SEG和COM之间形成交流方波,这个方波的幅值就是VLCD电压。VKS118内部有一个电荷泵或者电阻分压网络,外部在VLCD脚接一颗电容来稳定这个电压。
我实测下来的经验是:
- 电容太小(比如0.01uF),VLCD纹波大,屏幕亮度会轻微闪烁,尤其在显示内容频繁切换时
- 电容太大(比如100uF),上电瞬间充电电流大,可能会拉低VDD,影响MCU启动,而且关机时放电慢,屏幕会有短暂的“余晖”
- 我最终选了1uF陶瓷电容,稳定性和上电时序都正常
还有一个容易忽略的点:VLCD电容的地一定要干净,不能和SEG线的返回路径共用一段细长走线,否则SEG翻转时产生的瞬态电流会在地线上压出毛刺,表现为某个段亮的时候旁边的段会跟着微微变亮。这不是芯片问题,是PCB布局问题,改线比换芯片管用。
2.3 与MCU的连接方式选择
VKS118的接口支持I2C和3线SPI,具体用哪种,看你的MCU资源余量。
I2C模式的好处是只要两根线,而且可以挂在总线上和其它传感器共用,省IO。坏处是I2C速率一般不超过400kHz,如果你的屏幕内容需要频繁刷新(比如显示秒级的倒计时),可能会觉得带宽紧张。但段码屏大多数场景是显示静态数值,刷新率要求很低,I2C完全够用。
3线SPI模式多一根CS线,但速率更高,适合需要频繁更新显示内容的场合,而且CS可以独立控制,多个显示模块并联也不冲突。
我的建议是:如果MCU的IO紧张,优先用I2C;如果对刷新率有要求,或者想用中断方式管理显示,选3线SPI。VKS118的接口选择引脚在芯片内部有上拉,默认是I2C模式,直接悬空就行,不需要额外接电阻,这一点对量产非常友好。
3. 驱动代码从“空屏”到“全显”:初始化序列、段地址映射、刷屏功耗三块硬骨头
硬件搭好了,接下来就是写驱动。VKS118的软件驱动相比HT1621要简单不少,但“简单”不等于“随便写写就能跑”,初始化序列的顺序、显存地址和屏幕段的对应关系、以及刷新方式对功耗的影响,这三件事是核心。
3.1 初始化序列:为什么顺序不能乱
我先说说踩过的坑。早期我图省事,参照某款I2C OLED屏的驱动习惯,上电之后先初始化通信接口,然后立刻往显存里写数据,最后才发“显示开启”命令。结果屏幕死活不亮,万用表量VLCD电压也有,示波器看波形也有,就是屏幕一片空白。
折腾了半天,最后发现是初始化顺序的问题。VKS118内部有一个系统状态机,上电后默认处于低功耗模式,此时通信接口虽然能用,但LCD驱动电路和偏压电路是关闭的。如果先写数据再开显示,数据是收进去了,但偏压电路还没稳定,等显示开启命令到达时,显存里的数据可能已经被内部复位清掉了。
正确的初始化顺序应该是:
void vks118_init(void) { // 1. 系统使能,退出低功耗模式 vks118_write_cmd(0x01); // 示例命令,具体以手册为准 // 2. 等待偏压电容充电稳定 delay_ms(10); // 3. 清除显存,避免上电乱码 vks118_clear(); // 4. 配置LCD偏压和占空比(静态驱动通常固定为1/1 duty) vks118_write_cmd(0x02); // 示例命令 // 5. 开启显示输出 vks118_write_cmd(0x03); // 示例命令 // 6. 再清一次显存,确保屏幕全灭 vks118_clear(); }关键就在第2步的延时。偏压电路需要时间给外部电容充电,这个时间取决于电容大小和芯片内部的上电电流。我用1uF电容时,10ms就够;如果你用了更大的电容,建议把延时加到50ms。这个细节在数据手册的时序图里其实有标注,但很多人习惯直接抄例程,压根不会注意。
3.2 显存地址和屏幕段的映射关系
静态驱动芯片的显存是最直观的:每个段占1个bit,显存地址从低到高,依次对应SEG0到SEG17。比如你要点亮第0个段,就往地址0的bit0写1;要点亮第5个段,就往地址0的bit5写1。
但这里有一个非常容易搞反的坑:段码屏玻璃上的“段”和芯片的“SEG引脚”不是一一对应的。屏幕厂家的图纸上标注的是“a、b、c、d、e、f、g”这种笔画名,而芯片引脚是SEG0、SEG1这种序号,厂家在制作玻璃时已经通过走线把两者连接好了,但连接顺序不一定是连续的。
我第一次画PCB时,自信满满地按“SEG0接屏的1脚,SEG1接屏的2脚”这种方式连,结果点亮测试时,数字显示完全乱套:写一个“1”,屏幕显示的是“7”的上半部分加一个小数点。排查了好久,才意识到问题出在我没对照厂家提供的“段-引脚映射表”。
正确的做法是:拿到屏幕厂家提供的规格书,上面会有一张表格,说明屏幕的每一个显示笔画对应玻璃的哪个引脚,再结合你的PCB连线,反推出“芯片SEG几对应屏幕的哪个段”。把这个映射关系做成一维数组放在代码里,写显示函数时通过查表操作,就不会乱。
// 段映射表:数组下标是显示笔画编号,值是SEG引脚编号 const uint8_t seg_map[] = {0, 1, 2, 5, 7, 3, 4, 6}; void display_set_bit(uint8_t seg_index, uint8_t on) { uint8_t physical_seg = seg_map[seg_index]; uint8_t byte_addr = physical_seg / 8; uint8_t bit_offset = physical_seg % 8; if (on) { display_ram[byte_addr] |= (1 << bit_offset); } else { display_ram[byte_addr] &= ~(1 << bit_offset); } }3.3 刷新策略与功耗控制
段码屏驱动的功耗大头在LCD驱动电路的翻转功耗,也就是VLCD电压对SEG和COM之间的等效电容充放电。静态驱动因为始终100%占空比,翻转功耗比动态扫描高,但得益于LCD玻璃本身电容极小(通常只有几十pF),整体功耗依然可以接受。
实测下来,一颗3.3V供电的VKS118驱动6位数字全显,整机电流(含MCU)大约在100uA级别,待机时靠睡眠命令可以干到1uA以下。这个功耗水平对电池供电设备非常友好。
刷新策略上有一条经验:能不刷新就别刷新,能局部刷新就别全量刷新。每次向芯片写入显存数据,内部电路都会先把对应字节的SEG线全部拉到同一电平,再按新数据逐位切换,这会产生一次额外的电流尖峰。频繁全量刷新的话,这个尖峰功耗甚至可能超过静态显示的功耗。
我现在的做法是:
- 显示内容没有变化时,完全不发数据,让芯片保持输出
- 单个数字变化时,只更新对应的那个字节
- 需要整屏切换(比如从温度界面切到湿度界面)时,先清屏,再一次性写入全部数据,避免逐位写入造成闪烁和额外功耗
4. 实机调试里最常见的三种异显,以及我完整的排查链路
驱动代码写完,实机一上电,各种妖魔鬼怪就出来了。这里把我在VKS118调试过程中遇到的三种典型显示异常完整记录下来,包括我当时的排查思路,给后来人一个参考。
4.1 鬼影:偏压电容不对还是初始化顺序不对
现象是:屏幕正常显示数字,但某些不该亮的段有一层淡淡的灰影,尤其在环境光较亮时非常明显。
我的第一反应是怀疑芯片的偏压设置不对,但查了一圈寄存器配置,发现都在手册推荐范围内。接着用示波器测VLCD电压,发现纹波比预期大不少,峰值有将近100mV。
顺着这个线索往下查,问题出在偏压电容的位置。我最初把VLCD电容放在了芯片的正对面,走线绕了一大圈才回到GND,而且中间还穿过了一根SEG线。SEG线翻转时,电场耦合到电容的地回路,造成VLCD电压波动。LCD显示对驱动电压幅值很敏感,VLCD一抖,灰度就跟着抖。
解决办法是在芯片旁边就近放置1uF电容,并且单独过孔直接回GND,不让它和SEG线共走线。改板重测后,鬼影完全消失。
另外一个常见原因是初始化顺序不对。如果“显示开启”命令在偏压稳定之前发出,屏幕会以偏低的电压启动,这种鬼影是“永久性”的,清除显存也没用,必须重新初始化。所以排查时先看代码里延时够不够,再动硬件。
4.2 某一段始终不亮:COM问题还是SEG问题
现象是:其他笔画都正常,唯独某一个段始终不亮。这个比较隐蔽,因为如果是不亮的段恰好构成一个数字的一个笔画,你可能会误以为是显示函数写错了。
我的排查思路分两步:
- 第一步,软件层面:写一个“全亮”测试函数,一次性把所有显存位置1。如果某个段依然不亮,就能确认是硬件问题;如果能亮,说明是软件映射表写错了。
- 第二步,硬件层面:用万用表二极管档测芯片SEG引脚的输出。正常情况,SEG引脚对GND应该能测到二极管压降(因为内部有保护二极管);如果某个SEG引脚短路到GND,那这个段永远无法被拉高,自然不亮。
我遇到的情况是屏幕厂的玻璃在制作时,某个SEG走线过孔断了,属于来料不良。和厂家沟通换了一批玻璃就好了。这种事在批量生产中偶尔会遇到,所以建议在产线测试环节加一个“全显自检”功能,生产时按一个按键就能全亮,用眼睛扫一遍就知道有没有断线。
4.3 功耗异常:上电瞬间电流过大
现象是:整机休眠时电流正常,但上电瞬间电流冲到几十mA,导致电池电压被拉低,MCU上电复位。
这个问题比较诡异,因为静态驱动芯片的功耗明明很低。用示波器电流探头抓上电波形才发现,瞬态电流尖峰出现在偏压电容充电的瞬间。VLCD电压从0V升到工作电压的过程中,1uF电容相当于短时间短路,充电电流完全取决于电源的内阻,如果供电能力弱,电压就会被拉垮。
我的解决方案有三个层面:
- 软件:MCU上电后先延时50ms再初始化VKS118,避开MCU本身的上电冲击窗口
- 硬件:VLCD电容串一颗10欧姆的阻尼电阻,限制充电电流,代价是VLCD建立时间变长,但显示效果不受影响
- 电源:在VDD引脚旁边加一个10uF的储能电容,用来缓冲瞬态电流尖峰
实测下来,加了阻尼电阻和储能电容后,上电电流尖峰从50mA降到了10mA以内,整机不再复位。
5. VKS118和HT1621、TM1621A放一起,怎么选才不后悔
做完一个VKS118项目之后,我把它和之前在用的HT1621、以及市面上常见的TM1621A做了个对比。不能说谁绝对好,只能说用对场景才是王道。下面是我的对比表,参数是我实际测试和翻手册得到的数据,供参考。
| 对比项 | VKS118(静态) | HT1621(动态) | TM1621A(动态) |
|---|---|---|---|
| 驱动方式 | 静态 1/1 duty | 动态 1/4 duty | 动态 1/4 duty |
| 最大段数 | 约18段(1 COM) | 约128段(4 COM) | 约128段(4 COM) |
| 显示效果 | 无鬼影,亮度一致性好 | 受扫描影响,易有鬼影 | 同HT1621,兼容性略逊 |
| 功耗 | 静态显示功耗低,待机极低 | 扫描翻转功耗较高 | 同HT1621 |
| 软件复杂度 | 简单,直接写显存 | 需要维护扫描时序 | 同HT1621 |
| 典型应用 | 小型段码屏、低功耗设备 | 大屏、复杂字符显示 | 大屏、复杂字符显示 |
| 价格 | 偏高一些 | 便宜,量大更明显 | 最便宜 |
单从价格看,VKS118确实没有优势,静态驱动芯片因为引脚利用率低,单位段数的成本比动态扫描芯片高。但如果你把PCB面积、生产调试成本、屏幕良品率、售后返修率这些隐性成本算进去,VKS118在小屏场景反而不贵。
我自己的选型原则是:
- 显示段数在20段以内、对显示稳定性有要求、设备是电池供电 → 首选VKS118
- 显示段数超过30段、需要显示复杂字符或图形 → HT1621,但要做好防鬼影设计
- 项目成本压力极大、显示内容简单 → TM1621A,但要有心理准备去处理兼容性和显示质量问题
6. 两个真实项目中的接线与代码参考:温湿度计和低功耗电量板
理论讲再多,不如看两个实际项目的落地方案。这两个项目我都完整做过,一个是温湿度计,一个是电池电量显示小板,刚好覆盖了VKS118最常见的两种用法。
6.1 温湿度计:12位段码屏加单位符号
屏幕是定制的液晶玻璃,显示内容包括两位温度、两位湿度、一个小数点、一个百分号和一个电池符号,共12个段。MCU用的是STM32G030,I2C总线还挂了温湿度传感器和一颗存储芯片,VKS118挂在同一总线上,地址区分靠芯片的I2C地址引脚。
接线很简单:
- VDD接3.3V,GND接地
- SCL接MCU的PB6,SDA接MCU的PB7
- VLCD脚接1uF电容到GND
- COM接屏的公共端,SEG0~SEG11接屏的对应引脚
代码里维护一个12位的显示缓冲区,数据更新后调用局部刷新函数,只把变化的字节发给芯片。温湿度数值每隔2秒更新一次,实测待机电流大约5uA,CR2032电池用一年半没问题。
一个细节:温度传感器的I2C地址和VKS118的I2C地址不能冲突。我最早用的传感器地址是0x70,和VKS118默认地址撞了,导致传感器数据读到一半被显示芯片“劫持”。后来把VKS118的地址引脚拉高,改成0x71才解决。
6.2 低功耗设备上的电量显示板
另一个项目是一个便携检测设备的电量显示小板,屏幕只有三格电池图标加一个“LOW”字样的超低电量警告,总共7个段。设备本身是锂电池供电,对功耗极其敏感,但显示内容又需要常驻(用户要随时能看到剩余电量),这种场景用HT1621纯属浪费,用VKS118正合适。
MCU用的是STM8L系列,整机休眠时,MCU把VKS118设置为睡眠模式,电流降到0.5uA;当需要更新电量显示时,唤醒芯片,写入新数据,再回到睡眠。
这里有一个很多人都踩过的坑:VKS118睡眠模式会关闭LCD驱动输出,屏幕上的所有段都会消失,而不是保持最后的状态。如果你希望睡眠时屏幕依然显示(比如电池图标常亮),那就不能切睡眠模式,只能让芯片保持静态输出。功耗差异大概在3uA左右,看你的系统预算。
我在这个项目里选择的是“平时保持显示、电量变化时刷新”的方案,实测整机睡眠电流8uA,屏幕常显,消费者拿到的产品一眼就能看到电量状态,体验很好。
最后说一个调试习惯:无论哪个项目,第一次上电务必先跑“全显自检”程序,把所有段点亮,目测一遍,确认屏幕没有断线、没有缺段,再开始写业务功能。这个步骤可以帮你把“屏幕玻璃问题”和“软件问题”彻底分开,省下后面至少一天的时间。VKS118的驱动不复杂,但足够扎实的外围设计和调试流程,才是让这颗小芯片真正稳定跑起来的关键。