OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2882|回复: 5

原子LCD屏汉字显示程序的优化

[复制链接]

7

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1159
金钱
1159
注册时间
2018-5-30
在线时间
151 小时
发表于 2019-7-16 14:32:42 | 显示全部楼层 |阅读模式
原子例程提供了使用外接字库芯片的汉字显示程序,对于大部分的应用来说,屏幕显示的汉字在100个左右,而且对于4.3寸屏来说,24点阵显示偏小,需要48点阵字库,外接字库芯片会增加硬件成本。参照原子例程中ASC码的显示方法,使用自造点阵数据,显示少量的汉字,完全能满足大部分设计的应用。
其汉字的显示方法是:读出汉字编码→取出对应编码汉字点阵→逐点显示→完成。
此方法虽能显示出汉字,但显示速度较慢。我们进行了测试,显示11个48点阵汉字需140ms。
经仔细查看资料,认真观看原子视频,认为程序还有很大的优化空间,对以上汉字显示程序进行改进,以提高汉字显示速度。
优化内容:1、屏幕初始化部分。原子例程适应于多种显示屏,而在实际应用中,就是一种显示屏,所以在初始化程序中删除多余程序,只留下现用的屏程序。虽然初始化部分不影响显示速度,可也减少程序占用空间。2、将取汉字点阵改为取汉字点阵指针,减少一次读取点阵过程。3、就是优化的关键,将逐点显示改为设定初始点坐标,并设定显示数据宽度,采用连续输出点阵数据的方法。这样,48点阵的汉字的显示,就少了2300多次坐标点设定,大大提高了显示速度。4、将调用短函数内的指令直接写到函数中,减少程序跳转。5、ASC码的显示也照此方法优化。6、在程序中空格一般显示较多,可将空格显示单独列出,不用读字库,而直接写底色数据。
我的项目使用原子的4.3寸电容触摸屏,横屏显示,所以点阵取模方式采用逐行式,将例程中的ASC码字模要重新取模,汉字也要用逐行式取模。竖屏显示是不是采用逐列式,我没有验证。

通过以上程序优化,经实测,显示11个48点阵汉字的时间是14ms,只有原程序的十分之一,效果明显。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

7

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1159
金钱
1159
注册时间
2018-5-30
在线时间
151 小时
 楼主| 发表于 2019-7-16 14:36:06 | 显示全部楼层
汉字显示程序较长,不方便贴出。这里我放上画横线和画竖线程序,即能明白程序优化原理。
//画水平线
//x0,y0:坐标
//len:线长度
//color:颜色
void gui_draw_hline(u16 x0,u16 y0,u16 len)
{
        u16 j;
       
        LCD->LCD_REG = lcddev.setxcmd; LCD->LCD_RAM = x0 >> 8;
        LCD->LCD_REG = lcddev.setxcmd + 1; LCD->LCD_RAM = x0;
        LCD->LCD_REG = lcddev.setxcmd + 2; LCD->LCD_RAM = (x0 + len - 1) >> 8;
        LCD->LCD_REG = lcddev.setxcmd + 3; LCD->LCD_RAM = (x0 + len - 1);        //宽度
        LCD->LCD_REG = lcddev.setycmd; LCD->LCD_RAM = y0 >> 8;
        LCD->LCD_REG = lcddev.setycmd+1; LCD->LCD_RAM = y0;
        LCD->LCD_REG = lcddev.wramcmd;
        for(j = 0;j < len; j++) LCD->LCD_RAM = POINT_COLOR;        //显示颜色             
}
//画垂直线
//x0,y0:坐标
//len:线长度
//color:颜色
void gui_draw_lline(u16 x0,u16 y0,u16 len)
{
        u16 j;
       
        LCD->LCD_REG = lcddev.setxcmd; LCD->LCD_RAM = x0 >> 8;
        LCD->LCD_REG = lcddev.setxcmd + 1; LCD->LCD_RAM = x0;
        LCD->LCD_REG = lcddev.setxcmd + 2; LCD->LCD_RAM = x0 >> 8;
        LCD->LCD_REG = lcddev.setxcmd + 3; LCD->LCD_RAM = x0;        //宽度
        LCD->LCD_REG = lcddev.setycmd; LCD->LCD_RAM = y0 >> 8;
        LCD->LCD_REG = lcddev.setycmd+1; LCD->LCD_RAM = y0;
        LCD->LCD_REG = lcddev.wramcmd;                    //开始写入GRAM         
        for(j = 0;j < len; j++) LCD->LCD_RAM = POINT_COLOR;        //显示颜色             
}
回复 支持 反对

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-6-17
在线时间
10 小时
发表于 2020-3-30 14:59:02 | 显示全部楼层
方便参考以下源码吗?汉子显示的
回复 支持 反对

使用道具 举报

7

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1159
金钱
1159
注册时间
2018-5-30
在线时间
151 小时
 楼主| 发表于 2020-3-31 08:15:41 | 显示全部楼层
冯伟军 发表于 2020-3-30 14:59
方便参考以下源码吗?汉子显示的

原码较长,如果需要,请加QQ43187124
回复 支持 反对

使用道具 举报

0

主题

25

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
280
金钱
280
注册时间
2019-12-26
在线时间
134 小时
发表于 2020-3-31 16:02:56 | 显示全部楼层
void Show_Font(u16 x1,u16 y1,u8 *font,u8 size,u8 mode)
{
        u8 temp,t,t1;
        u16 x=y1;u16 y=x1;
        u16 y0=x;
        u8 dzk[72];   
        u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数         
        if(size!=12&&size!=16&&size!=24)return;        //不支持的size
        Get_HzMat(font,dzk,size);        //得到相应大小的点阵数据
        LCD_Scan_Dir(U2D_L2R);//设置扫描从上到下
       
        LCD->LCD_REG=lcddev.setxcmd;LCD->LCD_RAM=x>>8;
        LCD->LCD_REG=lcddev.setxcmd+1;LCD->LCD_RAM=x&0XFF;
        LCD->LCD_REG=lcddev.setycmd;LCD->LCD_RAM=y>>8;
        LCD->LCD_REG=lcddev.setycmd+1;LCD->LCD_RAM=y&0XFF;
       
        LCD->LCD_REG=lcddev.wramcmd;        //开始写入GRAM       
        for(t=0;t<csize;t++)
        {
                temp=dzk[t];                        //得到点阵数据               
                for(t1=0;t1<8;t1++)
                {
                        if(temp&0x80)LCD->LCD_RAM=POINT_COLOR;
                        else if(!mode)LCD->LCD_RAM=BACK_COLOR;
                        temp<<=1;
                        x++;
                        if((x-y0)==size)
                        {
                                x=y0;y++;
                                LCD->LCD_REG=lcddev.setxcmd;LCD->LCD_RAM=x>>8;
                                LCD->LCD_REG=lcddev.setxcmd+1;LCD->LCD_RAM=x&0XFF;
                                LCD->LCD_REG=lcddev.setycmd;LCD->LCD_RAM=y>>8;
                                LCD->LCD_REG=lcddev.setycmd+1;LCD->LCD_RAM=y&0XFF;
                          LCD->LCD_REG=lcddev.wramcmd;        //开始写入GRAM
                                break;
                        }
                }           
        }
        LCD_Scan_Dir(L2R_U2D);//设置扫描从上到下       
}
我写的,只理解了楼主第三点,快了4倍把
回复 支持 反对

使用道具 举报

7

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1159
金钱
1159
注册时间
2018-5-30
在线时间
151 小时
 楼主| 发表于 2020-4-1 15:10:19 | 显示全部楼层
无敌是多么寂寞1 发表于 2020-3-31 16:02
void Show_Font(u16 x1,u16 y1,u8 *font,u8 size,u8 mode)
{
        u8 temp,t,t1;

lcddev.setxcmd+2和lcddev.setxcmd+3是显示宽度的高位和低位。把前面改成:
  LCD->LCD_REG=lcddev.setxcmd;LCD->LCD_RAM=x>>8;
  LCD->LCD_REG=lcddev.setxcmd+1;LCD->LCD_RAM=x;
  LCD->LCD_REG=lcddev.setxcmd+2;LCD->LCD_RAM=(x+size-1)>>0;
  LCD->LCD_REG=lcddev.setxcmd+3;LCD->LCD_RAM=(x+size-1);
  LCD->LCD_REG=lcddev.setycmd;LCD->LCD_RAM=y>>8;
  LCD->LCD_REG=lcddev.setycmd+1;LCD->LCD_RAM=y;
就不用判断每行数据是否传送完,每行设定一次起始点,而是可以将所有数据一次传送完成,这样会更快。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 18:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表