摘 要 针对 LED屏控制器设计提出了一些新的方法。快速移位法使移位速度提升 33%。协议树的引入使通信协议的描述、解释和扩充更加快捷;应用循环缓冲区可有效避免通信缓冲区溢出引发的程序异常;显示双缓冲区的使用不仅简化了显示帧设计而且便于设计代码移植;基于优先级的主程序结构可优先且多次响应重要任务。运用这些方法可以显著提高控制器开发效率和运行稳定性。
关键词 快速移位 协议树 循环缓冲区 显示双缓冲区
0 引 言
随着LED显示屏市场不断扩大,缩短LED显示屏控制器开发周期、增强系统稳定性已显得尤为重要。本文针对单片机控制的 LED显示屏提出了一些新的设计方法,这些方法做成模板后稍加修改就可直接用于实际项目设计。
1 系统结构
为了方便描述,本文给出了具有代表性的 51单片机为控制核心的LED显示屏系统结构如图 1所示。系统主要包括快速移位模块,存储器扩展模块,串行通信模块,亮度采集模块,LED检测模块,配置模块,看门狗模块等。
图1 系统结构图
2 快速移位实现
LED显示屏的驱动电路采用“串行移位→锁存→驱动”结构,在单片机系统中通常由单片机实现移位输出,移出 1bit数据需3个机器周期(时钟置低,放1bit数据,时钟置高),这种方法优点是简单易用,缺点是数据输出速率低。本文在基本不增加硬件成本的条件下,提出利用 74HC165辅助单片机加快移位速度的方法,该方法可使移位速度提高 33%,其硬件连接和操作时序如图 2所示。
图2 快速移位硬件实现及移位时序
74HC165采用并入串出工作方式,单片机W 78E58的 P0口同时连接74HC 165的数据端口P0~P7和外部RAM 61C 256的数据端口D0~D7。单片机RD脚同时连接74HC165并行数据装入端PL和外部RAM读使能端OE。当单片机从外部RAM读取显示数据时,RD变低,同时PL也变低,使出现在数据总线上的数据被异步装入 74HC165内部移位寄存器中。读操作结束后,由单片机P1.6脚生成移位时钟(P1.6置低,P1.6置高生成一个时钟),又P1.6接CLK1,这样每个CLK1上升沿Q 7就输出1bit数据。P1.6经非门驱动生成LED驱动器的移位时钟SCLK,每个SCLK上升沿Q7输出的1bit数据被移入LED驱动器中,Q7输出则生成了串行移位数据SD。可见快速移位法输出 1bit数据只需 2个机器周期,相比单片机的 3个机器周期减少 1个机器周期,即移位速度提升 33%。
3 树型协议设计及其处理程序结构
LED显示屏的串行通信协议通常由LED显示屏生产商专门制订,制订方式大致有两种:一种是参照标准协议制订,另一种是完全自定义。由于没有统一标准,造成协议形式五花八门,不利于协议的解释、维护和扩展。
本节给出了 LED屏通信协议的树型设计方法。按此方法设计出的每个协议都形成一棵协议树[1],具有层次结构清晰,搜索速度快,内容扩展方便,通用性好等特点。本文以一种基于Modbus的交通诱导屏协议为例进行设计,协议主要包括两类命令:一类是读取1个或多个参数(功能码03H),另一类是设置1个或多个参数(功能码 16H),协议中部分内容设计为图 3所示的一棵协议树。
图3 交通诱导屏Modbus协议树
协议处理程序只需按照协议树采用多重CASE结构嵌套形式编写。图 4对协议中“功能码03→实时数据区→实时数据处理”给出了伪码描述,图中的地址码参见表 1。当协议项较多时采用此结构可以显著提高协议项搜索速度,从而缩短通信响应时间,这一点对于拥有大量交通诱导屏和其它设备的智能交通网络意义重大。每块诱导屏通信响应时间缩短,必然使整个交通网络轮询周期的缩短,这样控制中心就可在更短的时间内获取更新的路段信息。
图4 树型协议处理程序结构
有些协议没有按照图 3所示结构设计,如表 1所示。对于这类协议只要按照上述方法容易将非树形协议转化为图 3所示的协议树,协议处理程序与图 4所示方法相同。
表1 非树型协议
4 通信循环缓冲区使用
循环缓冲区在计算机系统应用较多[2],本文在外部 RAM上设置 2个循环缓冲区分别作为串行通信的收、发缓冲区。这样通信收、发缓冲区对应的存储区域都是一个循环队列。如此设计就可有效避免因通信缓冲区溢出而引发的通信处理异常。
循环缓冲区设置有读指针和写指针。每写入或读出一个数据,写指针或读指针就沿缓冲区移动一位。循环缓冲区空、满状态判断非常方便:当:取模(写指针+1)=读指针,表明缓冲区‘满',此时缓冲区丢弃新的数据;当:读指针=写指针,说明缓冲区‘空'。只要对每次移动后的读或写指针做“模”运算就可保证读、写指针指示范围超出缓冲区时又会自动回到缓冲区内,从而使缓冲区可以循环使用。只要缓冲区大小设置合理且系统运行正常,缓冲区循环使用时被覆盖的数据都是使用过的数据,而且缓冲区‘满'发生概率非常小。
51单片机汇编语言没有直接支持模运算,而是通过多字节除法间接实现,这样模运算频繁使用必定会拉长通信响应时间。本设计通过采用单片机硬件直接支持的‘逻辑与'运算替代‘模运算'解决了此问题,现在给出部分程序代码:
设接收循环缓冲区和发送循环缓冲区分别为 1K字节(0~3ffH)数组[rxd_buf]和[txd_buf],读指针r_p和写指针w_p分别指示数组[rxd_buf]和[txd_buf]的元素索引号。单片机串行接收和发送的C语言程序段为:
用逻辑与替代模运算是有条件的,即数组最后一个元素的索引号转换为二进制数为全‘1'。前面提到的“3ffH”转换为二进制码为全‘1',满足要求的还有“ffH”,“7ffH”等等。
5 显示双缓冲区应用
单片机控制的LED屏系统通常只有 1个串行数据输出口[3],显示模块PCB布线常常是红、绿、蓝三种LED管互相交错出现在同一个 16位 LED驱动器输出口上。例如,3个 16位LED驱动器共48个输出口上出现R 4|G4|B4|R4—G 4|B4|R4| G 4—B 4|R4|G4|B 4布线形式,对应控制3基色4×4点阵。显示信息通常做法是:根据PCB布线直接生成显示帧(如上移操作的各个帧),这种做法每一帧编程都要考虑PCB布线,而且不同布线的显示模块需重新编程,编程繁琐,通用性差。
为克服上述缺陷,本文提出了在外部RAM上设置显示双缓冲区[4]间接生成显示帧的设计方法。双缓冲区中一个为逻辑缓冲区,另一个为物理缓冲区,这里用 4×4点阵为例进行说明。逻辑缓冲区存放逻辑显示帧,其每个bit从左到右从上到下顺序对应实际显示屏像素而与显示模块 PCB布线无关,如表 2所示。物理缓冲区用于存放实际显示帧,它的每个bit顺序对应级联的16位LED驱动器各个输出口,它与显示模块PCB布线有直接联系,如表 3所示。
表2中“C(X,Y)”表项中X表示行序号,Y表示列序号,C表示基色。如“R(2,3)”表示第2行第 3列像素中的红色。表3中“X-Y”表项中X表示LED驱动器序号,Y表示该驱动器输出位序号。例如“0-5”表示LED管由第 0个驱动器的第 5位驱动,此LED管是第1行第1列像素中绿色LED管
双缓冲区实现显示分三个步骤:(1)在逻辑缓冲区生成显示帧。(2)调用帧转换函数将逻辑缓冲区内容转换为物理缓冲区的内容。(3)将物理缓冲区内容移位输出完成显示。
在逻辑缓冲区生成显示帧与 PCB布线无关,编程较容易,但显示前必须将逻辑显示帧映射到物理缓冲区,这里把完成这个映射的函数称为帧转换函数。这样编程时每一帧都在逻辑缓冲区生成,显示前调用帧转换函数,将逻辑缓冲区生成的显示帧转换为物理缓冲区的实际显示帧。对于不同PCB布线的显示模块只需改写帧转换函数,而在逻辑缓冲区编写的大量显示帧生成代码则可重复使用。
帧转换函数设计方法有 2种:代数法和查表法。代数法需要寻求映射:“表3=f(表2)”中函数f的表达式,该方法需要使用算术运算指令,缺点是转换速度慢,优点是实现代码短。查表法是在程序中存储一张映射表,转换时只需执行查表指令,这样做优点是转换速度快,缺点是映射表需占用程序存储器造成实现代码长。
基于速度优先本设计采用查表法。需存储的映射表就是表3,它每个表项包含两个字节,例如表 2中 1行 3列的绿色LED管G(1,3),查表后得到两个字节02H和09H,即对应表3中2 -9表项,则 1行 3列的绿色LED管应由第 2个驱动器的第 9位驱动。
表2 LED 3基色4×4点阵的逻辑缓冲区
表3 LED 3基色4×4点阵的物理缓冲区
若某帧要求第 1行显示绿色,即逻辑缓冲区(表 2中黑体部分)G(1,0),G(1,1),G(1,2),G(1,3)的值都为‘1'其它值为‘0',经帧转换函数映射后对应物理缓冲区(表 3中黑体部分)0 -5,1-1,1-13,2-9的值都为‘1',其它值都是‘0'。则物理缓冲区移位输出序列为:{驱动器 0}0000 0000 00 10 0000,{驱动器 1}00 10 0000 0000 00 10,{驱动器 2}0000 00 10 0000 0000。
6 含优先级的主程序结构
主程序根据各项任务两次处理的间隔时间为每项任务分配了优先级,优先级越高的任务两次处理的间隔时间越短。串行通信协议处理任务具有最高优先级,只要CPU空闲就执行,这样才能保证 LED屏及时更新显示内容或响应各项命令。其它任务按照优先级从高到低对应的两次处理间隔时间由短到长,例如,每隔100ms更新一次显示内容,每隔200ms读1次状态信息,每隔 300m s喂一次看门狗,每隔1000ms执行一次环境亮度检测,每隔5小时做一次LED故障自检等等。
7 结 论
本文提出的设计方法在实际系统中运行稳定可靠,现在这些方法已做成模板,开发人员直接套用这些模板快速完成相关设计后就能立刻投入项目中其它组件的设计,从而缩短了整个项目开发周期。限于篇幅,设计方法、应用范畴的不同,本文虽没有涉及含FPGA/CPLD的控制器设计,但文中的一些方法也同样适用此类控制器。