问答

汇集网友智慧,解决技术难题

21ic问答首页 - LCD_ShowChar字符显示函数影响系统的响应时间问题

LCD_ShowChar字符显示函数影响系统的响应时间问题

showmyself2022-07-21

各位好,

我现在调一块3.5寸的TFT LCD,发现厂家提供的 void LCD_ShowChar()这个显示字符串的函数执行效率非常低下,我的程序中一使用这个函数,按键的反应就下降很多,按一下按键,LCD上几乎1s才有反应,只要注释掉这个函数,按键的响应几乎瞬间的,非常快!

这个函数如下:
void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint8_t size,uint8_t mode, uint16_t pcolor, uint16_t bcolor)
{
    uint8_t temp,t1,t;
    uint16_t y0=y;
    uint8_t csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数
    num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)

    //Address_set(x,y,x+size/2-1,y+size-1); //如果把地址放在这里,不放循环中可以解决响应问题,但是商家给我的程序,这里被注释掉了,不知道为啥?我启用后,发送字符显示乱码------1
    for(t=0; t<csize; t++)
    {
        if(size==24)temp=asc2_2412[num][t];                  //调用1206字体
        else if(size==16)temp=asc2_1608[num][t];           //调用1608字体
         else if(size==38)temp=asc2_38x19[num][t];        //调用3216字体
        else if(size==48)temp=asc2_4824[num][t];        //调用4824字体
        //        else if(size==64)temp=asc2_6432[num][t];        //调用4824字体
        else return;                                                                //没有的字库
        for(t1=0; t1<8; t1++)
        {
            if(temp&0x80)LCD_DrawPoint(x,y,pcolor);  //发现问题在画点函数这里,画点函数带了坐标设置,导致每循环一次就会发一次坐标,而坐标是通过SPI发给LCD,SPI速度不高拖慢整个程序
            else if(mode==0)LCD_DrawPoint(x,y,bcolor);
            temp<<=1;
            y++;
            if(y>=240)return;                //超区域了
            if((y-y0)==size)
            {
                y=y0;
                x++;
                if(x>=320)return;        //超区域了
                break;
            }
        }
    }
}



如上所述,导致LCD_ShowChar()这个函数执行效率低的主要原因是,在循环中的画点函数带了坐标设置,每循环一次都会通过SPI发地址给LCD,严重拖慢了整个系统,如果把发坐标的部分单独拿出来,放在上面代码都1处,系统就正常了,响应非常快,但是放在1处,字符显示不正常了,这个坐标设置函数Address_set(x,y,x+size/2-1,y+size-1); 也没看出来有什么问题啊,是哪里有问题呢?各位有没有什么方法不要在循环里发坐标,循环里只发颜色数据,坐标放在外面设置,有什么写法可以分享,我自己在网上查了很多,发现很多都是这种循环带坐标的写法,难道坐标非得放在循环里吗
回答 +关注 1
460人浏览 6人回答问题 分享 举报
6 个回答
  • dalarang 发表于 2022-7-22 16:52
    八成商家提供的hz2424函数内有设置矩形窗口为24*24的相关语句,这样写完24个点会自动移位到下一行。
    你如 ...

    感谢热心的回复,经过好多天接近崩溃的调试,我终于解决这个问题了!

    主要原因是字符取模的方式不同,坐标设置的方式也不同。比如24x24的字符,商家的例程用的是逐列式取模,配合读点函数一个点一个点描绘的,太慢了!因为我的LCD的扫描方式是逐行扫描,所以我用逐行式取模,与之对应,但还是无法显示的主要原因,我找了好几天才发现主要是逐行取模的字符生成的字符点阵字节不一定就是字体大小,比如24x24=576, 生成的点阵会比576小,具体点阵是多少要按照取模后产生的字节数x8来计算,而不是24x24这样算,计算后在用这个值反推出水平方向的值是多少,然后把反推出来的值作为窗口的终点坐标,就可以实现你说的第一种的窗口自动填充了,中间计算细节较多,我也是在崩溃状态下研究好多天才搞清楚。

    在此结帖,感谢回复过的朋友!
  • showmyself 发表于 2022-7-22 10:55
    你说的这个没错,我用的是ST7789V驱动IC,是有自动移位功能的,即设定起始坐标和终点坐标后,他会按照坐 ...

    八成商家提供的hz2424函数内有设置矩形窗口为24*24的相关语句,这样写完24个点会自动移位到下一行。
    你如果直接套用函数来写其它如16*16或32*32点阵就会有换行对不上的问题,自己研究下他函数内的处理方式,按自己需要调整就行了。

    写字符点阵必然就以下三种方式之一:
    1、设置写入窗口为24*24矩形,然后直接写入576个点的颜色,效率最高,需要LCD控制器有此功能,但有些GUI不支持;
    2、将矩阵分为24行或24列,每写24个点的颜色时设置一次起始坐标,部分利用自动移位特性;
    3、每写一个点都设置一次坐标,效率最低,但GUI兼容性最好,所有GUI都支持;
  • dalarang 发表于 2022-7-22 09:13
    要看屏上的LCD控制器,自己拿数据手册看下。
    大多数LCD控制器有坐标自动移位的功能,写完一个点后坐标自动 ...

    你说的这个没错,我用的是ST7789V驱动IC,是有自动移位功能的,即设定起始坐标和终点坐标后,他会按照坐标限定的矩形框自动填充,我的屏现在设置的显示方向是横屏,显示方式是从左到右,从上到下(横屏正视自己的方向),但用这个函数显示字符死活不行,字符的取模方式逐列式,逐行式都试过,都不行!但奇怪的是商家提供的显示汉字的函数GUI_sprintf_hz2424是可以自动移位和填充颜色的,我看了下,hz2424汉字库用的取模方式是逐行式,我也仿照逐行式用到LCD_Showchar还是不行,显示出来是乱码,,非得用商家提供的逐列式取模+逐点绘制才可以!真的无语了,不知道啥原因
  • GUI 喜欢这样用最基本的画点函数构建整个图形接口。

    其实可以修改画点函数,将LCD内存坐标保存一份映射坐标在MCU内。每次设置坐标前对比MCU映射坐标和LCD内存坐标一致就绕过设置坐标,仅按照LCD规格操作映射的地址。内存操作比SPI快很多。
  • 要看屏上的LCD控制器,自己拿数据手册看下。
    大多数LCD控制器有坐标自动移位的功能,写完一个点后坐标自动移位到下一个点,不用再写入坐标可直接写点数据。
    另外很多LCD控制器有窗口填充功能,可以设置窗口的坐标和大小,然后直接把数据写进去,它会自动将数据填充到这个矩形窗口中。

    我以前也有个屏幕,供应商给的源码是每点重复发送坐标,后来自己按数据手册修改了矩形刷新函数后速度快了很多。
  • 本帖最后由 LcwSwust 于 2022-7-21 22:34 编辑

    楼主说得对,设置窗口后直接填充数据能提高效率,但是这个窗口要注意是否超出屏幕边沿,特殊情况还要特殊处理。
    还有就是,在内存中用一块区域来代替屏幕,在内存中绘图,然后整体复制到屏幕,也能加快速度。
    按键可以放在定时中断里处理,可快速响应按键,显示慢点也不怕了。

您需要登录后才可以回复 登录 | 注册