本实例驱动软件的主程序主要完成两个任务:初始化及显示内容的滚动。本小节先对主程序的操作流程进行说明,然后给出驱动所用的数据流程图,说明主要会有哪些数据及由谁对它们进行传递或变换,在此基础上再说明初始化过程以及实现图像内容的滚动显示操作。
1.主程序工作过程
其基本流程图如图6.11 所示,STM32 上电后执行初始化操作,然后进入主循环,用于更新显示内容,以实现汉字“欢迎光临!”滚动显示。滚动显示每30ms将把显示内容左移一列,视觉感受到的显示图像从屏幕右边移入,从左边移出。要实现上述效果,需要把图像帧存中的内容也每30ms更新一次,把更新数据写进更新帧。主循环大多数时间都处于空闲状态,只有当30ms的更新周期到来且定时器中断服务程序已经释放出一个空闲帧存,才会执行生成帧的更新操作。因此,我们在流程中加了一个虚设的空闲操作,如果该显示屏还有其他功能要实现,可以放在这个位置进行。上述更新过程改变的是双缓冲结构中的更新帧,不会对正用于屏幕扫描的显示帧产生干扰,在完成更新一帧数据之后,将“更新帧就绪”标记置位,提示扫描模块下一帧滚动移位数据已经准备好,在完成当前显示帧扫描后可以执行显示帧与更新帧的切换。具体执行过程是在定时器中断服务程序中进行的,下一小节再详细说明。
图6.11 主程序流程图
2.数据流图
驱动软件主要用到三个数据块,它们是系统状态数据块、显示模板数据块以及图像帧存。保存在这些数据区中的数据在程序执行过程中会经由不同的接口进行读取、变换或转移。描述数据操作或变换的方法之一是数据流图,本例中用到的数据流图如图6.12所示。
图6.12 LED 驱动软件数据流图
系统状态数据块(System Data Block)用于保存一些重要的标志以及系统数据,它在单片机的RAM 区进行分配,初始化操作会把所有的状态数据赋上确定的值,保证每次复位后系统必定处于完全可预测的状态。例如,为更新帧分配帧存状态字变量UpdateReadyFlag,用来表示就绪或待写入;给图像行扫描分配的扫描行计数变量RowCount,用于确定当前扫描到多少行,每次进入定时器的中断服务程序它就需要增量;为图像滚动控制分配的时钟计数变量SysTicks,用于生成确定的左移速率;等等。总之,我们会把那些影响软件操作进程的系统数据放在其中,对于状态数据变量所包含的具体值就不再一一说明,读者可以参看后面的表6.3及后面所附的程序代码。
显示模板数据块(Display Pattern Data Block)中保存的是显示屏所要显示的点阵模板。本章一开始已经明确它有两部分:屏幕上半部分的“Welcome”保存在数据块的静态存储部分;屏幕下半部分滚动显示的汉字“欢迎光临!”保存在数据块的动态存储部分。实际上,显示模板数据块的内容设计好了便不再改变。因此,显示模板数据块在单片机的Flash闪存中分配。
显示缓冲区数据块是两个图像帧,在RAM 中分配,是两块各为4 096字节的连续区域。根据本章开始的设计方案,图像帧的动态显示部分占42行,要从显示模板数据块中的动态数据存储部分取出当前滚动位置对应的2 688个字节数据进行动态填充;图像帧的剩余部分有22行,其中有连续的19行要从显示模板数据块中的静态数据存储部分取出“Welcome”所对应的19行×64列共1 216个字节来填充;而图像帧中没有被用到的2行数据为初始化时的原始值0。
上述数据流图除了展示这三个数据块外,还给出了两个数据接口:主程序及扫描定时器中断服务程序。同时也给出了接口对数据所进行的操作流程及所传递与变换的主要数据。例如,“主程序”(角色是接口)执行了“初始化”(角色是操作流程),把“初始状态值”(角色是所传递的数据)写入了“系统状态数据块”。读者可以仿照这种描述方法去理解上述数据流图中表示的每个数据读写或变换操作。了解这些对于接下来的说明是有帮助的。
3.初始化
初始化模块是最先被执行的,主要用于建立单片机的初始工作状态、分配与配置片上资源,包括端口分配、定时器初始化、程序中所用标志与数据的初始化以及中断系统的初始化等。图6.13给出了驱动程序初始化流程图。初始化流程包括单片机端口初始化、定时器状态初始化、系统状态数据块初始化、图像帧存初始化、单片机中断系统初始化。完成上述初始化后,就可以启动定时器并允许中断,系统进入工作状态。
(1)初始化端口。
控制器需要产生硬件行列扫描电路所需要的控制与移位的像素数据,从上节关于硬件电路的说明已经得知,这是通过把单片机的某些端口信号加载到75E 接口上实现的。因此,程序初始化的一个重要任务之一是恰当定义这些接口的输入/输出方式,STM32与75E控制接口的连接如图6.14所示。
图6.13 驱动程序初始化流程图
(www.daowen.com)
图6.14 STM32与75E控制接口的连接
我们把单片机STM32的PC口中的6位分配给了上、下半屏的列扫描移位像素值,每个像素的RGB各一条移位数据线。公用的控制信号都是通过单片机STM 的PA0~PA7输出的,它们包括当前行地址(低5位),剩下的3位分别分配给列扫描移位时钟CLK、移位寄存器锁存允许LE以及列输出允许OE这三个时钟与控制信号。把显示屏上、下半屏的两行像素的RGB信号组合在一起并被定义在同一端口上,这样做的好处是编程输出时只要执行一个端口操作指令就可以了。输出的行地址经硬件译码后会启动指定行的行驱动管。移位时钟的每一个时钟时期都会把PC口上输出的RGB像素值移入移位寄存器,完成一行数据的移位操作共需要在PA5上产生64个脉冲,PC口上同步产生64个像素数据。完成一行的移位后,在PA6(与75E行数据锁存允许引脚LE相连)上产生一个高电平,把已经移入上、下半屏所用的两组移位寄存器中的两行显示数据同时锁定。最后,把一个低电平加载到PA7(与75E列输出允许引脚OE相连),使得已被锁存的两行数据被输出,点亮这行地址所指定的每一个LED。
端口初始化时,需要把PA口与PC口都配置成输出口。
(2)定时器初始化。
STM32单片机有多达8个定时器。这里选用定时器3产生准确的扫描时间基准。根据之前关于系统设计的描述,图像帧扫周期是10ms,1/32扫描方式意味着行扫周期是312.5μs。定时器3将被初始化成每312.5μs产生一次中断,在中断服务程序中完成当前行的64列像素的列扫描。
定时器3的配置方法如下:STM32单片机的晶振为8MHz,系统时钟经过内部PLL倍频达到72MHz。定时器3是一个有16位计数器的定时器,设计定时器采用基本计数功能,选择为向上计数模式,计数频率为2MHz,故将其预分频器的分频系数设置为36,自动重装载寄存器中存放计数器的最大计数值625,并使能溢出更新中断,也就是当定时器的计数值超过625时,满足溢出条件,计数器溢出,从0开始计数,并产生更新事件触发中断。中断的时间间隔为312.5μs。
(3)中断系统初始化。
如上所述,驱动系统软件使用定时器3中断服务程序进行行扫描,需要对中断系统初始化以便定时器3中断服务程序能正确调用。
中断系统初始化包含三个步骤:①将定时器3中断加入中断向量表;②指定定时器3的中断优先权;③允许定时器3中断请求。
(4)状态初始化。
为了便于控制程序的运行与各部分之间的交互,设计了一些程序标志,系统状态标志如表6.3所示。初始化过程就是要把这些标志设成表6.3中所示的值。
表6.3 系统状态标志
(5)图像帧存初始化。
图像帧存即为显示缓冲区数据块所定义的两个一维数组,一个作为显示帧存,一个作为更新帧存,是经过设计的双缓存结构,在使用过程中它们的作用会发生改变。初始化即把存放在Flash中的显示模板数据块的静态部分同时拷贝到两个图像帧存,它们是上半屏的“Welcome”,不需要进行滚动显示,因此以后也不再改变。显示模板数据块的动态部分的字模内容为“欢迎光临!”,将动态部分前面的2 688个字节拷贝到显示帧存的后2 688个字节,它们仅仅是“欢迎”两个汉字字模数据。所以,初始化完成后显示帧存上将保存有上半屏的“Welcome”与下半屏的“欢迎”,这也是初始看到的显示内容;更新帧存上仅保存有上半屏的“Welcome”。
4.图像滚动显示
图像扫描是在定时器3中断服务程序中实现的,但它只是把存于帧存中的内容映射到LED 屏上而已。初始化后,如果不做其他操作,将只能看到不变的“Welcome”与“欢迎”,而不是下半部从右到左滚动显示的“欢迎光临!”。我们需要不断更新图像帧存中的内容,以实现滚动显示。滚动显示的时序控制,前面主程序的流程中已经说明,这里不再重复。这里只说明如何把移动后的图像数据从显示模板数据块中进行定位并拷贝到更新帧上。
图6.15所示的是实现滚动显示的图像帧存更新原理,初始化后起始列CurrentColumn与汉字模板的起始列重合,每当30ms的滚动时间到,这个地址加1,指向下一列。以CurrentColumn作为左边界,连续拷贝64个字节(一整行像素)到更新帧的第一行,即完成了一行数据的拷贝,然后指向显示模板上的下一行起始地址。下一行地址在哪里?从图6.15可见,虚线所界定的当前显示图像的相邻两行的起始地址之差并不等于64个字节的图像宽度,而应该是160 个字节的显示模板宽度。因此,程序中可以在CurrentColumn上加显示模块的宽度即160个字节,得到下一行图像的首地址,接着重复一次64字节的拷贝,就把第二行数据复制完成。如此连续运行42次行拷贝,就把从当前起始地址开始的一个42×64的图像像素块拷贝到了更新帧,用于汉字滚动显示的下半部分了。等下一个30ms的滚动时间到,起始地址CurrentColumn再加1,显示的图像又往后移一列。读者可以把上述过程直观理解成图像帧存中与汉字显示关联的是一个42×64的窗口,这个窗口以30ms一列的速率从显示模板上向右滑过,窗口所见的部分就是被显示到LED 屏上的内容。需要注意的是,操作过程中每当地址触及显示模板右边界时,务必要回卷到左边界继续扫描。
图6.15 图像帧存更新示意图
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。