OpenEdv-开源电子网

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

请教关于《SD卡图片显示+文件系统》中的问题

[复制链接]

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2012-12-4
在线时间
14 小时
发表于 2013-2-19 17:22:46 | 显示全部楼层 |阅读模式
请教原子哥:
    
       今天移植你的战舰版中《实验42 图片显示实验》时,发现个问题,求解??
目的:我要显示32位带alpha通道的bmp图片
现象:图片显示有淡红色的虚线
过程:
u8 minibmp_decode(u8 *filename,u16 x,u16 y,u16 width,u16 height,u16 acolor,u8 mode) 中
先是使用了f_lseek(f_bmp,pbmp->bmfHeader.bfOffBits);
再执行  res=f_read(f_bmp,databuf,readlen,(UINT *)&br); 
(readlen=1024;)
读出来的数据中间会出错.

我把 res=f_read(f_bmp,databuf,readlen,(UINT *)&br); 
改成
    res=f_read(f_bmp,databuf,readlen/2,(UINT *)&br); //读出readlen个字节
    res=f_read(f_bmp,databuf+readlen/2,readlen/2,(UINT *)&br); //读出readlen个字节
    br *=2;
暂时解决问题,

求解:
1、难道f_read一次只能读<512的数据吗?或者说f_read跟SD 卡的簇有关
2、但是在stdbmp_decode中一次读取1024个字节也没出现问题啊,不同的是stdbmp_decode中没用到f_lseek;



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

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-2-20 08:34:48 | 显示全部楼层
1,可以一次读大于512字节的,关键你的buf大小得容得下.
2,把你的这个bmp图片上传下,我测试下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2012-12-4
在线时间
14 小时
 楼主| 发表于 2013-2-20 09:36:32 | 显示全部楼层

 buf  我使用的是动态内存(malloc)
原png图片:




用ps直接将png存成32位bmp,整张图的alpha都位0;后发现需要选中需透明区域重新制作alpha通道,(MYPIC256.bmp)



我将图片缩成100X100;
使用futurixalpha将png转成32位bmp(MYPIC300.bmp),在windows中显示成了这样


使用res=f_read(f_bmp,databuf,readlen,(UINT *)&br); //读出readlen个字节
监控缓存中读出的数据,第一次读出有问题,第二次就没有问题,第三次有问题,第四次又没问题,如此循环。
在7寸屏tft屏上显示成这样



使用res=f_read(f_bmp,databuf,readlen/2,(UINT *)&br); //读出readlen个字节
    res=f_read(f_bmp,databuf+readlen/2,readlen/2,(UINT *)&br); //读出readlen个字节
    br *=2;
显示没有问题,能够实现透明背景显示


原子哥,帮我测试下MYPIC300.bmp的显示,谢谢啦!
IMG_20130220_090239.jpg
MYPIC256.bmp
PNG256.png
MYPIC300.bmp

futurixalpha(PNGtoBMP).exe

1.82 MB, 下载次数: 533

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-2-20 11:54:11 | 显示全部楼层
7寸屏,是不是你的驱动器有问题啊?
用的什么驱动?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2012-12-4
在线时间
14 小时
 楼主| 发表于 2013-2-20 13:15:07 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
驱动器没有问题的,一直用的很好,包括图片显示,
用stdbmp_decode显示都没问题的,
问题出在minibmp_decode函数sd卡的文件系统FATS中的f_read

原子哥你用minibmp_decode函数测试下我的MYPIC300.bmp图片,看看效果是不是跟我的一样
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-2-20 15:48:05 | 显示全部楼层
//智能画图
//FileName:要显示的图片文件  BMP/JPG/JPEG/GIF
//x,y,width,height:坐标及显示区域尺寸
//acolor:alphablend的颜色(仅对不大于320*240的32位bmp有效!)
//abdnum:alphablend的值(0~32有效,其余值表示不使用alphablend,仅对不大于320*240的32位bmp有效!)
//图片在开始和结束的坐标点范围内显示
u8 ai_load_picfile(const u8 *filename,u16 x,u16 y,u16 width,u16 height)
{
u8 res;//返回值
u8 temp;
if((x+width)>lcddev.width)return IC_WINDOW_ERR; //x坐标超范围了.
if((y+height)>lcddev.height)return IC_WINDOW_ERR; //y坐标超范围了.  
//得到显示方框大小     
if(width==0||height==0)return IC_WINDOW_ERR; //窗口设定错误
picinfo.S_Height=height;
picinfo.S_Width=width;
//显示区域无效
if(picinfo.S_Height==0||picinfo.S_Width==0)
{
picinfo.S_Height=lcddev.height;
picinfo.S_Width=lcddev.width;
return FALSE;   
}
//显示的开始坐标点
picinfo.S_YOFF=y;
picinfo.S_XOFF=x;
//文件名传递  
temp=f_typetell((u8*)filename); //得到文件的类型
switch(temp)
{   
case T_BMP:
res=minibmp_decode((u8*)filename,0,0,240,320,0,0); //解码bmp      
break;
case T_JPG:
case T_JPEG:
res=jpg_decode(filename);  //解码JPG/JPEG      
break;
case T_GIF:
res=gif_decode(filename,x,y,width,height); //解码gif     
break;
default:
  res=PIC_FORMAT_ERR;   //非图片格式!!!  
break;
}      
return res;
}


测试无问题.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2012-12-4
在线时间
14 小时
 楼主| 发表于 2013-2-20 19:32:22 | 显示全部楼层

原子哥:
以上我找到原因了;
原因是我的SD卡读写是以一个字节为单位的,
SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
而在文件系统ff.c中f_read函数下执行 if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) 时,又以4个字节来存放,导致执行后覆盖了前面两个字节
比如:先是执行mem_cpy,存放42个字节到rbuff中,再执行disk_read,数据从第41个字节处开始存放,(覆盖了前面两个字节)

原子哥:
在不修改ff.c和SD_ReadMultiBlocks仍然使用8位读写的前提下,有什么解决办法吗?

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-2-20 20:22:24 | 显示全部楼层
我就是以字节为单位读取的啊,没出现你说的问题.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
103
金钱
103
注册时间
2012-12-4
在线时间
14 小时
 楼主| 发表于 2013-2-21 09:50:01 | 显示全部楼层

原子哥:

        我使用的SDIO 4线DMA模式:
问题出在这:(红色标记处)
SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize)
{
  SD_Error errorstatus = SD_OK;
#if defined (SD_POLLING_MODE)
  uint32_t count = 0, *tempbuff = (uint32_t *)readbuff;
#endif

  TransferError = SD_OK;
  TransferEnd = 0;  //传输结束标置位,在中断服务置1
  StopCondition = 0;  //怎么用的?
 
  SDIO->DCTRL = 0x0;

 
  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    ReadAddr /= 512;
  }
  /*******************add,没有这一段容易卡死在DMA检测中*************************************/
    /*!< Set Block Size for Card,cmd16,若是sdsc卡,可以用来设置块大小,若是sdhc卡,块大小为512字节,不受cmd16影响 */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;   //r1
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);

  if (SD_OK != errorstatus)
  {
    return(errorstatus);
  }
 /*********************************************************************************/
  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
  SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
  SDIO_DataConfig(&SDIO_DataInitStructure);

  /*!< Send CMD17 READ_SINGLE_BLOCK */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_SINGLE_BLOCK;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);

  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }

#if defined (SD_POLLING_MODE) 
#elif defined (SD_DMA_MODE)
    SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE);
    SDIO_DMACmd(ENABLE);
    SD_DMA_RxConfig((uint32_t *)readbuff, BlockSize);
#endif

  return(errorstatus);
}

SD_DMA_RxConfig的原型函数只能以32位读取;而我的文件系统和SD_ReadBlock都是以字节为单位读取的;

原子哥有什么解决办法吗??

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-2-21 10:10:30 | 显示全部楼层
原来你用的SDIO哦,这个SDIO的数据读取,是存储在32位寄存器的.没法修改,你强制转换就可以了,不会带来不良影响.
前阵子我也在调试sdio,发现兼容性不好,测试了网上很多版本的,我手头的几种卡,总有些不能识别,还不如SPI模式(SPI模式只有1张卡不能识别),不知道谁有比较完善的SDIO代码,给我参考下哈,呵呵.
SDIO识别16G金士顿卡,总是不能正确使用.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2014-4-1
在线时间
0 小时
发表于 2014-11-15 15:14:39 | 显示全部楼层
回复【8楼】正点原子:
---------------------------------
原子哥,请问下载这个图片显示的程序里面加入NRF24L01接收代码后怎么不能接收数据呢,然后我查了是SPI共用了,这样的问题怎么解决呢?急用!!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-11-15 23:11:04 | 显示全部楼层
回复【12楼】潘明星:
---------------------------------
我也不知道。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-29 03:31

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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