金牌会员
 
- 积分
- 1823
- 金钱
- 1823
- 注册时间
- 2014-8-5
- 在线时间
- 211 小时
|

楼主 |
发表于 2015-6-28 10:04:46
|
显示全部楼层
发现一个错误漏洞:
所有的图片显示都是通过查询图片对应的索引,然后再调用显示指定索引图片显示,由于考虑到大小端问题,程序中加入大小端校验及转换,但是在显示指定所有图片需转换条件下,转换错误,错误代码如下:(以低速显示图片函数为例)
#else //低速显示图片
BMP_u8 FLASH_BMP_play(BMP_u8 num) //指定索引 图片显示 返回 0成功 其它失败
{
BMP_u8 code_buf[8]={0}; //数组数据缓存
BMP_u16 adress=0; //偏移地址
BMP_u8 i=0 ; //循环计数
SPI_Flash_Read((unsigned char*)&BMP_Code,OLED_BMP_START+num*(sizeof(bmp_code_typ)-4),sizeof(bmp_code_typ)-4); //读取指定图片数据指针结构体
if((BMP_Code.start==0x5A)&&(BMP_Code.end==0XA5)) //是否存在
{
if(BMP_Code.MOS_flaot==0x1234) //无需进行大小端转换
{
for(adress=0;adress<1024;) //循环写入
{
if(adress%128==0) //是否翻页
{
OLED_Set_Pos(0,adress/128); //设置页地址
}
SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8); //读取FLASH 内数据
for(i=0;i<8;i++) //写入数据到 OLED
{
OLED_WrDat(code_buf);
}
adress += 8; //地址偏移
}
return 0; //返回成功
}
else if(BMP_Code.MOS_flaot==0x3412) //需进行大小端转换 图片索引 及 图片数组数据地址 需转换
{
BMP_Code.bmp_num=((BMP_Code.bmp_num&0xff00)>>8)|((BMP_Code.bmp_num&0x00ff)<<8); //图片索引大小端转换
for(adress=0;adress<1024;) //循环写入
{
if(adress%128==0) //是否翻页
{
OLED_Set_Pos(0,adress/128); //设置页地址
}
SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8); //读取FLASH 内数据
for(i=0;i<8;i++) //数据 写入OLED
{
OLED_WrDat(code_buf);
}
adress += 8; //地址偏移
}
return 0; //返回成功
}
}
return 1; //返回失败
}
#endif
以上红色区域为错误对应,我的想法是根据大小端校验(0X3412),如果需要转换,应该是把读到的数据起始地址转换而不是索引。但考虑到如果图片数量过多(大于255),则索引也会出现大小端问题,所有我在调用显示指定索引图片函数之前,先对索引判断是否需要大小端转换,如果要转换则转换完成后再调用指定索引图片显示。原先指定索引图片显示里对索引进行转换改为对数据起始地址进行转换。
需改后的代码如下:
BMP_u8 FLASH_BMP_ID_play(BMP_u8 *BMP_ID) //显示FLASH中指定ID图片 返回0成功 1失败
{
BMP_u16 BMP_MAX = FLASH_BMP_Scan(); //当前FLASH 图片总数
#if UART_TEST__EN
Uart_printf(" 输入数组长度为 %d \r\n",strlen(BMP_ID));
#endif
while(BMP_MAX--) //从后向前轮询
{
#if UART_TEST__EN
Uart_printf(" 当前扫描索引为 %d \r\n",BMP_MAX);
#endif
SPI_Flash_Read((unsigned char*)&BMP_Code,OLED_BMP_START+BMP_MAX*(sizeof(bmp_code_typ)-4),sizeof(bmp_code_typ)-4); //读取指定索引图片指针数据
if(strcmp(BMP_Code.bmp_ID,BMP_ID)==0)
{
if(BMP_Code.MOS_flaot==0x1234) //无需进行大小端转换
{
#if UART_TEST__EN
Uart_printf(" 对应图片的索引为 %d \r\n",BMP_Code.bmp_num);
#endif
FLASH_BMP_play(BMP_Code.bmp_num); //显示指定索引图片
return 0;
}
else if(BMP_Code.MOS_flaot==0x3412) //需要大小端转换
{
BMP_Code.bmp_num=((BMP_Code.bmp_num&0xff00)>>8)|((BMP_Code.bmp_num&0x00ff)<<8); //图片索引大小端转换
#if UART_TEST__EN
Uart_printf(" 对应图片的索引为 %d \r\n",BMP_Code.bmp_num);
#endif
FLASH_BMP_play(BMP_Code.bmp_num); //显示指定索引图片
return 0;
}
}
}
#if UART_TEST__EN
Uart_printf(" 没有找到对应图片! \r\n");
#endif
return 1; //没有找到
}
#else //低速显示图片
BMP_u8 FLASH_BMP_play(BMP_u8 num) //指定索引 图片显示 返回 0成功 其它失败
{
BMP_u8 code_buf[8]={0}; //数组数据缓存
BMP_u16 adress=0; //偏移地址
BMP_u8 i=0 ; //循环计数
SPI_Flash_Read((unsigned char*)&BMP_Code,OLED_BMP_START+num*(sizeof(bmp_code_typ)-4),sizeof(bmp_code_typ)-4); //读取指定图片数据指针结构体
if((BMP_Code.start==0x5A)&&(BMP_Code.end==0XA5)) //是否存在
{
if(BMP_Code.MOS_flaot==0x1234) //无需进行大小端转换
{
for(adress=0;adress<1024;) //循环写入
{
if(adress%128==0) //是否翻页
{
OLED_Set_Pos(0,adress/128); //设置页地址
}
SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8); //读取FLASH 内数据
for(i=0;i<8;i++) //写入数据到 OLED
{
OLED_WrDat(code_buf);
}
adress += 8; //地址偏移
}
return 0; //返回成功
}
else if(BMP_Code.MOS_flaot==0x3412) //需进行大小端转换 图片索引 及 图片数组数据地址 需转换
{
BMP_Code.bmp_aderr = ((BMP_Code.bmp_aderr & 0xff000000) >> 24)\
| ((BMP_Code.bmp_aderr & 0x00ff0000) >> 8)\
| ((BMP_Code.bmp_aderr & 0x0000ff00) << 8)\
| ((BMP_Code.bmp_aderr & 0x000000ff) << 24); //数据起始地址进行大小端转换
for(adress=0;adress<1024;) //循环写入
{
if(adress%128==0) //是否翻页
{
OLED_Set_Pos(0,adress/128); //设置页地址
}
SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8); //读取FLASH 内数据
for(i=0;i<8;i++) //数据 写入OLED
{
OLED_WrDat(code_buf);
}
adress += 8; //地址偏移
}
return 0; //返回成功
}
}
return 1; //返回失败
}
#endif
此方案可以直接在OLED_BMP_CONFIG.h中修改宏的值 用于设置
设置宏如下:
//快速显示图片使能 1 快速显示---------------------------------------
#define   LAY_BMP_SPEED 0 //关闭 可节约800多字节 RAM
// 串口调试 使能------------------------------------------------------
#define UART_TEST__EN 1 //为1时开启串口调试 必须包含串口头文件
// FLASH图片数据修改 使能---------------------------------------------
#define FLASH_DATA_SET_EN 1 //为1时 允许修改FLASH图片数据
//本次写入FLASH 图片数据个数 必须宏 FLASH_DATA_SET_EN 大于0 有效
#define BMP_FONT_NUM 3 //当前数组图片个数 请与OLED_BMP_FONT.C 中图片数据个数对应 大于图片数据数量后面写入图片为乱码
#define FLASH_Volume ((BMP_u32)2) //FLASH容量 单位: M
#define FLASH_Sector_SIZE ((BMP_u32)4096) //FLASH扇区大小 单位: 字节
#define BMP_SIZE ((BMP_u32)200*1024) //FLASH给与图片数据字节大小
#define BMP_ALL_Sector (BMP_SIZE/FLASH_Sector_SIZE) //FLASH给与图片数据扇区数
#define FLASH_ALL_Adress ((BMP_u32)FLASH_Volume*1024*1024) //FLASH总字节地址
#define OLED_BMP_START (FLASH_ALL_Adress-BMP_SIZE) //FLASH图片数组指针开始地址
#define FLASH_START_Sector (OLED_BMP_START/FLASH_Sector_SIZE) //FLASH图片数组指针开始地址对应扇区
#define FLASH_Pointer_MAX (FLASH_Sector_SIZE/(sizeof(bmp_code_typ)-4)) //FLASH图片数组指针最大数量
#define OLED_CODE_Adress ((BMP_u32)(FLASH_START_Sector+1)*FLASH_Sector_SIZE) //FLASH图片数组数据写入首地址
#define OLED_CODE_Sector (FLASH_START_Sector+1) //FLASH图片数组数据写入首地址对应扇区
如果字库已经写好,所要用的图片也已写好且不需要串口打印状态,则可通过上面3个使能宏来节约ROM和RAM,并可以直接把串口及FLASH数据文件从工程移除
I2C OLED 汉字及图片显示方案最新工程:
|
|