服务热线

13103866733
网站导航
主营产品:
新闻中心
当前位置:首页 > 新闻中心

手把手教你用位图映射办法优化灰度液晶控制器驱动

时间: 2025-11-24 23:36:52 |   作者: 乐鱼官网客户端

  单色液晶控制器一般的写显现RAM办法是一次写8个像素,简略完成MCU主存到控制器的位图映射。可是支撑灰度的液晶控制器纷歧定有这样的操作办法,所以只用是非二色的显现时,也不得不每个像素都要写灰阶编码到控制器。可是在MCU主存中每个像素用8-bit乃至16-bit来表明,开支就大多了,许多时分是不必要的。假设用二值的位图寄存显现内容,在显现驱动软件中转化,就或许完成和单色液晶在图形库上的兼容性。

  例如ST7529液晶控制器的显存数据是5-bit灰度,选用并行接口(8080形式)驱动时,有16-bit表明3个像素的办法和3个8-bit表明3个像素的办法。这个控制器是给CSTN液晶规划的,所以总是要RGB 3个像素一同写,作为FSTN的驱动显得有些别扭——列方向的坐标只能以3像素为单位。假设能忍耐这一点,用8-bit数据形式,每次写显存操作便是更新一个像素,按列优先形式能完成逐条扫描线的数据写入。

  现在考虑相似ST7529这种控制器的位图映射软件驱动。在MCU的SRAM中拓荒一块接连空间作为显现区域内容的位图存储(只显现两种色彩,每个像素1 bit),向控制器写像素数据时每次依据位图中的一个bit,决议写控制器的数据是两种色彩代码中哪一个。假设控制器是用MCU的内存控制器(如STM32的FMC)衔接的,写操作就对应到一条STR指令;若无法用FMC,就要用一组GPIO输出并行数据,另一独自GPIO发生写脉冲。

  在写每个像素数据的时分,要进行位运算测验内存中数据的某位是1仍是0. 依照低地址数据在前,每个字中LSB在前的次序拜访整个位图。取数据的时分一次取32 bit的功率要高于8 bit. 内层循环便是逐位处理。在Cortex-m4上,以上代码的完成功率约为12.2 时钟周期每像素。

  这样的代码满足简练了。用位运算是由于不能直接寻址SRAM的某一位…… 可是真的不能吗?Cortex-m3/m4有bit-banding的功用,尽管我曾经没觉得有什么用,SRAM是处于bit-band区域中的。也便是,在SRAM中存储了位图,就有某一段地址是每个32-bit映射到位图中一个bit的。按接连地址拜访就能够遍历位图中每个像素。所以显现代码就只需求一个循环了:

  针对ST7529,假设输出是全黑和全白两种色彩,数据接口上有用位是全0或许全1,还能够把条件判别也省去,修改成这样:

  代码中直接输出数据 -p[n] , 由于p[n]为1则写数据就成了 0xFF,是满足需求的。这样又能少用指令了。实测的履行时刻削减到 8~9 时钟周期每像素,有一个起浮或许是CPU流水线的联系。看一下编译的成果:

  标出的部分便是循环主体,总共7条指令,显得没有一点剩余操作,实践履行时刻改变或许是总线的原因。

  回头看,从原理上呢,依据每个像素判别一下要写什么数据是没错的,可是假设写的数据和前次相同其实能不必更新接口上的并行数据,所以能少一步操作?然而要添加这个条件判别其实是又绕弯了,由于测验、保存前次成果和条件分支会耗费更多的周期。实测也是均匀履行时刻到了 10.4 时钟周期每像素。 程序如下:

  尽管上面这个测验改善失利,削减不必要的操作的思路是有价值的。实践的显现驱动便是写接连一串(个数不确定)的前景色像素,再写接连一串背景色像素,替换进行的。假设SRAM存储的不是位图,而是按次序排列的两种色彩各自接连的像素个数的序列,则显现代码有或许履行更快。

  可是现在SRAM存储的是位图,只能在此前提下评论。那么,从位图扫描的视点,计算接连的1个的个数,再计算后边接连的0的个数,再计算后边接连1的个数……如此下去也能够,只不过功率是个问题。无妨比照以下:

  这段程序将1像素和0像素分组输出,包含了测验计算和接连写脉冲的进程,属所以绕了弯路的做法,最终的履行时刻大约是 15.5 时钟周期每像素. 比最基本的办法还要慢,也是可想而知的。

  假设不必bit-banding呢,像最基本的办法那样每次先取一个字,那么程序还会可预期地多耗费点时刻:

  上面这段程序实践测验大约均匀 20.4 时钟周期每像素, 是显着慢多了。

  但之所以要这么改写,是我想测验一下能否快速地找出接连的1或0的个数——Cortex-m3/m4有CLZ (Count Leading Zeros)指令。在一个32-bit字之内,用这条指令直接得到从最高位开端往下有多少个接连的0. 它能省去一个循环的位测验。

  调试查错往后,上面这段代码在我用的测验位图(文本字符为主)上达到了均匀约 8 时钟周期每像素的功率,追上了前面用bit-band的最快的代码。不枉这份尽力啊。这种办法,履行时刻与显现内容是相关的,一般图形界面的话像素色彩接连呈现的时分多,所以应该是适用的。

  到了这个境地,觉得还有更快的或许吗?其实运用CLZ指令得以提高功率的原因是削减了循环次数,上面这个程序依然有循环:除了不可避免的从SRAM中取数据之外,接连发生多少次写脉冲是用循环来完成。而后者还有优化的或许:

  不必GPIO翻转的办法,用硬件主动发生N个脉冲。STM32的TIM1/TIM8等定时器的PWM能做到,或许用一个定时器作为另一个输出PWM的定时器的门控。我暂时还没有试验,好象用的板子GPIO衔接短少条件。

  假设用了FMC接口的话能够用借用这个思路,用DMA内存到内存的办法快速写。

  循环打开,这要费一些代码空间了。在上面的程序中,接连的写脉冲正常情况下不会太长。比如说,在32个以内就彻底打开循环:

  用这个 wr_pulses() 函数替代前一段代码中的发生WR脉冲的循环,完成部分的循环打开,之后…… 履行速度提高到了 6 时钟周期每像素的水平。

  当然,要求刷屏刷得快简略地把时钟频率提上去便是了,是否要纠结这种优化是MCU玩家自己决议,本文仅仅假日时分的一点研讨共享。要害点:一是bit-band的运用,二是CLZ指令的运用。这两个特性都得要m3/m4起才有,m0是没有的(现在国产m4也很廉价了嘛)。

关注我们