ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FZH1643段码LCD驱动芯片:I2C键盘扫描一体化方案详解

FZH1643段码LCD驱动芯片:I2C键盘扫描一体化方案详解 干过控制面板类项目的老哥应该都有同感一块段码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.3VFZH1643供电也是3.3V那直接连没问题。但有些面板模块为了方便直接吃5V这时SDA/SCL的通信电压就是5V3.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.3VVSS接地。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.3VINTMCU的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. 配置LCD4COM、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读写、显示点亮、按键扫描这三件事跑通再把业务功能往上加。芯片数据手册一定要对着看不同型号的寄存器定义、引脚功能、偏压配置都可能不一样我给的代码框架可以帮你节约时间但最终还是要以官方手册为准。如果后续项目里遇到功耗要求严苛的情况双模式切换那里值得花时间细调待机状态的扫描间隔和消抖参数那部分的好坏直接影响整机待机电流能不能打出来。祝大家打样一次过屏幕点亮、按键灵敏、通信稳定少走弯路。
返回列表