OpenEdv-开源电子网

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

请教!!!怎样从外部FLASH读取大图片数据,并显示在LCD上!

[复制链接]

1

主题

6

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-10
在线时间
0 小时
发表于 2012-12-10 13:36:46 | 显示全部楼层 |阅读模式
现在已经做好了从上位机串口把大图片数据通过串口传到下位机,并写入到外部FLASH里,并且可以正常读取!(写的小图片,只是做个试验,只是证明方案可行)
但现在问题来了!!!
如果我要显示在LCD上,在程序里开不了这么大的BUFF,最多18K左右的缓冲区,但240*320的16位真彩图片有130多K,求解决办法!!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-10
在线时间
0 小时
 楼主| 发表于 2012-12-10 13:56:21 | 显示全部楼层
我现在想到了一个解决办法,因为每个图形都有头数据,我把前8个字节的头数据赋给imginfo=(HEADCOLOR*)imgx;这个结构体,然后再把第9个数据和后面的数据一个个的读出,并打点。。。image_show(x,y,x+imginfo->w-1,y+imginfo->h-1,imginfo->scan,imgx+ifosize);
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-10 14:31:19 | 显示全部楼层
回复【楼主位】0o小松o0:
---------------------------------
直接将数据丢到LCD,不缓存。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-10
在线时间
0 小时
 楼主| 发表于 2012-12-10 16:47:32 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
如果用原子的那个画图函数,前8个字节 头数据 要存下来 给结构体吧!然后后面可以直接丢,是吗?
回复 支持 反对

使用道具 举报

5

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2011-6-24
在线时间
7 小时
发表于 2012-12-10 17:42:12 | 显示全部楼层
图片格式的信息保存到结构体里面,保存到外部Flash。剩下的数据收一行,写一行。显示的时候也是先读取结构体头文件,然后读一行,刷一行。如果不是动态帧的话,刷新速度应该还行吧。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-10 22:16:56 | 显示全部楼层
回复【4楼】0o小松o0:
---------------------------------
是的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-10
在线时间
0 小时
 楼主| 发表于 2012-12-12 11:04:17 | 显示全部楼层
回复【6楼】正点原子:
---------------------------------
现在可以从外部FLASH读取240*320的图片并正常显示了,现在没有用串口烧录图片数据了,发现还是有错位或者误码率的存在,错一位就后面整个数据都错了,所以还是自己写了一个FLASH烧录的小程序,把大图数据分2次烧录到外部FLASH,然后再读取显示,但现在的刷图速度好慢,刷完一个240*320的图 大概要花3-4秒左右,是不是我的代码的效率太低了,我把我的显示这部分的代码发上来,能帮我看下吗?
if((GPIOA->IDR & GPIO_Pin_13) == 0)

    GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    W25X_Read_Bytes(0, Head, 8);
    image_display(0,0,(u8*)Head);
    GPIO_SetBits(GPIOD,GPIO_Pin_2);
}
void image_display(u16 x,u16 y,u8 * imgx)
{
    HEADCOLOR *imginfo; 
    u8 ifosize=sizeof(HEADCOLOR);//得到HEADCOLOR结构体的大小
    imginfo=(HEADCOLOR*)imgx;
    image_show(x,y,x+imginfo->w-1,y+imginfo->h-1,imginfo->scan,imgx+ifosize);
}
void image_show(u16 xsta,u16 ysta,u16 xend,u16 yend,u8 scan,u8 *p)
{  
    u32 i;
    u32 len=0;
    LCD_Set_Window(xsta,ysta,xend,yend);
    if((scan&0x03)==0)//水平扫描
{
    switch(scan>>6)//设置扫描方式
   {
        case 0:
        LCD_Scan_Dir(L2R_U2D);//从左到右,从上到下
        LCD_SetCursor(xsta,ysta);//设置光标位置 
        break; 
        case 1:
        LCD_Scan_Dir(L2R_D2U);//从左到右,从下到上
        LCD_SetCursor(xsta,yend);//设置光标位置 
        break; 
        case 2:
        LCD_Scan_Dir(R2L_U2D);//从右到左,从上到下
        LCD_SetCursor(xend,ysta);//设置光标位置 
        break; 
        case 3:
        LCD_Scan_Dir(R2L_D2U);//从右到左,从下到上
        LCD_SetCursor(xend,yend);//设置光标位置 
        break; 
    }
}
else  //垂直扫描
{
    switch(scan>>6)//设置扫描方式
    {
        case 0:
        LCD_Scan_Dir(U2D_L2R);//从上到下,从左到右
        LCD_SetCursor(xsta,ysta);//设置光标位置 
        break; 
        case 1:
        LCD_Scan_Dir(D2U_L2R);//从下到上从,左到右
        LCD_SetCursor(xsta,yend);//设置光标位置 
        break; 
        case 2:
        LCD_Scan_Dir(U2D_R2L);//从上到下,从右到左 
        LCD_SetCursor(xend,ysta);//设置光标位置 
        break; 
        case 3:
        LCD_Scan_Dir(D2U_R2L);//从下到上,从右到左
        LCD_SetCursor(xend,yend);//设置光标位置 
        break; 
    }

    LCD_WriteRAM_Prepare();      //开始写入GRAM
    len=(xend-xsta+1)*(yend-ysta+1); //写入的数据长度
    for(i=0;i<(len+len);i++)
    {
        if((i%2) == 0)
        {
            W25X_Read_Bytes(8+i,Buffer, 1);
            W25X_Read_Bytes(9+i,Buffer_color, 1);
            LCD_WR_DATA(image_getcolor(scan&(1<<4),Buffer));
        }
    }   
#if USE_HORIZONTAL  //使用横屏
LCD_Set_Window(0,0,319,239);
#else
LCD_Set_Window(0,0,239,319);
#endif             
}
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-12 11:14:29 | 显示全部楼层
回复【7楼】0o小松o0:
---------------------------------
效率确实不高,一次多读一些数据吧,比如一次读4K字节,然后一次性写完4K,再读下一次,这样可以快很多。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-10
在线时间
0 小时
 楼主| 发表于 2012-12-12 20:39:17 | 显示全部楼层

回复【8楼】正点原子:
---------------------------------
修改后的程序,速度快了好多,我试了一下一次读15000个点,10000个点,8000个点,5000个点,4000个点的速率,高于5000就没意义了 差不多的了,而且高于8000后,刷图的时候会感觉明显的停顿(求解释,有点不懂!),还有另外看看,有没有更有效率的方法,现在刷一个240*320的图不超过1秒。。估计就0.7秒左右!
u16 image_getcolor(u8 mode,u8 *str)
{
    u16 color;

    if(mode)
    {
        color=((u16)*str++)<<8;
        color|=*str;
    }
    else
    {
        /*color=Buffer[0];
        color|=Buffer_color[0]<<8;*/
        color=*str++;
        color|=((u16)*str)<<8;
    } 

    return color;
}
//在液晶上画图
//xsta,ysta,xend,yend:画图区域
//scan:见image2lcd V2.9的说明.
//*p:图像数据
int number = 0;
void image_show(u16 xsta,u16 ysta,u16 xend,u16 yend,u8 scan,u8 *p)
{  
    u32 i;
    u32 u;
    u32 len=0;
    LCD_Set_Window(xsta,ysta,xend,yend);
    if((scan&0x03)==0)//水平扫描
    {
        switch(scan>>6)//设置扫描方式
    {
        case 0:
        LCD_Scan_Dir(L2R_U2D);//从左到右,从上到下
        LCD_SetCursor(xsta,ysta);//设置光标位置  
        break;  
        case 1: 
        LCD_Scan_Dir(L2R_D2U);//从左到右,从下到上 
        LCD_SetCursor(xsta,yend);//设置光标位置  
        break;  
        case 2: 
        LCD_Scan_Dir(R2L_U2D);//从右到左,从上到下 
        LCD_SetCursor(xend,ysta);//设置光标位置  
        break;  
        case 3: 
        LCD_Scan_Dir(R2L_D2U);//从右到左,从下到上 
        LCD_SetCursor(xend,yend);//设置光标位置  
        break;  
    }
}
    else  //垂直扫描 
    { 
        switch(scan>>6)//设置扫描方式 
    { 
        case 0: 
        LCD_Scan_Dir(U2D_L2R);//从上到下,从左到右 
        LCD_SetCursor(xsta,ysta);//设置光标位置  
        break;  
        case 1: 
        LCD_Scan_Dir(D2U_L2R);//从下到上从,左到右 
        LCD_SetCursor(xsta,yend);//设置光标位置  
        break;  
        case 2: 
        LCD_Scan_Dir(U2D_R2L);//从上到下,从右到左  
        LCD_SetCursor(xend,ysta);//设置光标位置  
        break;  
        case 3: 
        LCD_Scan_Dir(D2U_R2L);//从下到上,从右到左 
        LCD_SetCursor(xend,yend);//设置光标位置  
        break;  
    }

    LCD_WriteRAM_Prepare();      //开始写入GRAM 
    len=(xend-xsta+1)*(yend-ysta+1); //写入的数据长度 
    if((len+len)%5000 == 0) 
    { 
        number = (len+len)/5000; 
        for(u=0;u<number;u++) 
        { 
            W25X_Read_Bytes(8+(u*5000),Buffer, 5000); 
            for(i=0;i<5000;i++) 
            { 
                if(i%2 == 0) 
                { 
                    LCD_WR_DATA(image_getcolor(scan&(1><<4),Buffer)); 
                    Buffer[0] = Buffer[i+2]; 
                    Buffer[1] = Buffer[i+3]; 
                } 
            } 
        } 
    } 
    else 
    { 
        number = ((len+len)/5000) + 1; 
        for(u=0;u<number-1;u++) 
        { 
            W25X_Read_Bytes(8+(u*5000),Buffer, 5000); 
            for(i=0;i<5000;i++) 
        { 
            if(i%2 == 0) 
            { 
                LCD_WR_DATA(image_getcolor(scan&(1><<4),Buffer)); 
                Buffer[0] = Buffer[i+2]; 
                Buffer[1] = Buffer[i+3]; 
            } 
        } 
    } 
    W25X_Read_Bytes(8+(5000*(number-1)),Buffer, (len+len)-(5000*(number-1))); 
    for(i=0;i<(len+len)-(5000*(number-1));i++) 
    { 
        if(i%2 == 0) 
        { 
            LCD_WR_DATA(image_getcolor(scan&(1<<4),Buffer)); 
            Buffer[0] = Buffer[i+2]; 
            Buffer[1] = Buffer[i+3]; 
        } 
    }

    /*for(i=0;i<(len+len);i++) 
        { 
        if((i%2) == 0) 
        { 
            W25X_Read_Bytes(8+i,Buffer, 1); 
            W25X_Read_Bytes(9+i,Buffer_color, 1); 
            LCD_WR_DATA(image_getcolor(scan&(1<<4),Buffer)); 
        } 
        }*/  
#if USE_HORIZONTAL  //使用横屏
LCD_Set_Window(0,0,319,239);
#else
LCD_Set_Window(0,0,239,319);
#endif             
}  

//在指定的位置显示一个图片
//此函数可以显示image2lcd软件生成的任意16位真彩色图片.
//限制:1,尺寸不能超过屏幕的区域.
//     2,生成数据时不能勾选:高位在前(MSB First)
//     3,必须包含图片信息头数据
//x,y:指定位置
//imgx:图片数据(必须包含图片信息头,"4096色/16位真彩色/18位真彩色/24位真彩色/32位真彩色”的图像数据头)
//注意:针对STM32,不能选择image2lcd的"高位在前(MSB First)"选项,否则imginfo的数据将不正确!!
void image_display(u16 x,u16 y,u8 * imgx)

    HEADCOLOR *imginfo; 
    u8 ifosize=sizeof(HEADCOLOR);//得到HEADCOLOR结构体的大小 
    imginfo=(HEADCOLOR*)imgx; 
    image_show(x,y,x+imginfo->w-1,y+imginfo->h-1,imginfo->scan,imgx+ifosize);
}

回复 支持 反对

使用道具 举报

44

主题

121

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
412
金钱
412
注册时间
2012-7-1
在线时间
58 小时
发表于 2014-11-11 11:45:00 | 显示全部楼层
回复【9楼】0o小松o0:
---------------------------------
主函数要怎么写啊
回复 支持 反对

使用道具 举报

70

主题

275

帖子

0

精华

高级会员

Rank: 4

积分
729
金钱
729
注册时间
2017-6-20
在线时间
188 小时
发表于 2017-8-21 17:19:53 | 显示全部楼层
你好楼主,可以给我发一份您的程序吗?
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2018-8-21
在线时间
9 小时
发表于 2018-8-27 17:43:39 | 显示全部楼层
楼主为什么我用了你的程序显示了很多黑色的横线?能回复下?
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2018-7-6
在线时间
2 小时
发表于 2018-10-23 22:34:46 | 显示全部楼层
请问一下*Buffer是怎么定义的
回复 支持 反对

使用道具 举报

3

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2018-8-11
在线时间
28 小时
发表于 2019-9-11 14:16:18 | 显示全部楼层
您好 你的图片是怎样存到外部flash中的?图片是生成C语言格式位图存储的吗? 期待回复
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-28 13:58

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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