当前位置:首页 > 显示光电 > 显示光电
[导读]工业屏乱码不是“屏坏了”,强电磁现场里变频器、伺服、继电器启停会通过辐射/电源传导耦合进SPI/I2C排线,导致位翻转、时钟抖动、从机ACK失败。 硬件层屏蔽滤波是底座,软件层要做的是“传输出错能发现、写屏异常能恢复、系统跑飞能复位”。


工业屏乱码不是“屏坏了”,强电磁现场里变频器、伺服、继电器启停会通过辐射/电源传导耦合进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发现错帧、状态机恢复总线、双份显存防翻转、看门狗只做最后保险——四层叠起来,变频器旁边也不会莫名其妙乱码。单靠“重发一次”或“加个滤波电容”都不够,得协议层+驱动层+系统层一起收口。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭