FZH1643段码LCD驱动芯片:I2C键盘扫描一体化方案详解
2026/9/4 18:36:05 网站建设 项目流程

干过控制面板类项目的老哥应该都有同感:一块段码LCD外加十几个按键,看着简单,做起来全是麻烦。主控资源本来就紧张,显示刷新要按时序伺候,键盘扫描要消抖、要防串键,两组外设抢IO还抢中断,画板子的时候恨不得把引脚掰成两半用。我之前做过一个温控器面板,光是显示和按键就占掉了主控将近一半的GPIO,后来又加传感器、加通信,代码里到处是中断和时隙冲突,跑起来总感觉不稳。

后来换了个思路,把显示和按键全丢给一颗外设芯片去扛——就是这次要聊的FZH1643,带键盘扫描的LCD驱动芯片,走I2C接口,支持双模式切换。这玩意儿把段码LCD驱动、矩阵键盘扫描、I2C通信封装成一整个“面板外设”,主控那边只需要读几个寄存器、写几个字节,轻省很多。这篇文章我就围绕FZH1643的方案,从硬件接线、对外I2C接口电路设计、双模式切换,到初始化代码和常见问题排查,完整走一遍,给正要选型或者已经踩坑的朋友做个参考。

1. 为什么不直接用MCU扫键盘?

1.1 传统方案里的三个大坑

很多人第一反应是:段码屏和矩阵按键又不难,MCU直接撸不就完了?确实,小项目、接口少的时候这么干没问题,但一旦面板规模上来,传统方案的问题就很突出。

第一个坑是显示时序。段码LCD不是像点阵屏那样直接写数据就行,它需要COM口和SEG口之间不停切换交变电平,用交流波形驱动液晶分子。MCU得开着定时器持续刷新波形,中间一旦被高优先级中断打断,波形错了屏幕就闪,甚至出现残影。做产品的时候,显示刷新这类低频实时任务混在主循环里,很容易被其他任务“饿死”。

第二个坑是按键扫描和显示抢资源。矩阵按键需要周期性扫行、读列,还要做消抖。消抖一般用定时器累加计数,这就要占用一个定时器中断。显示刷新也要定时器,通信也要中断,多个中断优先级调来调去,代码复杂度直线上升。要是再碰上有组合键、长按、双击这类需求,状态机写到一半就想摔键盘。

第三个坑是IO占用。一块4位数的段码屏,动态扫描通常要4个COM加若干SEG,假设是4COM×16SEG,就要20个IO。矩阵键盘4×4再来8个IO。两部分加一起接近30个IO,中小型MCU的QFP封装都未必够用,还得上扩展IO芯片,小板子根本塞不下。

1.2 一体化方案到底省了什么

FZH1643这类芯片的逻辑,就是把这个“又占IO、又占时序、又占中断”的面板子系统整体抽象成一个I2C从设备。MCU只接两根线(SDA和SCL),最多再加一根INT中断引脚,就能同时控制显示和读取按键状态。芯片内部自己负责LCD波形刷新,自己循环扫键盘,主控完全不用关心这些底层的周期任务。

我对比过两种方案在同一个项目里的表现,直接上表看:

对比项传统MCU直驱FZH1643一体化方案
MCU GPIO占用20~30个引脚最多3个(SDA、SCL、INT)
显示刷新任务MCU定时器持续介入芯片自动处理
按键消抖处理软件状态机+定时器芯片扫描后直接给键值
休眠功耗控制要人工关LCD、停中断双模式硬件切换
底板面积走线多、容易拥挤布线简洁,板子明显小一圈
调试难度波形问题肉眼不可见I2C抓包,逻辑分析仪一目了然

所以这类芯片非常适合温控器、电磁炉面板、微波炉操作板、血压计、血氧仪、智能家居控制面板等产品。思路就是:面板越复杂,越值得把“显示+按键”外包出去。

2. FZH1643核心特性逐一拆解

2.1 LCD驱动是怎么“自己跑起来”的

段码LCD驱动的原理,我尽量用白话讲清楚。LCD段码点亮,靠的是COM和SEG两个电极之间的电位差,而且必须是AC波形——如果两端长期加直流电压,液晶材料会极化,屏幕几个月就坏了。所以驱动芯片要不断翻转极性,让每个像素上的平均直流分量为零。

FZH1643内部有时序控制器,它会按照设定的duty(占空比)和bias(偏压比)自动生成COM扫描波形,我只需要往显示RAM里写1或写0,芯片就负责把这个数据翻译成对应SEG引脚的输出状态。比如常见的4COM驱动,芯片一帧内依次扫4个COM,每个COM开启时间是1/4,配合SEG和COM之间的电压差,就能确定每一个交叉点的段码是亮还是不亮。

这个“自动刷新”的价值在于,主控不管在忙什么,屏幕显示都不会断。就算MCU被高优先级中断塞满了,屏幕照样稳定输出。而且显示刷新率和LCD偏压都由芯片内部NVM或寄存器配置,一般帧率做到60Hz以上,人眼看不出闪烁。开发时完全不用像直驱方案那样反复调波形时序。

2.2 双模式切换:正常工作与低功耗唤醒

FZH1643特色的“双模式切换”,我理解下来就是指两种工作模式之间的切换:

  • 模式A(正常工作模式):LCD显示开启 + 键盘扫描全速运行。这是设备正常运行时的状态,主控通过I2C读写显示数据和键值。
  • 模式B(低功耗/待机模式):LCD显示关闭,键盘扫描降频或维持低功耗检测。芯片会持续监视按键矩阵,一旦检测到有按键按下,通过INT引脚输出一个唤醒信号给主控,主控再切换回模式A。

这个设计对应的产品场景特别典型:控制面板多数时间处于待机状态,屏幕常亮费电,但按键必须随时可用。如果让MCU一直醒着监听按键,电流就压不下去;如果MCU睡了,又要额外电路来检测按键唤醒。FZH1643把这两端都包了,相当于一个带唤醒功能的面板协处理器。

进入模式B前,需要先把LCD显示关掉,再配置芯片进入低功耗状态。按键检测到什么算“有效”,芯片内部会有消抖机制,不会一碰就触发中断。这一点在电池供电的便携设备里特别有用,整体待机电流可以压得很低,而主控只需要处理一个外部中断再恢复显示就行。

2.3 I2C接口与寄存器架构

通信接口用的是I2C,这一点对主控来非常友好。I2C从机地址可以通过外部引脚配置,也就是说如果项目里有两块独立的面板,可以在同一根I2C总线上挂两颗FZH1643,分不同地址访问,互不干扰。

寄存器层面,大致分成几类:

  • 系统控制寄存器:负责芯片开关、模式切换、振荡器控制、显示开关。
  • LCD配置寄存器:设置占空比(比如1/4DUTY)、偏压比(1/3BIAS或1/2BIAS)、刷新率、VLCD对比度调节。
  • 显示RAM区域:每个段码对应一个bit或某个地址位,往对应位写1点亮段码。
  • 键盘扫描配置寄存器:启用/关闭键盘扫描,设置扫描间隔、消抖时间、INT中断使能。
  • 键盘键值寄存器:存放最近扫描到的按键编号,或直接用矩阵行列组合编码表示。

主控侧驱动逻辑就变得很直接:开机时把系统控制、LCD配置、键盘配置各写一遍;日常把显示数据写入显示RAM;有INT中断时,通过I2C读取键值寄存器,判断哪个按键被按下。以前那些繁琐的底层刷新全都不需要了。

3. 对外I2C接口电路设计要点

3.1 上拉电阻怎么选、怎么算

I2C总线是开漏结构,SDA和SCL的拉高完全靠外部上拉电阻完成,所以上拉电阻选不好,整个通信电路就废了一半。很多人在这一步栽跟头,回头就骂芯片不稳定,其实问题大概率出在电阻上。

上拉电阻的取值需要同时满足两个边界条件。一个是上升沿时间不能太长,否则高速通信时波形还没拉高,下一个时钟沿就来了,数据直接错。根据I2C规范,400kHz快速模式下信号的上升时间tr要小于300ns。电阻的最大值可以用下面的关系估算:

[ R_{P(max)} \approx \frac{t_r}{0.8473 \times C_{bus}} ]

比如总线上所有芯片引脚电容加PCB电容估算为150pF,那么:

[ R_{P(max)} \approx \frac{300 \times 10^{-9}}{0.8473 \times 150 \times 10^{-12}} \approx 2.36k\Omega ]

这个150pF在长走线、多设备的情况下很容易达到。如果走线很短、只有主控和一颗FZH1643,总线电容可能只有50pF左右,那电阻可以放宽到:

[ R_{P(max)} \approx \frac{300 \times 10^{-9}}{0.8473 \times 50 \times 10^{-12}} \approx 7.08k\Omega ]

另一个边界是电阻不能太小,否则灌电流过大。I2C规定IO输出低电平时VOL不超过0.4V,通常会限制灌电流在3mA左右。3.3V系统下电阻最小值约为:

[ R_{P(min)} \approx \frac{3.3V - 0.4V}{3mA} \approx 0.97k\Omega ]

所以一个很常见的取值区间是2.2kΩ到4.7kΩ。我在3.3V系统、400kHz速率、板内短走线场景下,通常直接选2.2kΩ;如果总线拉得比较远、用排线接到另一块面板,优先保证上升沿,选2.2kΩ或更低一些。100kHz模式下对上升沿要求宽得多,4.7kΩ甚至10kΩ也可以跑起来,但我不建议无脑加大,宁可多留余量。

3.2 电平匹配与总线保护

对外I2C设计还有一个容易忽略的点——电平域。如果主控是3.3V,FZH1643供电也是3.3V,那直接连没问题。但有些面板模块为了方便直接吃5V,这时SDA/SCL的通信电压就是5V,3.3V的MCU引脚不一定能承受5V高电平,反过来芯片也可能不认3.3V的高电平。

稳妥的做法是电路设计前就把电平域统一。要么芯片和主控都用3.3V,要么在中间加电平转换电路,比如用双MOSFET双向电平转换器来跨电平域通信。千万不要图省事直接拿电阻分压糊弄,I2C的上升沿本来就靠外部上拉,再加电阻分压会进一步拉慢边沿,高速模式下很容易翻车。

此外,如果I2C引出到面板排线,属于对外接口,建议在线上串联一个小阻值电阻,比如33Ω到100Ω,配合总线电容能够抑制信号振铃,对EMC也有帮助。有条件的情况下,在SDA和SCL对地各并联一个小电容,比如10pF,用来滤掉高频毛刺,但要控制容值别太大,否则会拖慢上升沿,必要性视具体环境而定。

3.3 PCB布线与抗干扰实战

这个主题下最容易被忽视的反而是接地和走线。我见过好几个项目功能测试正常,一到整机EMC测试就挂,示波器一抓,I2C总线上全是干扰脉冲。原因基本都是SDA、SCL走线绕了一大圈,旁边还贴着开关电源的反馈走线,噪声直接耦合进去。

对外I2C走线要注意几条:SDA和SCL两根线尽量靠近走,但要和高压、高频走线拉开距离,特别是不要去跨过开关电源的电感区域;如果必须跨层,要有完整的地平面做参考,不能走线下面正好是分割区;地线尽量短粗,芯片的地和主控的地保持同电位。

如果面板和主板之间通过排线连接,那就要考虑排线长度和接口保护。长排线会增加总线电容,也更容易被外部干扰触发误动作,解决办法是降低通信速率到100kHz,加强上拉驱动能力,接口处加TVS管做ESD保护。产品要做认证的话,这些细节省不了。

FZH1643如果有地址配置引脚,不能悬空,必须按数据手册要求接固定电平,否则上电后从机地址随机变化,主控扫描I2C总线时设备时有时无,排查半天都找不到原因。

4. 硬件接线与键盘/LCD配置实操

4.1 最小系统接线方案

FZH1643最小系统非常精简,外围元件屈指可数。以我实际用过的一套接线为例,整个面板模块的BOM比原来直驱方案少了一大半:

  • VDD接系统电源3.3V,VSS接地。VDD旁边必须放0.1µF陶瓷电容,芯片内部电路瞬间电流变化需要就近储能,最好再并联一个10µF钽电容或MLCC用于低频去耦。
  • VLCD引脚是LCD偏压输入。常见做法是在VLCD和VDD之间接一个偏压电容,比如0.1µF到1µF,具体值看手册建议。这个电容影响LCD偏压的稳定度,太大会拖慢显示建立速度,太小会出现显示不均匀。
  • COM0~COM3和SEG引脚接段码屏的对应引脚。段码屏的COM和SEG分配以LCD厂家的脚位图为准,接错之后显示内容就错乱成一团,排查时需要对照屏的引脚定义逐一核。
  • 键盘矩阵的行列引脚接按键矩阵。假设用4×4键盘,行线和列线分别接芯片的键盘扫描引脚,每个按键跨接在同一行、同一列的交叉点上。

下面是一个简化的接线列表,具体以芯片实际引脚为准:

信号连接到说明
VDD3.3V芯片主电源
VSSGND芯片地
VLCD偏压电容到VDDLCD对比度偏压
SDA/SCLMCU对应I2C引脚外部上拉到3.3V
INTMCU的GPIO外部中断引脚按键唤醒/报警
AD (如果存在)VDD或GND配置I2C从机地址
COM0~COM3LCD的COM引脚公共电极
SEG引脚组LCD的SEG引脚段电极
键盘行/列引脚按键矩阵行列交叉接按键

4.2 显示对比度与偏压设置

LCD显示最直观的问题就是对比度。同样是FZH1643,不同厂家、不同尺寸的段码屏,工作电压和对偏压的要求不一样,所以对比度一般要留软件调节手段。

FZH1643这类芯片通常有LCD偏压倍率或者VLCD调节寄存器,可以在一定范围内微调VLCD电压。简单场景下,也可以直接在VLCD引脚处用电阻分压或电位器手动调整。这里给个经验:如果屏幕显示太淡,先把VLCD电压往上抬,或者把偏压电容适当加大;如果显示发黑、出现不该亮的段码,说明VLCD太高或者偏压模式选错了。

开关LCD时还要注意偏压电容的充放电。上电后不要立刻开显示,先等芯片内部振荡器稳定,通常延时几十毫秒再写显示控制寄存器。如果上电瞬间直接开显示,偏压还没建立,屏幕会出现短时间的乱码闪烁,放产品里第一印象就很拉胯。

4.3 键盘矩阵连接与扫描原理

矩阵键盘的扫描原理很好理解:芯片逐行输出高电平(或低电平),同时读回每一列的状态,如果某一列的电平被拉过去了,说明该行该列的按键被按下。芯片周期性地做这个扫描,一次扫描周期内可以覆盖整个矩阵。

FZH1643把扫描也做进了硬件里,通过寄存器配置好行数、列数、扫描间隔和消抖时间之后,主控基本不用管。需要注意的是矩阵键盘的公共端和扫描端与芯片引脚之间的映射关系,千万不能按错,否则按下按键后读到的键值永远是乱的。

从硬件可靠性角度,我习惯在按键行线的每个引脚上串联一个1kΩ左右的小电阻,作用是在误接、静电或线缆磨损时限制电流,保护芯片IO。另外按键本身要做防抖动设计,软件上可以在读键值后做延时确认,硬件上如果按键是机械触点,芯片内部的消抖寄存器要记得配置,不是默认值就好使。

5. 软件配置与驱动代码示例

5.1 初始化序列怎么写

FZH1643的软件驱动,关键是把初始化顺序写对。我提供一份参考框架,具体寄存器地址和位定义以你的型号数据手册为准:

#define FZH1643_ADDR_W 0x40 // 从机写地址,具体值由AD引脚决定 #define FZH1643_ADDR_R 0x41 // 从机读地址 // 初始化函数 void fzh1643_init(void) { // 1. 上电后等芯片内部电压稳定 delay_ms(50); // 2. 系统控制寄存器:开振荡器、关显示,先做配置 i2c_write_reg(FZH1643_SYS_CTRL, 0x01); // 打开时钟,先关LCD显示 // 3. 配置LCD:4COM、1/3偏压、正常刷新率 i2c_write_reg(FZH1643_LCD_CFG, 0x23); // 示例值,按手册计算 // 4. 设置对比度:VLCD寄存器 i2c_write_reg(FZH1643_VLCD_CFG, 0x18); // 需要根据实际屏幕微调 // 5. 清空显示RAM,避免上电乱码 fzh1643_clear_display(); // 6. 配置键盘扫描:4x4矩阵,开启消抖 i2c_write_reg(FZH1643_KEY_CFG, 0x11); // 扫描使能 + 消抖时间档位 // 7. 清掉键盘INT标志,再开INT中断 i2c_write_reg(FZH1643_INT_FLAG, 0x00); i2c_write_reg(FZH1643_INT_EN, 0x01); // 8. 最后才打开LCD显示,避免上电乱闪 i2c_write_reg(FZH1643_SYS_CTRL, 0x03); // 振荡器 + LCD显示使能 }

这段代码虽然用了示例寄存器名,但逻辑顺序是通用的:先稳定电源,再关显示做配置,清RAM,配置键盘,最后开显示。很多人上来就开显示,后面调对比度、清RAM反而留下好几个上电闪屏的隐患。

5.2 写显示、读按键的代码框架

写显示数据其实就是往FZH1643的显示RAM填充bit。为了减少I2C传输次数,可以把显示缓冲整理成连续字节,一次性写入芯片的显示RAM起始地址。代码框架大概是这样:

void fzh1643_update_display(const uint8_t *buf, uint8_t len) { i2c_start(); i2c_write_byte(FZH1643_ADDR_W); i2c_write_byte(FZH1643_DISPLAY_RAM_ADDR); // 从显示RAM首地址开始 for (uint8_t i = 0; i < len; i++) { i2c_write_byte(buf[i]); } i2c_stop(); }

读按键更简单。有INT引脚的话,让主控睡在外部中断上,INT来了才去读键值寄存器:

// INT中断服务函数回调中处理 void fzh1643_handle_key_interrupt(void) { uint8_t key; key = i2c_read_reg(FZH1643_KEY_VALUE_REG); if (key != 0xFF) { // 0xFF通常表示无按键 process_key_event(key); } // 读完清掉INT标志 i2c_write_reg(FZH1643_INT_FLAG, 0x00); }

读取键值后一定要清中断标志位,否则INT引脚会一直拉着低电平,MCU的中断脚会被反复触发,表现就是按键一次触发好几遍,还把主循环卡得死死的。

5.3 双模式切换的软件处理

双模式切换的软件逻辑会比较简单,但有一个细节值得提:进入低功耗之前的顺序。

建议先禁止键盘INT中断,再关LCD显示,等显示关闭完成之后,再写系统控制寄存器进入低功耗模式。如果顺序反了,可能在关显示的瞬间触发一次INT,导致刚睡下就被叫醒。

void fzh1643_enter_standby(void) { i2c_write_reg(FZH1643_INT_EN, 0x00); // 先关中断 i2c_write_reg(FZH1643_SYS_CTRL, 0x01); // 关LCD显示,保持振荡器 delay_ms(10); // 等偏压泄放,显示彻底熄灭 i2c_write_reg(FZH1643_SYS_CTRL, 0x00); // 进入低功耗待机 } void fzh1643_wakeup_to_normal(void) { i2c_write_reg(FZH1643_SYS_CTRL, 0x01); // 恢复振荡器 delay_ms(50); // 等待LCD偏压稳定 fzh1643_clear_display(); i2c_write_reg(FZH1643_LCD_CFG, 0x23); // 重新配置LCD参数 i2c_write_reg(FZH1643_VLCD_CFG, 0x18); // 重新设置对比度 i2c_write_reg(FZH1643_SYS_CTRL, 0x03); // 开LCD显示 i2c_write_reg(FZH1643_INT_EN, 0x01); // 重新使能INT i2c_write_reg(FZH1643_INT_FLAG, 0x00); // 清标志 }

从低功耗模式唤醒之后,显示RAM的内容有两种可能:有的芯片会保留,有的芯片会清零。如果没确认这个行为,容易出现“唤醒后显示数据还在”或“唤醒后花屏”的情况,最稳妥的做法是唤醒后无论RAM是否保留,都重新刷新一遍显示数据,耗不了多少时间,但能省掉一堆奇怪问题。

6. 常见问题与排查技巧

6.1 I2C通信异常

这类芯片如果I2C通信不正常,第一步就废了,后面什么显示、键盘全是空谈。实际中遇到最多的问题集中在这几个现象:

现象一:主控发送地址后收不到ACK,或者ACK时有时无。先查器件地址配置引脚是不是没接,再查SDA、SCL是不是接反了,最后用示波器看波形,确认SDA和SCL上有没有正常上拉的电压。如果上拉电阻焊错成0Ω或者根本没焊,总线就是一条低电平,永远不会ACK。

现象二:低速通信正常,一上400kHz就出错。大概率是上拉电阻偏大,或者总线电容太重。解决办法是降低速率到100kHz先定位问题,如果降速后OK,说明是边沿时间问题,换更小的上拉电阻,或者优化走线减短总线长度。

现象三:同一总线上挂多个设备时互相干扰。检查是不是两个设备地址冲突了。FZH1643如果支持AD引脚配置地址,要确认AD引脚电平没被焊接短路,地址不能和其他I2C设备重复。

排查I2C问题,我强烈建议用逻辑分析仪抓波形,二十四通道的那种就行,看起始条件、地址、数据和停止条件是否完整。软件上做逐个寄存器读写测试也是个好办法,比直接跑完整驱动容易定位。

6.2 屏幕全亮、全灭、显示模糊

屏幕显示异常是最能劝退新手的,但其实很大一部分是配置和硬件接法问题。

屏幕全亮,或者不该亮的段码全亮了,常见于COM和SEG引脚和LCD屏的脚位定义对不上,以及偏压模式配置错误。LCD屏自身的COM、SEG编号有固定顺序,不是随意接的,画板之前必须先拿到屏的规格书,把每个脚对应的COM/SEG标号列清楚,再和芯片引脚表一一对应。

屏幕整体发淡,大概率是VLCD偏压不够。做个简单实验:把VLCD寄存器值往大调几个档位,看屏幕是不是变清晰,如果变清晰了就说明偏压不足。另一个原因是偏压电容掉了或者选值过小,导致LCD驱动波形供不上压。

屏幕有“鬼影”,就是不该亮的段常见微亮,一般是偏压电容容量偏小,或者是刷新频率设置过低。偏压电容往0.47µF、1µF这个挡位调,刷新率往高挡位设,鬼影通常能解决。液晶屏自身品质太差也会鬼影,这种就只能换屏供应商。

6.3 键盘误触发、按下没反应

按键问题排查相对直接。

按下没反应:先用万用表量按键在没有按下和按下时的导通情况,排除按键损坏或漏焊;然后量芯片按键扫描引脚上有没有周期性的扫描波形,没有波形就去查键盘扫描使能寄存器和INT使能;如果有波形,就看键值寄存器有没有更新。

误触发、按键按一下当成好几下:先检查消抖配置,芯片的消抖寄存器有没有使能,消抖时间是不是太短;再做软硬件配合,软件里按键事件处理增加一个短期屏蔽窗口,比如50ms内同一按键只处理一次。

按键行列接反、行列引脚和芯片映射关系搞错,也会出现按键功能串位,按“+”出来的是“-”这种离谱问题。这种情况不是芯片坏了,是接线和寄存器配置不匹配,仔细核对芯片手册中的键盘扫描引脚顺序和按键矩阵的接法就能解决。

7. 最后再补充一点个人经验

我用FZH1643这类带键盘扫描的LCD驱动芯片做了几个项目之后,最大的体会是:这类芯片真正的价值不只是省IO,而是把显示刷新和按键扫描这两类“脏活累活”从主控里彻底剥离了出去。主控只管业务逻辑,整个软件架构清晰了一大截,调试起来心情都不一样。

给准备上车的朋友一个建议:先不要急着画正式主板,拿一颗芯片、一块段码屏、一个4×4键盘,搭建最小验证板,先把I2C读写、显示点亮、按键扫描这三件事跑通,再把业务功能往上加。芯片数据手册一定要对着看,不同型号的寄存器定义、引脚功能、偏压配置都可能不一样,我给的代码框架可以帮你节约时间,但最终还是要以官方手册为准。

如果后续项目里遇到功耗要求严苛的情况,双模式切换那里值得花时间细调待机状态的扫描间隔和消抖参数,那部分的好坏直接影响整机待机电流能不能打出来。祝大家打样一次过,屏幕点亮、按键灵敏、通信稳定,少走弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询