OpenEdv-开源电子网

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

阿波罗系列综合实验RGB横屏显示的修改

[复制链接]

1

主题

6

帖子

1

精华

初级会员

Rank: 2

积分
167
金钱
167
注册时间
2019-10-19
在线时间
25 小时
发表于 2020-12-1 01:22:21 | 显示全部楼层 |阅读模式
从咸鱼上买了一块二手的阿波罗767核心板,根据自己的需求制作了一块底板,看了原子的767综合历程,非常喜欢它的滑屏。但原子的例程是竖屏的而本人需要横屏显示,在原子论坛上搜索相关修改成横屏的帖子,大家都在说因为要改很多东西,而放弃。其实有人想改成横屏只是想要它的横向滑
屏效果,至于里面的功能大部分是根据自己的需要来做删减。
我在修改成横屏的过程中摸索了1个多星期,今天终于想通了它的显示原理并修改成功!现在把修改过程做个简单的介绍。由于本人是业余爱好者,
所学专业并非电子或软件而是景观设计专业,接触STM也就大半年时间,在讲述过程中所用的术语可能不标准,请大家不要喷!
本例程修改是以RGB屏800X400为例,其他分辨大家自己参考修改

第一次修改成横屏的时候是下面显示的样子,估计很多人改成横屏基本都这样!
1.png
而且左右滑屏时,滑屏区域是上下移动,与原效果差距太大,且显示界面是乱码。对此我仔细读究原子的代码,主要看SPB.C(这个代码主要设置
显示图标的各个参数)及SPBLCD.C (这个代码用来滑屏显示)。
第一步首先要修改的是void LCD_Init(void)初始化函数中的显示方向,大概在1836行,把LCD_Display_Dir(0)改为LCD_Display_Dir(1);这是最基本的,大家都会改这个。
当然改完后直接编译下载就成了上图的效果。对此我把原子SPBLCD.C中的画点函数一个个标识在它的竖向显示背景图片中后发现它有如下规律。
/在指定位置画点.
//x,y:坐标
//color:颜色.
void slcd_draw_point(u16 x,u16 y,u16 color)
{         
        if(lcdltdc.pwidth)x=spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2-x-1;
        sramlcdbuf[y+x*spbdev.spbheight]=color;
}

2.png
图片中的color指针数组的0点是在右上角,从右上角往下递增,从右往左递增。如果把这张图片逆时针旋转90°刚好是RGB屏的扫描方向,因为RGB屏的扫描方式以
设备界面固定不变的,例如800X480的屏,它以800作为X轴,480作为Y轴,扫描是从左往右,从上到下,那么我们要显示的像素指针数组也要与它相适应,也要
从左往右曾大,从上到下增大,如果不一一对应,读出来的像素点就错误了。
那么如果把图片改为横向显示且是我们所用的尺寸大小其color指针数组如下图所示
3.png
color指针数组与RGB屏扫面方向是一致的,但在调用LTDC_Color_Fill()函数时会出现一个问题,那就是LTDC_Color_Fill()使用DMA传输,而
在传输过程中color指针会一直递增当它超过我们屏幕显示区域后它不能自动换行,举例说明一下,正常情况下我们要的显示效果是,如果滑屏后
传递过来的X坐标值,那么我要显示应该是从color[x]处开始读取它的像素数据,读到color[屏幕宽度]后,color指针数组要跳到下行的X处,但DMA传进去的
只是color[x]的首地址,之后它的地址会一直递增而不会跳到下行X处的位置,因此我把SPBLCD.C中void slcd_frame_show(u32 x)函数做了 如下修改,
//显示一帧,即启动一次spi到lcd的显示.
//x:坐标偏移量
void slcd_frame_show(u32 x)
{  
        if(lcdltdc.pwidth)
        {
//                x=spbdev.spbwidth*(SPB_PAGE_NUM-1)+spbdev.spbahwidth*2-x;
//                LTDC_Color_Fill(0,spbdev.stabarheight,spbdev.spbwidth-1,spbdev.stabarheight+spbdev.spbheight-1,sramlcdbuf+x*spbdev.spbheight);
                u16 i;
                for(i=0;i<spbdev.spbheight;i++)
                {

                        LTDC_Color_Fill(0,spbdev.stabarheight+i,spbdev.spbwidth-1,spbdev.stabarheight+i,sramlcdbuf+x+i*(spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2));
                }

每次传递一行参数,一共用传递spbdev.spbheight次,spbdev.spbheight是滑屏显示的高度,这样就解决了指针不会跳行的问题(这是我自己的理解,如果大家有更好办法可以跟一下贴)
因为原子用竖屏传递参数不存在这问题,所以它只要给了color的首地址,首地址一直递增后自动回到下一行的首地址(这跟它的图片像素*color数组排列有关)。

下面我把修改过的地方一一贴出来,大家可以根据自己的屏幕大小自行参考修改
在SPB.C中需要修改的地方

第一处
        }else if(lcddev.width==800)        //对于800*1280的LCD屏幕//对于800*48的RGB屏幕
        {
//                icowidth=110;
//                micoyoff=18;
//                lcdtype=5;
//                icoindex=2;
//                spbdev.stabarheight=30;
//                spbdev.spbheight=1090;
//                spbdev.spbwidth =800;
//                spbdev.spbfontsize=16;
                icowidth=110;      
                micoyoff=10;      
                lcdtype=5;
                icoindex=2;
                spbdev.stabarheight=30;
                spbdev.spbheight=300;            //我自己定义的滑屏的高度
                spbdev.spbwidth =800;
                spbdev.spbfontsize=16;
        }



第二处----(只改了红色字体处,上下图标的间距,根据自己需要修改)
for(i=0;i<SPB_ICOS_NUM;i++)
        {
                spbdev.icos.width=icowidth;        //必须 等于图片的宽度尺寸
                spbdev.icos.height=icowidth+spbdev.spbfontsize+spbdev.spbfontsize/4;
                spbdev.icos.x=icoxpit/2+(i%4)*(icowidth+icoxpit)+(i/8)*spbdev.spbwidth;
                spbdev.icos.y=spbdev.stabarheight+10+((i%8)/4)*(spbdev.icos.height+15);

                spbdev.icos.path=(u8*)spb_icos_path_tbl[icoindex];
                spbdev.icos.name=(u8*)icos_name_tbl[gui_phy.language];
        }         


在SPBLCD.C中需要修改的地方
//在指定位置画点.
//x,y:坐标
//color:颜色.
void slcd_draw_point(u16 x,u16 y,u16 color)
{         
        if(lcdltdc.pwidth&&lcdltdc.dir==0)
        {
                x=spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2-x-1;
                sramlcdbuf[y+x*spbdev.spbheight]=color;
        }else if(lcdltdc.pwidth&&lcdltdc.dir==1)
                        {
                                sramlcdbuf[x+y*(spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2)]=color;
                        }

}
//读取指定位置点的颜色值
//x,y:坐标
//返回值:颜色
u16 slcd_read_point(u16 x,u16 y)
{
        if(lcdltdc.pwidth&&lcdltdc.dir==0)      
                {
                        x=spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2-x-1;
                        return sramlcdbuf[y+x*spbdev.spbheight];
                }
                else if(lcdltdc.pwidth&&lcdltdc.dir==1)
                        {
                                return        sramlcdbuf[x+y*(spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2)];
                        }
}

其实这两个函数改不改都没关系,因为滑屏中并没有使用到他们。

最后一个修改在
//显示一帧,即启动一次spi到lcd的显示.
//x:坐标偏移量
void slcd_frame_show(u32 x)
{  
        if(lcdltdc.pwidth)
        {
//                x=spbdev.spbwidth*(SPB_PAGE_NUM-1)+spbdev.spbahwidth*2-x;
//                LTDC_Color_Fill(0,spbdev.stabarheight,spbdev.spbwidth-1,spbdev.stabarheight+spbdev.spbheight-1,sramlcdbuf+x*spbdev.spbheight);
                u16 i;
                for(i=0;i<spbdev.spbheight;i++)
                {


                        LTDC_Color_Fill(0,spbdev.stabarheight+i,spbdev.spbwidth-1,spbdev.stabarheight+i,sramlcdbuf+x+i*(spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2));
                }
        }else

改完后,做一张横向显示的图片,我用的是RGB800X400根据spbdev.spbwidth*SPB_PAGE_NUM+spbdev.spbahwidth*2算得X轴长度为2800
Y轴我定义了300,所以图片像素为2800X300,然后保存到你代码要求的相应文件夹内。
4.JPG
最后就是这样的显示效果!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

109

主题

5564

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10561
金钱
10561
注册时间
2017-2-18
在线时间
1911 小时
发表于 2020-12-1 15:50:09 | 显示全部楼层
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2020-12-22 16:55:31 | 显示全部楼层
cool
回复 支持 反对

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
发表于 2020-12-22 21:27:43 | 显示全部楼层
你好,我在移植正点原子nes游戏模拟器也碰到这个问题,不知道如何解决,可以告知下联系方式吗?我想请你有偿解决
回复 支持 反对

使用道具 举报

13

主题

107

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1242
金钱
1242
注册时间
2015-9-26
在线时间
356 小时
发表于 2021-2-2 16:10:47 | 显示全部楼层
我按照这个方法试了,可是界面刷新的很慢。
回复 支持 反对

使用道具 举报

1

主题

6

帖子

1

精华

初级会员

Rank: 2

积分
167
金钱
167
注册时间
2019-10-19
在线时间
25 小时
 楼主| 发表于 2021-3-14 15:32:50 | 显示全部楼层
xqn2012 发表于 2021-2-2 16:10
我按照这个方法试了,可是界面刷新的很慢。

不要把图片放在sd卡里,那样会卡顿。把图片放在W25QXXX里
回复 支持 反对

使用道具 举报

13

主题

107

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1242
金钱
1242
注册时间
2015-9-26
在线时间
356 小时
发表于 2021-3-16 17:39:28 | 显示全部楼层
arkingzhou 发表于 2021-3-14 15:32
不要把图片放在sd卡里,那样会卡顿。把图片放在W25QXXX里

就是在W25Q 里的
回复 支持 反对

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1429
金钱
1429
注册时间
2019-4-22
在线时间
272 小时
发表于 2021-10-13 21:58:47 | 显示全部楼层
你好,请问这个问题你解决了吗
回复 支持 反对

使用道具 举报

14

主题

821

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2070
金钱
2070
注册时间
2021-7-17
在线时间
647 小时
发表于 2022-1-8 17:23:03 | 显示全部楼层
赞一个  
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-26 06:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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