十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

基于LT165A的2.8寸320X240除湿机彩屏显示方案设计与实现

基于LT165A的2.8寸320X240除湿机彩屏显示方案设计与实现 在做除湿机控制板选型时把显示方案从数码管、LED指示灯或点阵屏换成一块 2.8 寸 320X240 彩屏很多人以为难点只在“把屏幕点亮”。真正开始动手后才会发现彩屏只是一个开始最花时间的反而是如何在上面把当前湿度、设定湿度、运行模式、水箱状态、定时信息清清楚楚地呈现出来并且保证屏幕上的每一个数字和图标都跟压缩机的启停同步。市面上常见的除湿机显示物料并不少数码管方案便宜直接但只能显示几个数字和固定符号段码 LCD 可以多显示一些图标却无法自由排版12864 点阵屏能画图但用来做现代感强的 UI 仍然吃力。于是“MCU 直驱彩屏”或“LT165A 小尺寸 TFT”这类方案就逐渐出现在中高端除湿机、移动空调、净化器和暖风机产品里。这篇文章不是去比较某两个芯片的跑分而是想围绕“LT165A 2.8寸 320X240 除湿机彩屏显示方案”把从面板选型、接口设计、显示驱动、UI 状态管理到联调排错的完整链路讲清楚。你读完之后至少能做出一个可以自己运行、便于后续扩展成产品固件的彩屏显示框架。先给一个总的判断这类 2.8 寸小彩屏方案的价值不在于“显示面积比数码管大”而在于它能用图形化语言把除湿机的运行状态变成用户一眼能看懂的信息。对工程师而言真正的成本也不只是屏幕物料而是显示层与业务逻辑层之间的同步设计。只要你把软件分层、区域刷新、异常显示和状态切换这四件事想明白这个小屏幕方案很稳。1. 除湿机彩屏方案真正要解决的问题1.1 传统显示方案的三个痛点我们先回到产品视角。除湿机的使用场景很特殊用户把机器放在地下室、衣柜旁、卫生间或客厅角落通常不会一直蹲在旁边操作。多数时间用户只是路过时扫一眼屏幕判断两点现在湿度是多少机器有没有正常工作。在传统数字显示方案里用户看到的是一个湿度数字比如“65”。如果环境湿度正在从 75 往 50 降用户只能靠“记性”去对比数字变化感知非常弱。机器有故障时常见的做法是让某个 LED 闪烁用户看到灯亮却不知道是什么意思最后还要翻说明书。触摸式高端机上可能还要做一二级菜单老式按键配合点阵屏操作起来非常绕。这些问题的本质是传统显示硬件能表达的信息密度太低。除湿机这种产品并不是不需要交互界面而是受限于成本业界长期用最低成本的段码或数码管把复杂状态“压缩”成几个符号。1.2 换彩屏后工程挑战变了换成 2.8 寸 320X240 彩屏后硬件表达能力上来了文字、数字、色块、进度条、动画和图标都可以画。但随之而来的不是一个更容易的工程而是一类新的工程问题界面自由度变大以后MCU 软件要处理的事情从“驱动一个七段码”变成“管理一帧 320X240 的彩色图像”。这时候最忌讳的做法是把 UI 代码和压缩机控制代码写在同一个大 while 循环里屏幕刷新一次就阻塞几十毫秒甚至几百毫秒导致按键没响应、传感器读取被延误。很多开发者在“屏幕能不能点亮”阶段浪费了大量时间恰恰是因为一开始就没有把显示当作一个独立的软件模块来设计。所以在开始写驱动之前我建议先想清楚这类产品真正需要的是哪种显示逻辑是“状态展示屏”而不是“可自由触摸的平板”。除湿机的 UI 不需要复杂动画也不需要后台跑一套完整的 GUI 操作系统。它需要的是稳定的状态反馈、清晰的大数字和经得起长时间运行的可靠性。这也决定了我们后面的代码结构可以非常轻量不需要引入重型图形库。2. LT165A 与 2.8寸 320X240 彩屏的基础认知2.1 LT165A 在方案中扮演什么角色“LT165A”这个型号在项目材料中主要是作为一个与 2.8寸 320X240 彩屏配套使用的控制方案出现。针对具体硅片内部集成度和指令集不同厂家、不同批次资料可能有差异所以最稳妥的方式是把它理解为除湿机显示链路里的主控或显示驱动核心。在实际小家电面板设计中这类芯片通常有两种常见形态第一种LT165A 作为主控 MCU 使用。芯片内部集成 CPU、Flash、RAM 和 LCD 控制器既能跑业务逻辑也能直接驱动 TFT 屏。这种形态的优点是 BOM 简单、整体成本低适合除湿机这种功能相对固定、不需要频繁 OTA 升级的应用。第二种LT165A 作为显示协处理芯片使用。外部还有一个专门负责整机控制的 MCULT165A 只接收 MCU 下发的显示命令内部自行完成屏幕刷新、字库读取和图标绘制。这种形态适合主控资源紧张、UI 复杂或需要多级菜单的场景。从节省物料和简化软件链路的角度看除湿机这一类家电更常见的是第一种形态也就是单颗芯片同时完成传感器读取、按键扫描、屏幕刷新和继电器控制。但到底采用哪种形态最终还是要以实际手里那颗 LT165A 的数据手册为准。这里必须提醒一句不要因为某个型号和网上某个教程里的芯片名字相同就认为寄存器地址、初始化序列也完全一致。拿到规格书后第一步要确认的是三件事是否内置 LCD 控制器支持的是 SPI、8080 并口还是 RGB 接口内部是否带显存或支持的最大分辨率为多少。320X240 这个分辨率对多数带 LCD 控制器的芯片来说并不高但接口和显存配置直接决定代码写法。2.2 320X240 分辨率意味着什么320X240 表示屏幕横向有 320 个像素点纵向有 240 个像素点整屏共 320 × 240 76800 个像素。我们平时说的“2.8寸”指的是屏幕对角线长度约为 2.8 英寸。在除湿机前面板上2.8 寸是一个很友好的尺寸比 1.44 寸、1.8 寸的屏大得多能放得下一组 30 号以上的大号湿度数字又比 3.5 寸、4.3 寸屏幕节省前面板空间结构和开模成本都容易控制。真正要让 MCU 处理的是像素数据量。如果采用 RGB565 格式每个像素占 2 字节整屏一帧数据就是76800 × 2 153600 字节约 150KB。如果你的 MCU 内部 RAM 只有几十 KB那它通常是没法在本地保存一帧完整图像的。这时候需要依赖带显存的 LCD 控制方案MCU 可以按区域写入像素屏幕控制器自己负责把显存内容刷新到面板上。这也是 LT165A 这类方案适合 320X240 小尺寸屏的原因之一。2.3 色彩深度与 RGB565 选择TFT 彩屏常见色彩深度有 RGB565、RGB666、RGB888 三种说法。RGB888 理论色彩最丰富但 320X240 下显存开销更高一般小尺寸屏接口也很少真的走 24bit。实践中使用最多的是 RGB565也就是红色 5bit、绿色 6bit、蓝色 5bit。RGB565 的颜色数量是 65536 种对除湿机 UI 来说完全够用。界面里主要是湿度数字、状态文字、模式图标和水箱提示不会出现需要照片级色彩的图像。选 RGB565 还能减小刷新带宽和存储开销让图像刷新更快。这里有个新手容易踩的坑颜色格式里的“RGB”顺序并不一定等于屏幕实际显示的 RGB 顺序。有些 LCD 控制器默认是 RGB 顺序有些是 BGR 顺序。写代码时你给一个红色 0xF800如果屏幕内部按 BGR 解析就可能显示成蓝色或者颜色明显偏色。遇到这种问题不需要改所有绘图代码确认数据手册里是否有类似“BGR/RGB bit”的寄存器位把它反过来即可。3. 显示方案的系统架构与接口选择3.1 两种典型系统拓扑无论 LT165A 是主控还是协处理芯片整个除湿机显示方案可以抽象成下面两条链路。第一种链路是“单芯片直驱型”LT165A 直接连接 TFT 屏模组必要时再接一颗温湿度传感器、几个按键、一个蜂鸣器、一路控制压缩机和风机的继电器输出。这时 LT165A 承担所有工作UI 代码和控制逻辑都运行在同一颗芯片上。优点是整板器件少缺点是如果芯片资源比较紧张大量绘图运算可能会挤占业务逻辑的时间。第二种链路是“双芯片分工型”主控 MCU 负责整机控制和传感器采集通过 UART、SPI 或 I2C 把显示数据发给 LT165A 或带驱动的显示模组显示芯片只负责把数据显示出来。这样主控的压力小UI 升级时也不用动整机主控逻辑。缺点是增加了通信协议设计和 BOM 成本。具体到除湿机项目如果公司是为了把原来三四个 LED 显示的入门机型升级为彩屏显示单颗芯片直驱会更合适。如果产品本身已经有成熟的主控板只是想把原来的盲操作或数码管升级成彩屏那么双芯片分工更合适。3.2 屏幕硬件接口怎么选TFT 液晶模组和主控之间的接口在 2.8寸 320X240 这个规格上最常见的是 SPI 串行接口和 8080 并口。接口类型优点缺点适用场景SPI引脚少占用 GPIO 少布线简单全屏刷新速度较慢需要区域刷新优化低引脚 MCU、UI 以文字数字为主的除湿机8080 并口 8bit速度中等绘图比 SPI 快占用 10 个以上 GPIO线多主控引脚充裕、希望减少刷新等待8080 并口 16bit速度更快占用引脚更多布线压力大相对复杂的 UI 动画场景RGB 接口刷新速度最快需要同步时钟引脚很多通常要外部显存大屏或视频级刷新除湿机不常用从除湿机 UI 的实际内容看它的刷新主要集中在湿度数字变化、模式切换、图标亮灭和局部提示文字。这些变化不需要一秒钟刷新几十帧。选择 SPI 接口时如果代码里有“区域刷新”概念往往也能获得不错的显示体验。更谨慎的建议是优先看 LT165A 本身支持哪种接口再根据主控 GPIO 余量决定。3.3 背光、按键和触摸部分的处理2.8寸 TFT 模组一般都有独立的背光引脚常见是 2 到 4 个 LED 串联需要串限流电阻或由背光驱动芯片供电。对于小家电直接用一个三极管或 MOS 管开关背光再通过 PWM 调节亮度即可。除湿机通常不依赖触摸屏。原因是使用场景里手可能是湿的触摸屏成本更高而且面板容易脏。绝大多数除湿机仍以机械按键、轻触按键或旋钮作为输入彩屏主要承担输出显示。选屏时如果不是非要触摸交互就不要为了“彩屏”买带触摸的模组这样可以少处理触摸校准、触摸中断等一大堆事。如果屏幕模组自带触摸芯片但产品并不使用触摸功能最好在硬件设计时把触摸相关引脚悬空或禁用避免触摸中断引脚浮动导致误触发。这个细节在量产时非常影响稳定性。4. 硬件准备与前置检查4.1 硬件清单搭建一个基于 LT165A 的 2.8寸 320X240 除湿机彩屏显示验证环境至少需要以下部分LT165A 主控板或对应的核心板/评估板2.8寸 320X240 TFT 彩屏模组接口类型与主控匹配温湿度传感器模块用于模拟除湿机环境数据按键输入至少包含模式切换、档位调节两个按键继电器或 LED 负载模拟电路用于验证除湿、风机等输出调试器与串口工具用于下载固件和输出日志3.3V/5V 电源。这些物料中屏幕模组是变量最大的部分。同样是 2.8寸 320X240不同模组厂商使用的 LCD 驱动 IC 可能不同初始化寄存器序列经常不通用。因此一定要向屏厂确认两个文件屏幕规格书中定义的引脚顺序以及该模组控制器推荐的上电和初始化序列。4.2 上电之前必须检查的硬件点我在调试 LCD 项目时发现大部分“白屏”问题其实不是软件问题而是硬件基础配置错了。上电前建议按下面几条检查检查项检查内容逻辑电平主控 I/O 是 3.3V 还是 5V屏幕模组支持的电平是多少必要时加电平转换背光电路背光供电是否独立是否串接了合适的限流电阻避免开机瞬间过流复位引脚屏幕复位脚是否有上拉主控和屏幕的复位时序是否同步电源滤波屏模组电源引脚附近是否加了 0.1uF 和 1uF 去耦电容地线是否完整排线方向软排线或杜邦线是否插反SPI 的 SCK、MOSI、MISO、CS 是否分别对应很多 SPI 屏的从机引脚只支持 3.3V 输入如果主控是 5V 单片机又没有加电平转换长期运行可能烧坏屏控制器的 IO也会产生随机花屏。这一点请务必重视。4.3 软件开发环境软件方面通常使用 Keil MDK、IAR for ARM 或 GCC 工具链中的任意一种。具体选择以 LT165A 可用的编译链为准。使用 Keil 时要注意如果代码中用到 sprintf 等标准库函数需要确认 MicroLib 是否开启否则浮点格式化或字符串格式化函数可能显著增加 Flash 占用甚至导致链接失败。调试手段上至少留一路 UART 日志输出。屏幕显示出现诡异问题时日志里能否看见传感器数据、按键事件和状态切换记录会直接决定排错效率。5. 软件分层与 LCD 初始化流程5.1 显示软件不要写成一大坨除湿机彩屏方案的软件至少应该分成四层层次职责例子应用层按键业务、压缩机控制、定时逻辑按下模式键后切换 modeUI 状态层根据业务状态决定显示内容mode 变化后刷新顶部状态文字控件/绘制层画数字、画进度条、画图标显示当前湿度为 62.0%RHLCD 驱动层初始化屏幕、设置窗口、填充像素写寄存器、发送像素数据多数新手项目之所以乱是把业务状态、UI 控件和 LCD 底层寄存器混在同一个文件里。后期每加一个新功能都要牵动一大段 LCD 代码稍一改动就出现显示异常。正确的方式是应用层只知道“当前湿度是 62.3”不知道湿度数字在屏幕的哪个坐标LCD 驱动层只负责按照传入的矩形和颜色把数据送入屏幕不知道这个数字代表什么。这样测试、维护和复用都会容易很多。5.2 LCD 底层接口设计不管底层的 LT165A 或者屏控制器寄存器怎么变化先定义一套稳定的底层接口是值得的。以下是常见的抽象/* 文件路径app/lcd_port.h */ #ifndef LCD_PORT_H #define LCD_PORT_H #include stdint.h void lcd_hw_init(void); // 硬件复位、GPIO、总线初始化 void lcd_reset(uint8_t assert); // 控制复位引脚 void lcd_write_cmd(uint8_t cmd); // 写命令 void lcd_write_data(uint8_t data); // 写单字节数据 void lcd_write_data_buf(uint8_t *buf, uint16_t len); // 批量写数据 void lcd_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); // 设置窗口 void lcd_backlight_set(uint8_t percent); // 0~100 设置背光亮度 #endif /* LCD_PORT_H */这套接口的好处是上层代码永远不关心这些操作是走 SPI、8080 并口还是写入芯片内部显存地址。将来换一颗主控或换一块驱动 IC 不同的屏只要重写这一层UI 层代码基本不用动。5.3 LCD 初始化步骤彩屏初始化的基本流程并不复杂但顺序很容易出错。下图只是流程描述不需要绘图工具先复位再等待电源稳定随后退出睡眠模式然后配置像素格式、扫描方向、显存访问控制最后打开显示并开启背光。下面给出一个不绑定具体控制器型号的框架把它放在你自己的 LT165A 或屏幕控制器初始序列之前即可。/* 文件路径app/lcd_init.c */ #include lcd_port.h #include stdint.h void delay_ms(uint32_t ms); void lcd_init(void) { /* 1. 硬件复位让屏幕控制器的逻辑回到已知状态 */ lcd_hw_init(); lcd_reset(1); delay_ms(20); lcd_reset(0); delay_ms(120); /* 2. 这里开始是控制器相关初始化序列。 * 注意不同厂家的 LT165A/屏控制器寄存器差异很大 * 下面的命令号只是演示流程请换成实际手册里的值。 */ lcd_write_cmd(0x01); /* 软件复位实际命令号以手册为准 */ delay_ms(120); lcd_write_cmd(0x11); /* 退出睡眠模式 */ delay_ms(20); /* 3. 设置扫描方向和 RGB/BGR 顺序。 * 0x00 通常表示从左到右、从上到下。 * 如果屏幕做成竖屏安装需要结合控制器位定义修改。 */ lcd_write_cmd(0x36); lcd_write_data(0x00); /* 4. 设置像素格式为 RGB565 */ lcd_write_cmd(0x3A); lcd_write_data(0x05); /* RGB565 */ /* 5. 打开显示 */ lcd_write_cmd(0x29); /* 6. 打开背光 */ lcd_backlight_set(80); }代码里的 0x01、0x11、0x29 等命令是从常见的 MIPI DCS 风格命令集里抽象出来的很多 TFT 控制器都兼容或类似但绝不意味着所有控制器都适用。写进项目前要把每一个命令编号和参数都对照一遍 LT165A 或屏幕控制器数据手册。5.4 扫描方向与坐标系2.8寸 320X240 屏在除湿机上经常是竖着安装而不是像电脑显示器那样横着放。如果模组出厂坐标系是横向 320、纵向 240那么竖装后你要么把物理屏倒过来装要么在初始化时通过扫描方向寄存器把显示内容旋转 90 度。此时软件看到的逻辑分辨率会变成 240 宽、320 高。这个区域最容易出问题的不是开机显示 logo而是画局部区域时窗口坐标算错。比如逻辑分辨率是 240X320你却仍然按 320X240 画一个湿度数字的位置结果数字可能被截断或显示到屏幕外。在 UI 层统一使用逻辑坐标并在驱动层通过一个“旋转/镜像映射”函数转换能减少很多麻烦。更简单粗暴的做法是直接把 LT165A 初始化为竖屏扫描方式让 GUI 层始终面向 240 宽 320 高的坐标系开发。6. 除湿机 UI 状态设计与完整示例代码6.1 除湿机界面如何布局先设计一个常见的 2.8 寸除湿机界面布局。屏幕大小有限不适合把所有信息都堆上去建议按信息重要程度分区区域建议内容展示目的顶部状态区当前模式标准除湿、干衣、连续、自动让用户知道机器现在在干什么中部主数字区当前环境湿度例如 62.0%RH除湿机最重要的反馈中部偏下目标湿度条或湿度曲线告诉用户当前湿度离目标还有多远底部图标区水箱满、定时、风机档位、故障告警辅助提醒不要试图在 2.8 寸屏上同时显示 8 个状态图标。图标越多单个图标越小用户越难看清。除湿机用户最关心的是“现在湿度多少”其次才是“什么时候水箱会满”。6.2 用数据结构表达界面状态UI 层需要一份独立的显示数据而不是直接读取 ADC 或按键寄存器。示例结构如下/* 文件路径app/dehum_ui_types.h */ #ifndef DEHUM_UI_TYPES_H #define DEHUM_UI_TYPES_H #include stdint.h typedef enum { DEHUM_MODE_STANDARD 0, /* 标准除湿 */ DEHUM_MODE_DRY_CLOTHES, /* 干衣模式 */ DEHUM_MODE_CONTINUOUS, /* 连续除湿 */ DEHUM_MODE_AUTO /* 自动模式 */ } dehum_mode_t; typedef struct { dehum_mode_t mode; /* 当前模式 */ uint16_t humidity_x10; /* 湿度单位 0.1%RH623 表示 62.3%RH */ int16_t temperature_x10; /* 温度单位 0.1℃235 表示 23.5℃ */ uint8_t fan_level; /* 风机档位0 停止1 低2 高 */ uint8_t water_full; /* 水箱满标志1 表示满 */ uint8_t timer_hour; /* 定时关机小时数0 表示未开启 */ uint8_t sensor_error; /* 温湿度传感器故障 */ } dehum_ui_data_t; #endif /* DEHUM_UI_TYPES_H */这里用湿度乘以 10 后存成整数最直接的好处是 UI 层做格式化时不需要引入浮点数。比如 62.3%RH读取到后存成 623显示时拆成 62 和 3 即可。6.3 主界面绘制与局部刷新下面给出一个极简但可运行思路的主界面绘制函数。它用矩形填充清掉旧数字再显示新的湿度数字和模式文字。/* 文件路径app/dehum_ui_draw.c */ #include dehum_ui_types.h #include lcd_port.h #include stdio.h #define COLOR_BG_RGB565 0x0000 /* 背景色黑色可按 UI 风格修改 */ #define COLOR_TEXT_RGB565 0xFFFF /* 文字色白色 */ #define COLOR_CARD_RGB565 0x7BEF /* 卡片底色深灰 */ /* 底层画填充矩形和字符串的接口由 LcdDriver 层实现 */ void lcd_fill_rect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color); void lcd_draw_string(uint16_t x, uint16_t y, const char *str, uint16_t fg_color, uint16_t bg_color, uint8_t font_size); static void ui_draw_mode_text(dehum_mode_t mode) { const char *mode_text ; switch (mode) { case DEHUM_MODE_STANDARD: mode_text Standard; break; case DEHUM_MODE_DRY_CLOTHES: mode_text Dry Clothes; break; case DEHUM_MODE_CONTINUOUS: mode_text Continuous; break; case DEHUM_MODE_AUTO: mode_text Auto; break; default: mode_text Unknown; break; } lcd_fill_rect(20, 16, 220, 40, COLOR_CARD_RGB565); lcd_draw_string(24, 20, mode_text, COLOR_TEXT_RGB565, COLOR_CARD_RGB565, 16); } static void ui_draw_humidity_value(uint16_t humidity_x10) { char buf[16]; uint16_t x 40; uint16_t y 80; if (humidity_x10 1000) { lcd_fill_rect(x, y, x 180, y 64, COLOR_BG_RGB565); lcd_draw_string(x, y 12, --.-%, COLOR_TEXT_RGB565, COLOR_BG_RGB565, 32); return; } /* 623 - 62.3% */ snprintf(buf, sizeof(buf), %1u.%u%%, (unsigned int)(humidity_x10 / 10), (unsigned int)(humidity_x10 % 10)); /* 先清掉旧数字区域再写新数字 */ lcd_fill_rect(x, y, x 180, y 64, COLOR_BG_RGB565); lcd_draw_string(x, y 8, buf, COLOR_TEXT_RGB565, COLOR_BG_RGB565, 32); } void dehum_ui_draw(const dehum_ui_data_t *ui) { if (ui-sensor_error) { lcd_fill_rect(0, 0, 240, 320, COLOR_BG_RGB565); lcd_draw_string(30, 140, Sensor Error, COLOR_TEXT_RGB565, COLOR_BG_RGB565, 24); return; } ui_draw_mode_text(ui-mode); ui_draw_humidity_value(ui-humidity_x10); /* 底部显示水箱状态这里示意只刷新小图标区域 */ if (ui-water_full) { lcd_draw_string(20, 260, Water full, COLOR_TEXT_RGB565, COLOR_BG_RGB565, 16); } else { lcd_fill_rect(20, 258, 140, 278, COLOR_BG_RGB565); } }这里有一个关键点刷新湿度数字时并没有做整屏清屏而是用一个矩形把要变化的小区域“擦掉”再写字。整屏清屏在 320X240 屏幕上有 76800 个像素要写即使带显存控制器也会有明显的整体闪烁感。局部刷新只写入用户目光聚焦的区域视觉上更流畅。6.4 业务主循环中的状态联动下面这段代码把传感器数据采集、UI 刷新和输出控制放进一个简单的时间片轮询结构里。它不是完整工程重点展示“多长时间刷新一次 UI”“多久读一次传感器”以及“UI 数据和业务数据怎么同步”。/* 文件路径app/main_loop.c */ #include dehum_ui_types.h #include dehum_ui_draw.h #include lcd_port.h #include stdint.h typedef struct { uint32_t last_tick; uint16_t period_ms; void (*handler)(void); } soft_timer_t; static dehum_ui_data_t s_ui {0}; static void sensor_read_task(void); static void ui_refresh_task(void); static void key_scan_task(void); int app_main(void) { lcd_init(); lcd_fill_rect(0, 0, 240, 320, COLOR_BG_RGB565); while (1) { soft_timers_poll(); /* 业务控制逻辑根据当前湿度、模式和湿度传感器状态 * 决定压缩机/风机是否开启真实产品里需要放在更严格的 * 状态机中并加入压缩机延时保护。 */ if (s_ui.sensor_error) { relay_compressor_set(0); relay_fan_set(0); } else if (s_ui.mode DEHUM_MODE_CONTINUOUS) { relay_compressor_set(1); relay_fan_set(s_ui.fan_level); } else if (s_ui.humidity_x10 600) { relay_compressor_set(1); relay_fan_set(s_ui.fan_level); } else { relay_compressor_set(0); relay_fan_set(0); } } return 0; } static void sensor_read_task(void) { uint16_t raw_humi; int16_t raw_temp; uint8_t err; err sensor_read(raw_temp, raw_humi); if (err ! 0) { s_ui.sensor_error 1; } else { s_ui.sensor_error 0; /* 假设驱动返回 raw 值放大 10 倍如 623 表示 62.3%RH */ s_ui.humidity_x10 raw_humi; s_ui.temperature_x10 raw_temp; } } static void ui_refresh_task(void) { dehum_ui_draw(s_ui); }仔细看这段程序你会发现 UI 刷新函数每次都会重新绘制所有会变化的内容。在实际项目里可以进一步增加 dirty 标志比如只有水满标志变化时才去更新底部图标。这种细节对 2.8寸 小屏而言不是性能瓶颈但能明显减少 SPI 总线占用时间降低背光下可见的波纹噪声。7. 运行验证与效果验证7.1 先跑一个最小显示程序写完 UI 层之前先不要直接烧整机程序。最稳妥的方法是先把屏幕调成一个纯色再画几个明显色块最后显示一串数字。第一步清屏为红色观察屏幕是否全红。如果出现蓝色或绿色偏色说明 RGB/BGR 顺序需要调整如果屏幕出现雪花或花屏优先怀疑初始化序列、时钟极性和窗口设置。第二步在固定坐标画一个白边矩形在其中显示 0 到 9 的数字字模验证字体提取方向和扫描方向是否一致。第三步用按键切换模式观察顶部模式文字是否变化同时用万用表或示波器看继电器输出是否跟着切换。7.2 在没有真实除湿机负载时如何验证开发阶段不必真的把压缩机接上。用两颗 LED 分别代表压缩机和风机即可。观察点也很简单当 UI 显示“湿度 75%RH、标准除湿”时代表压缩机的 LED 应点亮当把传感器湿度值调到 50%RH且设定目标湿度为 60%RH 时压缩机 LED 应熄灭。如果用手捏住传感器或用湿毛巾靠近传感器模拟湿度上升同样能看到湿度数字快速上升并触发压缩机启动逻辑。这一步能有效验证“UI 显示数据”和“控制输出数据”来自同一份业务状态而不是各写各的。7.3 判断显示效果是否合格一个除湿机彩屏显示可以交付的标准至少应该包括下面几条开机背光亮起后静态界面无闪烁、无细密麻点、无明显水波纹。湿度数字从 75.0%RH 下降到 60.0%RH 时数字刷新平滑且有合适节奏不会让人感觉数字在乱跳。水箱满后屏幕出现水满图标同时压缩机与风机停止倒掉水后图标消失机器恢复。按键按下后屏幕变化与蜂鸣器提示同步不会出现按一下模式、屏幕切了两档的现象。传感器拔掉或通信异常时显示区域出现“--%”或“Sensor Error”而不是停在最后一次错误值上。如果以上标准都达到说明这个显示方案已经从“能点亮屏幕”进入“能产品化”的状态。7.4 运行失败时先看哪里如果上电后白屏第一步看背光有没有工作。接着看复位时序和初始化命令是否正常。如果背光正常但没有任何内容大概率是屏幕没有正常初始化或 CS 片选、RS/DC 数据命令脚接反。如果屏幕有内容但花屏重点查扫描方向设置、窗口设置、RGB/BGR 顺序、SPI 极性相位。绝大多数花屏不是“像素数据错了”而是控制器把数据放到了错误的显存坐标上。如果文字发虚或明显有重影可能是 SPI 时钟过快、FPC 排线过长或屏幕供电纹波偏大。尝试把 SPI 分频调低并在屏幕电源附近补一个 10uF 电容往往会有改善。8. 常见问题与排查方法下面这张表汇总了除湿机彩屏调试中常见的问题和排查方向。建议收藏备用出现问题后按表格顺序逐项排查。问题现象可能原因排查方式解决方案白屏背光不亮背光电源未接或限流电阻过大万用表量背光两端电压检查背光供电与开关控制白屏背光亮LCD 未初始化成功确认复位时序和初始化命令对照数据手册检查初始化序列花屏或显示错位扫描方向或窗口设置错误打印发送的窗口坐标和数据长度统一坐标系检查扫描寄存器定义红蓝颜色反了RGB/BGR 设置反了显示纯红 0xF800 看是否偏蓝切换控制器的 RGB/BGR 位显示闪烁明显每次都整屏刷新分析刷新耗时改为局部刷新或减少刷新频率湿度数字跳动异常传感器读取间隔太短增加打印观察采样值每 2~3 秒采样一次并做中值滤波湿度为负或乱码传感器故障未处理拔掉传感器观察界面增加 sensor_error 标志并显示“--%”按键切换会同时跳两档按键消抖逻辑简单示波器看按键波形增加 10~20ms 去抖和时间释放判断继电器动作干扰屏幕强电地与信号地布线不合理观察继电器吸合时屏幕变化加强滤波隔离继电器线圈加续流电压不稳导致复位系统电源裕量不足示波器抓 3.3V 波形屏幕开启瞬间电流较大提高电源余量遇到显示异常最快的办法不是反复改代码而是先构造一个最小用例。比如只填充一种颜色、只画一个固定坐标的点把问题范围一步步缩小。经验是硬件问题多半出现在“上电初期”软件问题多半出现在“刷新过程中”。9. 工程化建议与避坑总结9.1 如何让 LT165A 彩屏方案的运行更稳定从工程化角度一套能拿得出手的除湿机彩屏方案应该有三个特质启动可靠、刷新稳定、异常可恢复。启动可靠指上电后屏幕一次就能正常点亮。不要把初始化代码塞到一个不允许延时的中断里执行也不要让复位信号和主芯片复位共用太短的复位脉宽。屏幕控制器需要稳定的复位时序必要时在初始化前加 200ms 以上延时。刷新稳定指 UI 刷新时不阻塞关键控制逻辑。除湿机里的压缩机有延时启动保护要求如果屏幕整屏刷新或字体加载过程把主循环卡住几百毫秒可能导致按键丢失或保护逻辑误判。建议在按键和传感器任务里记录时间戳不使用长时间阻塞延时。异常可恢复指当温湿度传感器通信失败时UI 能进入错误状态并在一段时间后自动重试而不是永远停留在错误画面。界面上的处理比控制策略更简单显示“--%”比显示 0% 或 99% 更能向用户表达真实状态。9.2 代码结构方面的建议无论 LT165A 的寄存器结构如何下面的代码结构都值得保留LCD_PORT 层只做 GPIO、SPI/并口、复位、背光控制LCD_DRIVER 层填写控制器寄存器、设置窗口、像素格式GUI/UI 层不直接碰寄存器只调用绘制矩形、字符串、图标的接口APP 层管理状态机持有 UI 数据和控制输出数据。这样的好处是屏幕厂商后期如果换了同分辨率但不同控制器的面板你只需要换 LCD_DRIVER 层的初始化序列UI 和业务代码都不用动。2.8寸 320X240 显示方案里最难改的从来不是 UI而是底层适配
返回列表