
简介这是一份基于STM32F101控制HT1621B液晶显示模块的完整工程源码包面向嵌入式初学者及需要快速实现段码液晶驱动的开发者。资源将STM32的GPIO/SPI配置、HT1621B初始化与读写命令、字符段码转换及动态刷新逻辑封装为可复用驱动函数并配有完整Keil工程文件便于直接编译烧录与二次开发。压缩包共129个文件以c/h源文件、o/crf编译中间文件、uvproj/uvopt工程配置及hex/bin烧录文件为主另有备份与调试辅助文件整体约2.49MB。目前已有356人学习下载。通过研读工程代码可掌握MCU与HT1621B的串行时序、段码显示原理并借鉴模块化驱动编写思路适合用于小型仪表、电子标签等显示场景的快速落地。 做温控器那会儿我对着样板上一片空白的段码LCD发过半小时呆。屏是买回来了4位数字加一堆单位符号数了数要控制的分段接近一百个MCU的GPIO扒光了也不够用。后来换上HT1621B液晶显示方案三条线搞定所有显示整个项目才算活过来。如果你也在做家电面板、仪表盘、小家电这类需要段码屏的产品或者只是手头有一片HT1621B驱动的液晶屏不知道怎么点亮这篇文章就是按我实际踩过的路写的——从芯片原理到GPIO模拟时序从段码映射到故障排查尽量讲透。1. 先搞明白段码屏为什么要交给HT1621B去养段码液晶和数码管的驱动逻辑完全不是一回事。数码管是LED给个高电平就亮直流驱动没问题。但液晶屏里的每个段是一层液晶分子长时间施加同向直流电压会产生电解反应液晶材料会老化失效所以必须用交流波形去驱动。更重要的是段码屏的每一段都要单独引出电极一片显示4位数字加图标的屏至少上百个段MCU就算有这么多引脚也没办法给每个段生成可靠的交流驱动波形。HT1621B干的事情就是把管理大量LCD分段这件事全部接管过去。它内部集成了32个SEG输出和4个COM输出最多能驱动32×4128个液晶段对应一个完整的四位八段显示加十几二十个静态图标绰绰有余。芯片内部自带RC振荡器和偏压发生器外部只需要接一粒几块钱的芯片MCU用三根GPIO模拟串行时序就能实现对所有段的开关控制。这个架构最大的价值在项目后期。你不需要在MCU上为显示逻辑分配大量中断和定时器显示刷新由HT1621B自己持续扫描COM和SEG波形MCU只在内容变化时发几个字节的数据。对于电池供电的设备来说HT1621B的低功耗特性也很突出静态电流通常在微安级别休眠模式更省很适合温控器、燃气表、电子秤这类常年通电的终端。另一个容易被忽略的点HT1621B支持的偏压比1/2和1/3、占空比1/4可以软件配置这意味着它不挑屏。不管你的液晶屏是3V的、5V的还是3.3V系统下配了一块3V屏都能通过设置配上合适的驱动电压和偏压比例。选型阶段我因为这个特点少走不少弯路屏厂给什么规格都能用不用额外换驱动方案。2. 接线和上电HT1621B这几十个脚怎么搭最稳HT1621B的标准封装里除了VDD和GND核心引脚就两组一组是SEG0到SEG31一组是COM0到COM3中间夹着CS、WR、DATA三根串行控制线还有OSCI、OSCO、VLCD几个辅助脚。实际项目里我最常用的接线方式如下VDD接MCU电源3.3V或5V均可VSS接地。VLCD用于设定LCD驱动电压接法需要单独处理。CS、WR、DATA分别接MCU三个GPIO后续都用软件模拟时序。OSCO和OSCI不接外部晶振直接用内部RC振荡器省两个引脚。COM0-COM3按PCB Layout顺序接屏的公共端SEG0-SEG31接屏的段电极。VLCD是新手最容易栽跟头的地方。如果屏幕显示很淡或者全屏都是鬼影大概率就是VLCD电压没给对。3.3V系统下VLCD直接接VDD通常能正常显示5V系统里如果屏的工作电压只有3VVLCD不能直接接5V得用两个电阻分压或者一颗10k电位器把电压调下来。我自己的习惯是第一次上电前VLCD先通过一个10k电位器接在VDD和GND之间边调边看显示效果确定最清晰的点后再实测电位器分压值换成固定电阻。VLCD引脚对地还必须并一颗0.1uF到1uF的电容这颗电容用来稳定内部偏压产生器的工作点省了它你会发现显示亮度在待机状态和刷新状态之间来回抖。还有两个隐藏细节容易被忽略。一是VDD的旁路电容不要省建议VDD和VSS之间放一颗0.1uF陶瓷电容加一颗4.7uF电解电容位置尽量贴近芯片的VDD引脚。液晶驱动瞬间电流很大旁路电容不给力的话显示内容切换的一瞬间整颗芯片电压都会跌落画面会出现短暂的花屏或闪动。二是HT1621B和早期HT1621不完全等价买芯片时要确认是带B后缀的型号引脚基本兼容但电气特性有些差异按照B版本手册为准。上电顺序也要提一嘴。MCU复位时GPIO默认可能是高电平如果CS在初始化前没有稳定拉高WR和DATA上乱跳的电平可能被HT1621B当成有效命令接收导致上电瞬间屏幕上出现一两个不该亮的段。稳妥的做法是MCU启动后先把CS、WR、DATA三个引脚设为推挽输出全部输出高电平再对HT1621B做初始化。初始化命令发完之后再开LCD显示命令这样屏幕上就不会出现乱七八糟的过渡状态。3. 时序和指令用GPIO手搓一条3线串口HT1621B的串行时序很简单本质就是一拍一拍地移位输出。CS拉低表示一次传输开始WR的上升沿把DATA引脚上当前的bit锁进芯片内部CS拉高结束传输。数据位都是高位在前先发命令标识再发命令字节或者地址加数据。写命令时首先要发3位的命令标识101表示这是一条写入命令随后跟8位命令内容。写显存时也是在命令标识101之后先发6位RAM地址再发4位数据。这4位数据对应同一个SEG地址下的COM0到COM3也就是4个COM段。给你看下我项目里实际在用的代码骨架STM32和GD32这类Cortex-M内核跑起来没有任何问题#define HT1621_CS_L() GPIO_ResetBits(GPIOB, GPIO_Pin_12) #define HT1621_CS_H() GPIO_SetBits(GPIOB, GPIO_Pin_12) #define HT1621_WR_L() GPIO_ResetBits(GPIOB, GPIO_Pin_13) #define HT1621_WR_H() GPIO_SetBits(GPIOB, GPIO_Pin_13) #define HT1621_DAT(x) (x) ? GPIO_SetBits(GPIOB, GPIO_Pin_14) : GPIO_ResetBits(GPIOB, GPIO_Pin_14) static void ht1621_delay(void) { volatile uint32_t i 10; while (i--); } static void ht1621_send_bits(uint16_t data, uint8_t cnt) { while (cnt) { cnt--; HT1621_DAT((data cnt) 0x01); HT1621_WR_L(); ht1621_delay(); HT1621_WR_H(); ht1621_delay(); } } static void ht1621_write_cmd(uint8_t cmd) { HT1621_CS_L(); ht1621_send_bits(0x05, 3); // 101 命令标识 ht1621_send_bits(cmd, 8); HT1621_CS_H(); } static void ht1621_write_ram(uint8_t addr, uint8_t dat) { HT1621_CS_L(); ht1621_send_bits(0x05, 3); // 101 命令标识 ht1621_send_bits(addr, 6); // 6位RAM地址 ht1621_send_bits(dat, 4); // 4位数据 HT1621_CS_H(); }初始化序列我用的是这样一组命令ht1621_write_cmd(0xA0); // 系统配置内部RC振荡器1/3偏压4个COM ht1621_write_cmd(0x80); // 系统使能打开振荡器 ht1621_write_cmd(0xA4); // LCD偏压发生器关闭 ht1621_write_cmd(0xA9); // LCD偏压发生器打开很多人只发0x80和0xA9发现屏幕也能亮但缺了0xA0的偏压配置低温下显示可能会明显变淡甚至出现串段。初始化命令的顺序也建议保持先配置、再使能、最后开显示的节奏。顺序颠倒后芯片内部偏压还没建立好就强行驱动液晶虽然不会烧芯片但上电瞬间屏上会出现短暂的杂点闪烁观感很不好。实际传输时还要注意GPIO翻转速度。用普通的GPIO模拟每两个bit之间加一点延时是必要的尤其MCU跑在72MHz甚至更高主频时GPIO翻转速度太快HT1621B可能抓不到有效的WR上升沿。我一般用一个空循环做延时跑72MHz时循环10次大概产生几百纳秒的延迟足够稳定。如果你用的MCU主频不同先示波器看下WR的周期保证在1us以上比较稳。4. 段码映射数字和图标是怎么对到屏幕上的这是HT1621B驱动的灵魂。芯片不关心你屏幕上数字长什么样它只知道RAM里每个地址上的每1个bit对应着某个SEG和某个COM交叉处的那个段。你往地址0x05的bit0写1地址0x05的SEG5和COM0交叉的那个液晶段就亮了——至于这个液晶段在屏幕上显示的是数字1的右下角还是一棵小树的叶子完全取决于PCB和LCD屏厂怎么把引脚走到对应位置。RAM的组织结构是32个地址SEG0到SEG31每个地址4个bitCOM0到COM3。所以同一个SEG线上挂着最多4个段分时由不同的COM扫描点亮这就是1/4占空比的意思。买回来的段码屏厂家会提供一张段位表标明哪个数字的哪个笔画接到了第几个SEG、第几个COM。拿最常见的7段数字举例。如果屏厂把数字的a、b、c、d、e、f、g七段分别接到了SEG0到SEG6且都挂在COM0上那么显示数字2就需要同时点亮a、b、d、e、g这五段对应的RAM操作就是往地址0、1、3、4、6里各写一个高电平到COM0位。实际操作时我习惯做一张数字字形映射表数字a段b段c段d段e段f段g段01111110101100002110110131111001401100115101101161011111711100008111111191111011但是先别高兴太早这张表只在段顺序与SEG顺序一致时才成立。很多屏厂出于走线方便的考虑会把数字的七段打乱顺序接到SEG上这时候就必须按屏厂给的段位表翻译一遍。我自己写过一个简单的脚本把屏厂的Excel段位表解析成一维数组按SEG和COM的交叉方式逐位生成显示数据再整理成C数组烧进MCU里。手工一个个对太容易错了尤其是有小数点和特殊图标的时候。写显示函数时每次刷新尽量只更新变化的段不要动不动整屏重写。HT1621B支持连续写模式可以先写首地址然后连续发送4位数据芯片自动递增地址。对于要实时刷新数字的温控器界面我用的是离散写地址方式每个数字单独更新只在切换单位或图标时补写对应标志位。这样既降低串行总线占用也避免频繁刷新导致液晶显示闪烁。还有一个实际工程里的技巧HT1621B的RAM在MCU掉电后会全部清零重新上电后如果不做初始化屏幕就是全灭状态。如果产品需要在断电后保留上次显示内容比如燃气表的总用量最好在外部EEPROM或MCU内部Flash里存一份显示状态镜像每次上电后先恢复再显示。直接依赖HT1621B的RAM保存数据是不现实的。5. 调试实录不亮、缺段、串字到底卡在哪5.1 屏完全不亮但程序跑起来了先别急着怀疑代码。拿万用表量HT1621B的VDD对地有没有正常电压VLCD引脚是不是有电压COM0到COM3上有没有波形。液晶驱动正常时用示波器挂在任意一个COM引脚上能看到频率几十到几百赫兹的扫描波形。如果COM上完全平的说明芯片根本没起振大概率是初始化没发对要么是CS线没拉低要么是WR时序没对准。排除了硬件和初始化问题后再看VLCD。我遇到过一块屏VLCD接VDD后全灭把VLCD往下调到VDD的80%时突然亮了。这是因为屏的驱动电压上限比系统电压低偏压太高反而让液晶无法翻转。建议调试时先拿电位器把VLCD从低到高慢慢拧观察哪个区域能正常显示再决定固定值。5.2 缺段某个笔画死活不亮缺段基本是段位映射错位或者是RAM地址写错。先用最简单的办法验证代码里把地址0到31逐一遍历每个地址的bit0到bit3依次写1再写0观察屏幕上哪些段跟着亮灭这样能把整片屏的段位表实际测出来。然后和自己写的映射表对照找出差异。还有种情况是地址对了、bit方向错了。比如你想要COM0亮结果把数据写成了0x08那是写到COM3去了。严格按HT1621B的RAM位序来写第1个bit对应COM0第2个bit对应COM1依此类推。我一开始就栽过这个跟头后来干脆在驱动层做了个宏把COM和SEG参数分离调用时按哪个COM、哪个SEG来传参再也不用记地址偏移。5.3 显示内容串位、残影、乱闪这三个问题通常是时序打太快导致的。HT1621B虽然最高可以跑到几百kHz的串行速率但GPIO模拟时不可能严格保证建立时间。WR上升沿到来时DATA上的电平还没稳定芯片就锁到了错误数据表现出来就是某个不该亮的段亮了一下或者整体显示错乱。解决思路很简单把ht1621_delay()的延时加大先跑通功能再逐步减小延时看临界点在哪里。实测下来在72MHz主频的Cortex-M0内核上两个bit之间留500ns以上就很稳如果你用的是Arduino这类慢速平台反而要注意别太慢——只要在芯片手册的时间上限以内慢一点没关系。残影还有一种可能是液晶本身响应慢。HT1621B采用动态扫描方式驱动COM扫描频率由内部RC振荡器决定。如果RC振荡器频率偏低扫描刷新率跟不上液晶的响应时间就会出现轻微拖影。这种问题换芯片引脚配置不能根治优先确认OSCO引脚有没有被外部电路误接地。如果用了外部晶振检查晶振负载电容是否匹配。5.4 温度一变显示就变淡这是段码屏的通病液晶材料的响应电压会随温度漂移。夏天正常的显示电压冬天可能显得很浅。HT1621B的偏压是固定的软件层没法做自动温度补偿量产产品一般靠屏厂在液晶里加温补材料解决。DIY或者小批量产的话把VLCD调在中间值让显示浓度在目标工作温度范围内都能接受就行。要求高的场景可以加一颗热敏电阻做VLCD的自动分压但电路复杂度会增加不少一般不建议为了显示浓度牺牲系统可靠性。6. 选型与扩展HT1621B之外的几个替代方案最直接的替代就是HT1621B的正统前身HT1621。两者引脚和指令基本兼容但HT1621B优化了低功耗特性在很多数据手册里标注的工作电流更低。从供应链角度看HT1621B目前市场上货源充足价格也很便宜大批量一粒通常不到一两块钱直接用B版就好。国内做兼容替代的还有TM1621A这类型号指令集和时序完全兼容HT1621B可以直接贴板替换开发代码不用改。用国产替代最主要的原因是交货周期更短像这两年有些进口品牌芯片交期拉到十几周国产芯片一两周就能拿到货。但替代型号的电气参数、功耗、驱动能力需要重新实测不能只看引脚兼容就盲换尤其是低功耗产品国产和原厂在休眠电流上有时存在几十微安的差距。如果你需要的段数少于128段也可以用尺寸更小、通道数更少的同系列芯片比如64段的版本成本更低。反过来如果产品除了显示还要做按键扫描HT1621B就不够用了需要找带按键扫描功能的型号。我见过不少项目在显示芯片旁边又加了一颗按键扫描芯片其实一开始选型时换一颗带扫描功能的型号就能省掉这个位置。软件层面我在几个正式项目里都没有用硬件SPI去接HT1621B因为GPIO模拟三线确实足够快。显示刷新率的上限不是串行传输速度而是液晶本身的响应速度你用硬件SPI跑2MHz和GPIO模拟跑100kHz肉眼完全看不出区别。反而GPIO模拟的好处是引脚选择自由不受SPI外设和复用功能的限制布线能省很多事。如果你的MCU刚好有SPI空闲且引脚方便也可以用SPI硬控把WR当作SPI的SCK、DATA当作MOSI、CS当作片选时序上注意SPI模式要匹配上升沿采样。最后建议第一次调试HT1621B时别一上来就写完整显示驱动。先点亮一个段再点亮一个数字最后再做整屏映射。这个过程虽然慢但能帮你彻底搞清芯片和屏的工作方式后面出问题时排查起来会快得多。我经历过好几块屏不亮最后都是段位映射表抄错或者VLCD电压不对导致的没有一次是芯片本身的问题。本文还有配套的精品资源点击获取