工业显示屏幕的抗干扰编程:解决强电磁环境下的显示乱码问题
工业屏乱码不是“屏坏了”,强电磁现场里变频器、伺服、继电器启停会通过辐射/电源传导耦合进SPI/I2C排线,导致位翻转、时钟抖动、从机ACK失败。 硬件层屏蔽滤波是底座,软件层要做的是“传输出错能发现、写屏异常能恢复、系统跑飞能复位”。
一、先定协议边界:SPI本身不校验
SPI没有ACK/CRC原生机制,I2C也只有字节级ACK,挡不住整帧被干扰改写。 所以串口屏/主控下发显示数据必须自己加帧结构:
typedef struct {
uint8_t head; // 0xAA
uint8_t cmd; // 写区域/清屏/OSD
uint16_t x,y,w,h;
uint16_t len;
uint8_t payload[]; // 像素/字模
uint16_t crc;
} disp_frame_t;
接收端校验head→len→CRC,任一不对直接丢帧,不执行、不回显:
int frame_check(disp_frame_t*f){
if(f->head != 0xAA) return -1;
if(f->len > MAX_PAYLOAD) return -2;
if(crc16((uint8_t*)f, FRAME_CRC_OFF(f)) != f->crc)
return -3; // 位翻转,丢弃
return 0;
}
CRC失败别“将就显示”,否则乱码就来自这一帧。
二、写屏重试+CS状态机
EMI下SPI写一半被冲,现象是半屏花、地址窗口错。写屏驱动别只发一次,包成状态机:
int lcd_send_safe(const disp_frame_t*f){
for(int retry=0; retry<3; retry++){
lcd_cs_low();
int rc = spi_tx(f, frame_len(f));
lcd_cs_high();
if(rc==0) return 0;
delay_us(50); // 退避
}
return -1;
}
关键点:
异常必须主动释放CS,别让屏卡在选中态
I2C从机NACK要复位总线,必要时9个SCL脉冲解锁
超时不是while死等,设局部timeout,超时算失败
重试次数别太多,工业现场连续错一般是干扰源还在,重发也白搭
三、GRAM/显存双份校验
控制类界面(启停状态、报警字)最怕被干扰改写成反状态。做法:
逻辑显存存两份,A/B比对
或显存加每区CRC,定时自检
写屏前校验“这次要画的内容”合法性(比如报警位不能无缘由翻转)
uint8_t ui_ram[RAM_SZ];
uint16_t ui_crc = crc16(ui_ram, RAM_SZ);
void ui_self_check(void){
uint16_t c = crc16(ui_ram, RAM_SZ);
if(c != ui_crc){ // RAM被翻了
ui_restore_from_backup(); // 从备份恢复
lcd_force_redraw();
}
}
关键参数(运行模式、安全联锁)放Backup SRAM/EEPROM,启动校验,别放普通栈里。
四、局部恢复优先于复位
看到通信错就系统复位是新手写法,产线设备会反复重启。正确层级:
单帧CRC错 → 丢弃+请求重发
连续N帧错 → 复位SPI/I2C外设
屏无响应 → 重新init显示驱动
以上都失败 → 任务挂起,最后才看门狗兜底
void disp_err_handler(int e){
static uint8_t cnt=0;
if(e==-3 && ++cnt<5) return; // 偶发干扰
if(cnt>=5) lcd_reinit(); // 总线层面恢复
cnt=0;
}
五、看门狗:兜底不是主力
WDT超时设正常主循环周期的2~3倍,喂狗放主循环关键路径末尾,中断里不喂。
更稳的是“业务心跳”:
static uint32_t disp_heartbeat;
void disp_task(void){
if(frame_check_ok) disp_heartbeat = now_ms();
if(now_ms()-disp_heartbeat > 1000){
lcd_reinit();
disp_heartbeat = now_ms();
}
feed_iwdg(); // 只有任务真在推进才喂
}
假活(程序在跑但通信死了)纯看门狗发现不了,必须靠心跳。
复位后读RCC/复位状态寄存器,记“看门狗复位”次数进Flash,方便现场排查是不是EMI导致。
六、刷新策略降敏感
强干扰时段别整屏狂刷:
静态区不重发
只刷脏矩形
关键OSD(报警、急停)本地双缓冲+校验后再送屏
SPI时钟别顶满,留余量比“刷得快”重要
七、落坑清单
收到错帧直接画→乱码上屏
SPI无CRC裸发→位翻转发现不了
异常不释放CS→屏卡死后续全错
通信错就整机复位→产线反复重启
中断里喂狗→跑飞也喂,狗失效
关键状态只放栈→EMI翻转无察觉
时钟线不包地→变频器一启动就抖
屏供电纹波大→软件再稳也花
八、落地顺序
显示协议加head+len+CRC
接收端校验失败丢弃
写屏封装CS状态机+重试
关键UI RAM双份/CRC自检
局部恢复:重发→重init→任务复位
主循环心跳+WDT兜底
复位原因记录Flash
硬件配合:屏蔽排线、电源滤波、信号隔离
工业屏抗干扰编程的本质:硬件抗住大部分,软件兜住漏过来的那部分。CRC发现错帧、状态机恢复总线、双份显存防翻转、看门狗只做最后保险——四层叠起来,变频器旁边也不会莫名其妙乱码。单靠“重发一次”或“加个滤波电容”都不够,得协议层+驱动层+系统层一起收口。





