RA8835驱动320240液晶屏:初始化、绘图与STM32移植

RA8835驱动320240液晶屏:初始化、绘图与STM32移植 1. RA8835 到底是什么为什么还在用RA8835 是深圳驰宇微主推的一颗液晶驱动控制器兼容 S1D13305/SEIKO EPSON 系列。它内置 32KB 显示 RAM支持 8080/6800 并行接口最大可驱动 640x256 的理论范围实际工控屏最常见的是 320x240。很多新人看到 RA8835 会下意识觉得“古老”但这个东西一点也不落后。在 3.8 寸、5.1 寸、5.7 寸这种中小尺寸工业屏上RA8835 方案一直很稳定成本低、开发资料多、替代方便。用 STM32、GD32、STC 都能驱动不像某些专用彩色屏芯片换个 MCU 型号就要重新折腾一遍底层驱动。这篇文章主要讲清楚三件事RA8835 控制器和 320240 屏的硬件连接、初始化流程和寄存器配置、跨尺寸移植时容易踩的坑。适合想快速把这几个尺寸的屏用起来、又不想被一堆晦涩寄存器劝退的工程师。从我实际测试的经验看RA8835 驱动 320240 的过程比很多人想象的简单真正的坑主要在时序、显存组织还有不同尺寸屏之间的代码复用。如果把这个骨架搭好了后面换 5.1 寸、3.8 寸就是改几个参数的事不用从零开始查手册调时序。2. 芯片、屏和接口的关系先别急着写代码2.1 控制器和屏不是一回事很多刚入手的新人会搞混一个概念RA8835 是“控制器”不是“屏”。320240 液晶屏通常由液晶玻璃、偏光片、驱动电极和外围电路组成。玻璃本身不会显示需要 RA8835 这个“大脑”负责显存管理、产生扫描时序、把数据送到液晶驱动电路。所以买屏的时候经常看到两类模块带 RA8835 控制器的模组通常叫 LCM背面有一颗主控芯片用户只需要接并行总线并往寄存器写数据。不带控制器的玻璃/COG 模组这种要自己配 RA8835 或者直接接 MCU 的 LCD 控制器难度高一个量级。驰宇微这些 3.8 寸、5.1 寸、5.7 寸的 320240 屏基本都是带 RA8835 控制器的模组。用户操作的对象是控制器不是玻璃本身。所以本质上你是在和一颗“老朋友”芯片打交道只要会操作 RA8835这三个尺寸屏的显示控制思路就完全一样。2.2 接口信号RA8835 支持 8080 和 6800 两种并行时序常用的是 8080。典型引脚如下。引脚方向功能D0-D7双向8 位数据总线CS输入片选低有效A0输入寄存器/数据选择有的屏标 RSWR输入8080 写时序RD输入8080 读时序RESET输入复位低有效VDD/VSS-电源/地VOUT/VDH/VDL-偏压电源模块内部生成则不需接实际使用中A0 决定命令还是数据。写命令时 A00写数据时 A01。这一条最容易出问题很多人把命令和数据全当数据写结果屏幕花屏或者完全不亮。另一个常见低级错误是 WR 和 RD 接反写函数发的是 RD 脉冲那不管怎么调寄存器屏幕都没反应。2.3 接口电平RA8835 工作电压一般为 2.7V~5.5V5V 单片机可以直接连3.3V MCU 也能稳定驱动前提是选择 3.3V/5V 兼容的模组。我用 STM32F103 3.3V 直连过 5V 版本的 320240 屏多数情况下能工作但不建议长期这么干最好接电平转换或者直接选 3.3V 版本。这里还有个容易被忽略的坑3.3V 系统驱动 RA8835 时如果屏模块上的上拉电阻都是接 5V 的IO 口可能被倒灌电流。时间久了 MCU 引脚会出问题。布线之前最好看一下模块原理图确认 A0、CS、WR、RD 这些引脚有没有外部上拉。3. 三个尺寸的差异和选型不是越大越难3.1 3.8寸、5.1寸、5.7寸的共性三款都工作在 320x240 分辨率下也就是说 RA8835 的初始化代码几乎可以完全通用。显存组织方式也一样内存是按 8 点为一字节排列的不是连续像素一个字节。这点和很多彩色屏不一样一定要记牢。除此之外这三款屏的常用偏压、行扫描方式基本一致所以 3.8 寸调通的驱动改一下背光控制和屏幕参数就能驱动 5.7 寸。我实际做过一个项目同一个 .c 文件只改了引脚宏定义就从 5.1 寸换到了 3.8 寸界面没做任何调整。3.2 各尺寸的实际差异尺寸常见可视区域特点适合场景3.8 寸约 76.8x57.6mm体积小功耗低适合嵌入式手持设备数据采集、仪表、小面板5.1 寸约 103.9x77.6mm显示面积适中性价比高工控人机界面、医疗器械5.7 寸约 115.2x86.4mm最大信息量足视野好工业控制台、设备终端这里说明一下具体可视区域和外形尺寸以厂家规格书为准我写的是常见的参考值不同批次和不同背光方案可能略有出入。选型时建议关注三件事安装尺寸、背光电压/电流、有没有触摸屏。触摸版和非触摸版的排线定义通常不同软件上可能要多一个触摸控制 IC 的驱动。3.3 选型和替换的注意事项确认模块是 320x240不是 240x320。虽然都是两个数字但横竖屏差异会导致初始化参数完全不一样240x240 的方屏也常被混淆。确认接口间距和排针方向。5.7 寸的 FPC/排针位置和 3.8 寸往往不同软件可以统一硬件要单独做板。确认背光 LED 灯串数量。5.7 寸背光功耗明显高如果沿用 3.8 寸的背光驱动电路可能带不动亮度也不均匀。一句话总结RA8835 驱动软件层面可以一套通吃三个尺寸但硬件、背光、结构孔位必须按具体尺寸重新核对。4. 初始化时序和关键寄存器照着配就能亮4.1 上电和复位RA8835 上电后不要立刻初始化先等待电源稳定。我测过的最小要求是 VDD 稳定后至少等待 1ms然后拉低 RESET 复位信号保持至少 100us再拉高再等待 50ms 以上再开始写寄存器。这个顺序写反会经常出现“偶尔正常、偶尔白屏”的怪病。尤其是用 DC-DC 供电时电源建立时间比较长MCU 启动完了屏幕还没准备好。我见过不少同事复位后只延时 5ms 就初始化结果十块板子里有两三块起不来改成 50ms 后全部稳定。4.2 常用初始化代码8051 风格以下是一段可以直接修改使用的初始化举例。命令和数据用不同函数封装。#define LCD_COMMAND 0 #define LCD_DATA 1 void lcd_write_cmd(unsigned char cmd) { LCD_CS 0; LCD_A0 0; // A00 命令 LCD_WR 0; P0 cmd; LCD_WR 1; LCD_CS 1; } void lcd_write_data(unsigned char dat) { LCD_CS 0; LCD_A0 1; // A01 数据 LCD_WR 0; P0 dat; LCD_WR 1; LCD_CS 1; } void lcd_init(void) { delay_ms(100); // 上电稳定 LCD_RESET 0; delay_us(10); LCD_RESET 1; delay_ms(50); lcd_write_cmd(0x40); // SYSTEM SET lcd_write_data(0x30); // P1: 每行 1 个字节生效 // 按 320x240 常见参数配置 lcd_write_data(0x87); // P2: 字符宽度-1 lcd_write_data(0x07); // P3: 字符高度-1 lcd_write_data(0x27); // P4: 字符间距 lcd_write_data(0x39); // P5: 点阵行数-1 lcd_write_data(0xEF); // P6: 扫描行数低位 lcd_write_data(0x00); // P7: 高位 lcd_write_data(0x00); // P8: 光标位置等 lcd_write_cmd(0x44); // SCROLL lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_cmd(0x5A); // HDOT SCR lcd_write_data(0x00); lcd_write_cmd(0x5B); // OVLAY lcd_write_data(0x0C); // 2层合成正常显示 lcd_write_cmd(0x5C); // DISP ON/OFF lcd_write_data(0x54); // 开启显示光标等 lcd_write_cmd(0x5D); // DISP ADR lcd_write_data(0x00); lcd_write_data(0x00); }这里参数需要特别说明RA8835 的 SYSTEM SET 和 SCROLL 寄存器和具体分辨率强相关不同厂家给出的示例值可能不一样。上面这份是 320x240 比较通用的一版我实际在驰宇微 3.8 寸上验证过但换屏后最好对照规格书确认 P2、P5、P6、P7 的值。P2 对应每行字节数相关P3 对应字符高度P5-P7 决定扫描行数。320 点宽度、单色模式、8 点一字节时水平方向 320 点就是 40 字节。4.3 为什么一上来就是 0x40 而不是别的RA8835 的指令集以 SYSTEM SET 为起始。芯片上电后MCU 必须首先发送 SYSTEM SET然后才能执行 SCROLL、OVLAY 等后续指令。如果不发 SYSTEM SET 直接写显示数据写入内容根本不会进入正确的显存映射。这个顺序在许多 S1D13305 兼容控制器上都是一样的。所以移植代码时如果发现命令全写了屏幕没反应先检查是否漏了 SYSTEM SET、参数个数是否匹配。SYSTEM SET 后面必须跟着 8 个参数字节一个都不能少否则芯片内部状态机就乱了后续命令全都不认。4.4 显存寻址和点阵关系RA8835 内置 32KB 显存按层、按字节管理。320x240 单色显示一屏数据量是 320 / 8 * 240 9600 字节。 双图层合成时大概用到 19200 字节32KB 完全够。重要的是显存地址不一定是逐行从左到右连续排列具体由 SCROLL 寄存器配置。很多花屏、错位问题都是显存地址计算错了。建议在初始化完后先不要急着画图而是全屏写 0x00 或者 0xFF观察是否为规则满屏再开始测试几何图形。RA8835 的显存读写地址也要先发命令设置。常用命令是 0x46MCURSOR和 0x47MWRITE配合或者用 0x24 设置光标地址后连续写。不同版本驱动代码习惯不一样我这里推荐一个简单方式设置地址用 0x46设置成自动递增地址模式然后连续写数据效率最高。5. 底层绘图的实现点、线、区域、字符5.1 画点函数是所有图形的基础显示数据按字节存放一个字节对应 8 个水平点。设定好显存地址后画点就是要读出该字节、修改某一位、再写回去。不能在原地址上只写一个字节否则会覆盖同一字节里的其他 7 个点。画点示例void lcd_set_pixel(unsigned int x, unsigned int y, unsigned char color) { unsigned int addr; unsigned char data_byte; if (x 320 || y 240) return; addr (y * 40) (x / 8); lcd_set_memory_cursor(addr); // 设置显示 RAM 地址 data_byte lcd_read_data(); // 读出该字节 if (color) { data_byte | (0x80 (x % 8)); } else { data_byte ~(0x80 (x % 8)); } lcd_set_memory_cursor(addr); lcd_write_data(data_byte); }这里 addr 的计算方式适用的是“单层、逐行、每行 40 字节”的配置。如果代码里用了双层或非连续滚动区addr 公式要跟着 SCROLL 配置改。比如双图层时第二层的起始地址不同偏移量要额外加。5.2 读回操作是必要之恶RA8835 支持从显存读数据。有的工程师为了省事所有绘图只用写操作画反色或者叠加图形时就会出问题。例如画“擦除”效果必须知道当前像素是什么颜色。读回时序比写慢我实测在 STC12 上连续读写时读操作大约多占几十微秒。如果追求刷新速度建议在 MCU 内部开一个 9600 字节的缓存所有绘图操作先改缓存再批量写屏。这种方式能显著提升大面积刷新效率代价是占一点 RAM。对 51 系列来说 9600 字节可能太奢侈但 STM32 完全没问题。还有一个技巧如果只是画点、不要求高效清除单点可以在内存中维护当前整屏的位图需要擦除时直接按位操作内存再整体刷新到屏上。这样读回显存的过程就省掉了逻辑也简单。5.3 矩形和直线填充的优化思路直线、矩形按点画当然能用但效率低。针对矩形填充可以用更高效的方式计算起始字节、结束字节整字节直接写 0xFF 或 0x00边界字节用掩码。比如 320x240 全屏清屏按字节循环写 0x00比逐点画快 8 倍。void lcd_clear(unsigned char color) { unsigned int i; for (i 0; i 320 * 240 / 8; i) { lcd_set_memory_cursor(i); lcd_write_data(color ? 0xFF : 0x00); } }注意这个写法隐藏了一个性能问题——每写一个字节都重新设置地址RA8835 的指针自动递增特性没有利用起来。更好的方式是连续写模式芯片在写数据后地址自动加 1只要设置一次起始地址后面连续写即可。这样刷一屏 9600 字节会大幅提速。优化后的清屏类似这样先设置起始地址为显存首地址然后连续调用 9600 次写数据函数不重复设置地址。在 STM32 主频 72MHz 下一次清屏能控制在几个毫秒级别做动态界面刷新完全够用。5.4 字符显示和字库RA8835 本身有一个文本模式通过 SYSTEM SET 配置好字符宽度和高度后可以用字符代码直接显示 ASCII。这个模式在显示固定菜单时报字号很有用但大多数工业应用还是直接用图形字库把中文字模搬到显存里。中文显示的核心思路是先从字库文件提取 16x16 或 24x24 点阵数据然后按字节搬移到显存中。注意模拟灰度的显示效果在单色屏上没有意义直接用单色字模即可。常见取模方式选择“横向取模、高位在前”和 8 点一字节的显存结构是吻合的省掉很多位翻转操作。字库存储上建议直接把字库数组放在外部 Flash 或 SD 卡里不要一股脑塞进 MCU 内部 Flash。320x240 屏上做中文菜单几百个汉字很正常内部 Flash 很快就会爆。用文件系统按区位码或 Unicode 索引查找字模是最常见的做法。6. STM32 平台移植细节和 51 完全不一样的体验6.1 总线引脚配置思路STM32 的 GPIO 翻转速度上限、推挽输出模式都和 8051 不同。如果用普通 GPIO 模拟时序只要打开编译优化GPIO 翻转速度通常能跑到几 MHz满足 RA8835 几百 ns 的写脉冲没有问题。最简单的移植方法是找一个 8 位并口把 D0-D7 接到同一组 GPIO例如 GPIOD 的低 8 位。控制脚 CS、A0、WR、RD、RESET 用单独引脚。#define LCD_CS_L() GPIO_ResetBits(GPIOE, GPIO_Pin_0) #define LCD_CS_H() GPIO_SetBits(GPIOE, GPIO_Pin_0) #define LCD_A0_L() GPIO_ResetBits(GPIOE, GPIO_Pin_1) #define LCD_A0_H() GPIO_SetBits(GPIOE, GPIO_Pin_1) #define LCD_WR_L() GPIO_ResetBits(GPIOE, GPIO_Pin_2) #define LCD_WR_H() GPIO_SetBits(GPIOE, GPIO_Pin_2)数据总线写成宏还是寄存器看工程习惯。我建议用宏封装这样换引脚时改一处即可。如果用库函数操作 GPIO 数据位每次写数据都要循环 8 次设置引脚效率很低直接操作 ODR 寄存器会快很多。6.2 FSMC 总线方案STM32F103 系列自带 FSMC可以支持 NOR/SRAM 接口RA8835 刚好是并行 SRAM 类时序。把屏当成外部存储设备挂到 FSMC Bank 上A0 接到地址线WR/RD 对应 FSMC 的写读控制代码里向某个地址写数据就等于向 RA8835 写数据。FSMC 的时序要设置好地址建立时间、数据建立时间、数据保持时间。RA8835 典型写周期约 240ns 上下建议把 FSMC 时序配置得稍宽松一点我第一次移植时照搬 IS61LV25616 的时序参数屏幕偶尔闪字放宽数据建立时间后就好了。使用 FSMC 后底层函数可以简化为#define RA8835_REG (*(volatile unsigned char *)0x60000000) #define RA8835_DAT (*(volatile unsigned char *)0x60000002) void lcd_write_cmd(unsigned char cmd) { RA8835_REG cmd; } void lcd_write_data(unsigned char dat) { RA8835_DAT dat; }注意这里地址位 A1 作为 A0 使用所以命令地址和寄存器地址相差 2。如果 A0 接到 A16地址差就是 0x10000要根据实际接线修改。FSMC 方案适合刷新频繁的界面但如果只是简单菜单普通 GPIO 模拟完全胜任没必要引入 FSMC。6.3 读时序的坑用 FSMC 时读显存比写显存更容易踩坑。RA8835 的 RD 信号打开三态门有一定延迟FSMC 默认的数据采样时序可能过早读回的值是 0x00 或者上一次的值。解决办法是把 FSMC 的 DataSetupTime 调大或者在硬件上给 RD 路径加一点 RC 延迟。我在 STM32F103 上实测把 DataSetupTime 设为 6 个 HCLK 周期左右读回才稳定。不同屏批次有差异调试时可以先把读出的值打印出来看。如果读回一直是 0xFF 或者 0x00多半是 RD 时序问题不是芯片坏了。6.4 中断优先级和延时函数RA8835 并行驱动对时序要求并不苛刻但如果在刷屏过程中被高优先级中断频繁打断可能会出现闪屏。尤其是采样中断、通信中断很频繁时一次刷屏被切成几十段屏幕内容会看到明显撕裂。我的处理方式是刷屏期间临时屏蔽可屏蔽中断或者把刷屏放到优先级较低的任务中执行。对实时性要求高的系统建议用 DMA 配合 FSMC 缓冲一屏数据但 RA8835 不是三线 SPI 那种高速接口DMA 的优势有限通常 GPIO 模拟也够用。7. 背光电路、偏压和电源显示问题的另一半来源7.1 背光不是越亮越好RA8835 控制的是显示内容背光单独驱动。常用背光方式是 LED 恒流驱动电流范围在 20mA 到几百 mA 不等具体要看屏的灯串规格。很多人直接把背光正极接 5V、负极串一个电阻这种做法在小尺寸上够用但 5.7 寸的背光灯串多、压降大如果驱动不足会出现亮度不均、闪烁。建议用专用背光 IC 或者简单的 PNP 三极管开关配合限流电阻。7.2 偏压电路带 RA8835 控制器的模块一般已经把偏压电路做在模组内部用户不需要管 VOUT、VDH、VDL。但如果买到半成品模组需要自己配置负压电荷泵和对比度电阻这种情况最好直接联系原厂要应用原理图。这里补充一点RA8835 的对比度通常通过调节 VLCD 电压实现。有些模块上有电位器有些靠电阻选择。对比度调太低显示内容会非常淡调太高会出现负像或全黑。我一般先把对比度调到能隐约看到字迹的位置再慢慢微调。7.3 电源纹波引起的花屏屏幕初始化没问题但显示内容一多就出现噪点、横纹多半是电源问题。RA8835 内部逻辑和液晶偏压共用电源时如果 MCU 启动瞬间电流波动大屏幕显示就会不稳定。我在一个 5.1 寸项目上遇到过电机一启动屏幕就闪。后来在屏的电源输入端并了 100uF 电解电容和 0.1uF 陶瓷电容并且把背光和主逻辑电源分开走线问题才消失。硬件上给显示器分配独立 LDO比在软件上各种延时都管用。还有一个容易被忽视的问题地线。RA8835 的地和背光地如果共用一根细长走线背光电流的突变会通过地线阻抗耦合进逻辑电路。PCB 布线时尽量让背光回路和逻辑回路的“地”在电源入口处单点汇合不要交叉。8. 三个尺寸的代码复用我踩出来的移植经验8.1 参数表化驱动里最好不要把 320 和 240 写死而是抽象成宏或参数结构体。比如#define LCD_WIDTH 320 #define LCD_HEIGHT 240 #define LCD_BPL 40 // 每行 40 字节在 320x240 下这三个值固定但在 3.8 寸、5.1 寸、5.7 寸之间切换时只要分辨率一致代码几乎不用改。如果是 240x320 的模组那 BPL 就变成 30画点公式也要改。所以先把这几个宏搞清楚能少走一大半弯路。8.2 不同模组的偏压电阻和对比度虽然 RA8835 是同一颗芯片但不同尺寸屏的液晶材料、偏压响应不同同样初始化代码显示对比度会有差异。如果 3.8 寸看着正常、换 5.7 寸就整体发白或者过黑优先检查模块上的对比度电位器或偏压配置电阻而不是怀疑代码。我见过最典型的情况同一套程序3.8 寸显示完美5.7 寸显示全是“重影”。最后发现是模块的帧频参数差异SYSTEM SET 里的 P6/P7 需要微调把扫描行数从 239 改成 239 还是发虚最后改到 255 就正常了。所以“通用代码”只是起点不是终点。8.3 时序放宽原则从 3.8 寸换到 5.7 寸负载变大数据线上沿可能变缓。代码里如果写时序卡得很紧换屏后容易出现偶发花字。我习惯把 WR 低电平时间放宽到 1us 以上写读间隔也留足余量。这个余量在 320x240 这种分辨率下对刷新率的影响可以忽略。特别是在 EM1163 或其它 3.3V 主控驱动 5.7 寸大屏时数据线负载电容增加信号边沿变缓。如果按芯片手册的最小写周期去写虽然大部分时间正常但高温或电压波动时就会偶发错误。放宽时序是最便宜的稳定性保障。8.4 图层和滚动区的利用RA8835 支持多层和滚动显示。在 320x240 屏上做菜单滑动、趋势图滚动时可以直接用 SCROLL 寄存器设置滚动区域让屏幕自己滚动而不需要 MCU 不断重绘。这个功能在工控曲线显示里特别实用。具体做法是定义显示起始地址和滚动屏高然后修改显示起始地址寄存器实现纵向滚动。我做过一个温湿度曲线界面把历史曲线区域设成独立滚动区每采一次数据更新一行屏幕自然向上滚动效果非常流畅MCU 负载也很低。9. 常见问题速查表和排障方法现象可能原因处理建议全白屏背光亮未初始化或 SYSTEM SET 失败检查上电复位顺序、命令字节全黑屏背光亮显示开关未打开或显存全 0检查 DISP ON/OFF 命令写 0xFF花屏时序过快、电源不稳加延时检查电源滤波显示错位显存地址公式错误逐字节全屏填充测试检查 BPL字体模糊对比度电位器不对调整偏压电阻读回全 0RD 时序太短调 FSMC 参数或加读延时背光不均匀灯串驱动不足改恒流驱动方案每次上电显示不同复位时序不满足拉长复位低电平和等待时间排障第一步永远是“全屏分别写 0x00 和 0xFF”。如果这两步都能显示规整的整屏色块说明硬件和初始化基本没问题剩下就是绘图坐标和地址问题。如果连整屏色块都不规整先回头查电源、复位、数据线接反。我再补充一个自己的习惯画点函数测试阶段先把四角和中心点都画出来比如在 (0,0)、(319,0)、(0,239)、(319,239)、(160,120) 这几个坐标画点。如果这些点位置正确说明坐标映射公式没问题如果出现对称镜像或者偏移基本就是地址计算或者取模方向反了。10. 我最后想补充的三点实操体会第一点RA8835 这类并行屏在国产工控方案里生命力很强。别一听“老芯片”就排斥正因为它老所有坑都被人踩过了资料容易找问题容易查。真在产线上跑起来稳定性比许多花哨方案靠谱。第二点代码里一定要把“读显存”这个能力用好。我做 3.8 寸的界面时移动光标和区域反色都用到了读回功能虽然读操作慢但逻辑清晰调试也快。等到后面需要做大面积滑动刷新再引入内部缓存优化。第三点也是我最想提醒的拿到新屏的第一件事不是写初始化而是看规格书的时序图和命令表。我见过太多人直接抄网上代码结果屏的版本号、引脚顺序、偏压配置都不一样白白折腾好几天。仔细看一遍实测参数能让后面省掉大量麻烦。如果以后你想在这几个尺寸上叠加触摸、中文菜单、曲线绘制底层框架就用这篇讲的 RA8835 驱动。框架不变功能全部可以一层层加进去。