【嵌入式】MCU外接Flash图片数据存取实例

一 问题背景

工程中需要使用大量的图片资源用于GUI显示,但是图片资源比较大,不能直接保存在MCU上,所以考虑外接Flash芯片用于图片数据的存储。实际使用中,将Flash芯片内的地址直接映射到芯片内部,读取映射的地址即可加载图片。

 

二 外部Flash连接

我这边选用S25FL256S芯片作为外部Flash,该芯片可以存储256M的数据。将该Flash通过SPI连接到MCU的外部,连接方法如下所示:

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。
        (1)SDO/MOSI – 主设备数据输出,从设备数据输入;
        (2)SDI/MISO – 主设备数据输入,从设备数据输出;
        (3)SCLK – 时钟信号,由主设备产生;
        (4)CS/SS – 从设备使能信号,由主设备控制。当有多个从设备的时候,因为每个从设备上都有一个片选引脚接入到主设备机中,当我们的主设备和某个从设备通信时将需要将从设备对应的片选引脚电平拉低或者是拉高。

 

三 数据存储

(1)将需要存储的图片,直接导入到bmpcvt软件中,可以通过Image---->Scale设置需要的像素大小。调整完毕之后,选择File---->Save As,另存为.c文件格式,保存的格式选择第一个选项(第二个选项压缩格式,可能会存在失真的情况)。

最终生成.c文件如下,其中需要存储的图片资源为_acbrazil[] 数组内容:

#include <stdlib.h>

#include "GUI.h"

#ifndef GUI_CONST_STORAGE
  #define GUI_CONST_STORAGE const
#endif

extern GUI_CONST_STORAGE GUI_BITMAP bmbrazil;

//需要存储的图片资源
static GUI_CONST_STORAGE unsigned long _acbrazil[] = {
  0xFF4AA46F, 0xF84AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 
        0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xEE4AA46F, 0xF94AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0xA64AA46F, 0x344AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 
        0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0x364AA46F, 0xB14AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8D4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 
        0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9B4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36D, 0x004BA97C, 0x004BA97B, 0x004AA36D, 0x004AA46F, 0x004AA46F, 
        0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36D, 0x004AA675, 0x004DB7A3, 0x0051CFE2, 0x0051CEE0, 0x004DB6A0, 0x004AA674, 0x004AA36D, 
        0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA46F, 0x004CB090, 0x0050C8D1, 0x0053D8FA, 0x0053DAFF, 0x0053DAFF, 0x0053D7FA, 0x0050C7CE, 0x004CAF8D, 
        0x004AA46F, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA36D, 0x004BAB81, 0x004FC1BC, 0x0052D5F3, 0x0053DAFF, 0x0052DBFF, 0x0052DAFF, 0x0052DAFF, 0x0052DBFF, 0x0053DAFF, 0x0052D4F1, 
        0x004FC0B9, 0x004BAA7F, 0x004AA36D, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36D, 0x004AA776, 0x004EB9A7, 0x0051D0E6, 0x0053D9FF, 0x0052DBFF, 0x005BCEEA, 0x0075A9A5, 0x00888F76, 0x00879077, 0x0074ABA9, 0x005AD0ED, 0x0052DBFF, 
        0x0053D9FF, 0x0051CFE4, 0x004DB8A4, 0x004AA675, 0x004AA36D, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36E, 0x004AA570, 0x004CB294, 0x0050CAD5, 0x0053D8FC, 0x0053DAFF, 0x0052DAFF, 0x0064BFCF, 0x00997546, 0x00B0550B, 0x00B25003, 0x00B25104, 0x00B0560D, 0x0097794D, 0x0062C4D7, 
        0x0052DAFF, 0x0053DAFF, 0x0053D8FB, 0x0050C9D2, 0x004CB191, 0x004AA470, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA36E, 0x004BAC84, 0x004FC3C1, 0x0052D6F5, 0x0053DAFF, 0x0053D9FE, 0x0052D9FE, 0x005FDAFC, 0x00B8C2B9, 0x00D9B090, 0x00D5AC8C, 0x00CC986E, 0x00BF773E, 0x00B45B14, 0x00B25104, 0x00967B51, 
        0x0059D1F0, 0x0053DAFF, 0x0053D9FE, 0x0053DAFF, 0x0052D5F3, 0x004FC1BE, 0x004BAB82, 0x004AA36D, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA36D, 0x004BA879, 0x004EBBAC, 0x0052D1E9, 0x0053DAFF, 0x0053D9FF, 0x0053D9FE, 0x0053D9FE, 0x0051D9FE, 0x0088DBEF, 0x00E9E3DE, 0x00ECE6E1, 0x00EEECEA, 0x00F1F1F2, 0x00EDE9E6, 0x00DFC6B2, 0x00C58552, 0x00B05B15, 
        0x0070B0B2, 0x0052DBFF, 0x0053D9FE, 0x0053D9FE, 0x0053D9FF, 0x0053D9FF, 0x0052D1E7, 0x004EBAA9, 0x004BA777, 0x004AA36D, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004CB294, 0x0051CCDB, 0x0053D9FD, 0x0053DAFF, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0052DAFF, 0x008CA090, 0x00BD6D2D, 0x00BB6E30, 0x00C07A42, 0x00CC976D, 0x00DEC3AE, 0x00EEEBE8, 0x00EEECEA, 0x00D5A885, 
        0x0085A093, 0x0051DAFF, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053DAFF, 0x0053D8FC, 0x0051CBD9, 0x004CB191, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004CB296, 0x0051CDDE, 0x0053D9FD, 0x0053D9FF, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0052DAFF, 0x00869179, 0x00B25105, 0x00B05309, 0x00B05308, 0x00B05307, 0x00B35A12, 0x00C3804B, 0x00E1CBB9, 0x00F1EEED, 
        0x009BD4DF, 0x0051D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053DAFF, 0x0053D9FD, 0x0051CCDB, 0x004CB192, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA36D, 0x004BA87A, 0x004EBCAF, 0x0052D2EB, 0x0053DAFF, 0x0053D9FF, 0x0053D9FE, 0x0053D9FE, 0x0052DBFF, 0x0074AAA8, 0x00B0560D, 0x00B1550B, 0x00B1550B, 0x00B1550B, 0x00B1550A, 0x00B05307, 0x00B76421, 0x00D7BAA1, 
        0x0085E0F8, 0x0051D9FE, 0x0053D9FE, 0x0053D9FE, 0x0053D9FF, 0x0053DAFF, 0x0052D1E9, 0x004EBBAC, 0x004BA778, 0x004AA36D, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA46E, 0x004BAC86, 0x004FC4C4, 0x0052D6F6, 0x0053DAFF, 0x0053D9FE, 0x0052DAFF, 0x005BCEEB, 0x009A7547, 0x00B35307, 0x00B1550B, 0x00B1550B, 0x00B1550B, 0x00B1550B, 0x00B25105, 0x009A825B, 
        0x005CD6F7, 0x0052D9FF, 0x0053D9FE, 0x0053DAFF, 0x0052D6F5, 0x004FC2C1, 0x004BAC84, 0x004AA36E, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36E, 0x004AA571, 0x004CB396, 0x0051CBD8, 0x0053D8FC, 0x0053DAFF, 0x0052DAFF, 0x0065C0CF, 0x009B7444, 0x00B1550C, 0x00B35307, 0x00B35307, 0x00B0560D, 0x00997749, 0x0063C2D4, 
        0x0052DAFF, 0x0053DAFF, 0x0053D8FC, 0x0050CAD5, 0x004CB294, 0x004AA470, 0x004AA36E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36D, 0x004BA778, 0x004EBAAA, 0x0052D1E8, 0x0053D9FF, 0x0052DAFF, 0x005CCDE8, 0x0077A6A1, 0x00898D71, 0x00898D72, 0x0076A8A4, 0x005BCEEB, 0x0052DBFF, 
        0x0053D9FF, 0x0051D0E6, 0x004EB9A7, 0x004AA776, 0x004AA36D, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA36D, 0x004BAB83, 0x004FC2BF, 0x0052D5F4, 0x0053DBFF, 0x0052DBFF, 0x0052DAFF, 0x0052DAFF, 0x0052DBFF, 0x0053DAFF, 0x0052D5F2, 
        0x004FC1BC, 0x004BAB81, 0x004AA36D, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA470, 0x004CB192, 0x0050C9D3, 0x0053D8FB, 0x0053DAFF, 0x0053DAFF, 0x0053D8FA, 0x0050C8D0, 0x004CB090, 
        0x004AA46F, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA36D, 0x004AA676, 0x004DB8A5, 0x0051CFE4, 0x0051CFE2, 0x004DB7A2, 0x004AA675, 0x004AA36D, 
        0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8E4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA36D, 0x004BAA7E, 0x004BA97D, 0x004AA36D, 0x004AA46F, 0x004AA46F, 
        0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9C4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0x8D4AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46E, 0x004AA46E, 0x004AA46F, 0x004AA46F, 0x004AA46F, 
        0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x004AA46F, 0x9B4AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0xA44AA46F, 0x304AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 
        0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x324AA46F, 0x314AA46F, 0xB04AA46F, 0xFF4AA46F,
  0xFF4AA46F, 0xF64AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 
        0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xEB4AA46F, 0xF74AA46F, 0xFF4AA46F
};

GUI_CONST_STORAGE GUI_BITMAP bmbrazil = {
  34, // xSize
  24, // ySize
  136, // BytesPerLine
  32, // BitsPerPixel
  (unsigned char *)_acbrazil,  // Pointer to picture data
  NULL,  // Pointer to palette
  GUI_DRAW_BMP8888
};

(2)往Flash中写数据之前,先清除一下原本的数据,这里有三个函数可供选择,分别是清除扇区(4kb)、清除块(64kb)、清除整片Flash(256Mb),其中相关操作在芯片说明书中均有提及:

/*********************************************************************************************************
** Function name     : flash_sector_erase
** Descriptions      : Sector erase(4kb)
** Input parameters  : addr -- sector address
** Output parameters : None
** Returned value    : The operation result. 1 -- sucess, 0 -- false
*********************************************************************************************************/
uint8_t flash_sector_erase (uint32_t addr)
{
	flash_write_enable();												    /* Write enable                 */
	
	SPI_FLASH_CS_LOW();				 									    /* P0.2--0,CS = 0 选中SPI Flash */
	ssp_xfer_byte(0x20);
	ssp_xfer_byte((addr & 0x00FF0000) >> 16);
	ssp_xfer_byte((addr & 0x0000FF00) >> 8);
	ssp_xfer_byte(addr & 0x000000FF);
 	SPI_FLASH_CS_HIGH();													    /* P0.2--1,CS = 1 释放SPI Flash */

	while ((flash_read_status() & 0x01) != 0x00);							/* Wait for the flash free      */
    
	return 1;
}

/*********************************************************************************************************
** Function name     : flash_block_erase
** Descriptions      : Block erase(64kb)
** Input parameters  : addr -- block address
** Output parameters : None
** Returned value    : The operation result. 1 -- sucess, 0 -- false
*********************************************************************************************************/
uint8_t flash_block_erase (uint32_t addr)
{
	flash_write_enable();												    /* Write enable                 */
	
	SPI_FLASH_CS_LOW();				 									    /* P0.2--0,CS = 0 选中SPI Flash */
	ssp_xfer_byte(0xD8);
	ssp_xfer_byte((addr & 0xFF0000) >> 16);
	ssp_xfer_byte((addr & 0x00FF00) >> 8);
	ssp_xfer_byte(addr & 0x0000FF);
 	SPI_FLASH_CS_HIGH();													    /* P0.2--1,CS = 1 释放SPI Flash */

	while ((flash_read_status() & 0x01) != 0x00);					        /* Wait for the flash free      */
    
	return 1;
}

/*********************************************************************************************************
** Function name     : flash_all_erase
** Descriptions      : Erase the whole flash(256mb)
** Input parameters  : None
** Output parameters : None
** Returned value    : The operation result. 1 -- sucess, 0 -- false
*********************************************************************************************************/
uint8_t flash_whole_erase( void )
{
	flash_write_enable();												    /* Write enable                 */
	
	SPI_FLASH_CS_LOW();				 									    /* P0.2--0,CS = 0 选中SPI Flash */
 	ssp_xfer_byte(0xC7);
	SPI_FLASH_CS_HIGH();													    /* P0.2--1,CS = 1 释放SPI Flash */

	while ((flash_read_status() & 0x01) != 0x00);	                        /* Wait for the flash free      */
    
	return 1;
}

(3)写扇区的接口如下,其中相关操作在芯片说明书中也有提及:

/*********************************************************************************************************
** Function name     : flash_write_enable
** Descriptions      : Enable the flash memory to write
** Input parameters  : none
** Output parameters : none
** Returned value    : none
*********************************************************************************************************/
static void flash_write_enable (void)
{
	while ((flash_read_status() & 0x01) != 0x00);  /* Wait for flash free          */

	SPI_FLASH_CS_LOW();				 			   /* P0.2--0,CS = 0 选中SPI Flash */

	ssp_xfer_byte(0x06);

	SPI_FLASH_CS_HIGH();						   /* P0.2--1,CS = 1 释放SPI Flash */

	while ((flash_read_status() & 0x03) != 0x02);  /* Wait for operation complete  */
}

/*********************************************************************************************************
** Function name     : flash_write_sector
** Descriptions      : Write flash memory , just in one page memory 
** Input parameters  : WAddr    -- the start address to write
** Output parameters : buf      -- the buffer to write the data
**                     RLength	-- the length of the data to write
** Returned value    : The operation result. 1 -- sucess, 0 -- false
*********************************************************************************************************/
uint8_t flash_write_sector (uint32_t WAddr, uint32_t *buf, uint32_t WLength)
{
	uint32_t i;

	if (WLength == 0)
	{
		return 0;
	}

	flash_write_enable();												    /* Write enable                 */

	SPI_FLASH_CS_LOW();				 									    /* P0.2--0,CS = 0 选中SPI Flash */
	ssp_xfer_byte(0x02);
	ssp_xfer_byte((WAddr & 0x00FF0000) >> 16);
	ssp_xfer_byte((WAddr & 0x0000FF00) >> 8);
	ssp_xfer_byte((WAddr & 0x000000FF));
	for (i = 0; i < WLength; i ++)
	{
        ssp_xfer_byte((buf[i] >> 24) & 0xFF);  //4字节的数组按字节顺序写入flash(注意大小端顺序)
        ssp_xfer_byte((buf[i] >> 16) & 0xFF);
        ssp_xfer_byte((buf[i] >> 8)  & 0xFF);
		ssp_xfer_byte(buf[i] & 0xFF);
	}
	SPI_FLASH_CS_HIGH();													    /* P0.2--1,CS = 1 释放SPI Flash */

	while ((flash_read_status() & 0x01) != 0x00);

	return 1;
}

(4)将图片的数据用上面的接口存入Flash:

// Tx buffer
uint32_t Tx_Buf[64];
static GUI_CONST_STORAGE unsigned long _acbrazil[] = {//图片数据}

void Flash_SSP_Entry(void)
{
    int m;
	int n;
    uint32_t addr = 0x00000;
    uint32_t *src_addr = (uint32_t *)&_acbrazil[0];
    
    flashSSPInit();  //Flash SSP模块初始化
    
    /*flash_whole_erase();  //清除整片flash*/
    flash_block_erase(addr);  //清除64k扇区
    
    for(m = 0;m < 13;m ++)  //上面图片的大小为34*24*4=3264字节,所以这边每次存256字节,存个13次即可
	{
        for (n = 0; n < BUFFER_SIZE; n++) 
        {
            Tx_Buf[n] = *src_addr ++;  //每次存64*4=256字节
        }
        
        flash_write_sector(addr , Tx_Buf, BUFFER_SIZE);

        addr = addr + 0x100;  //指针偏移256字节长度
	}
    
    flashSSPFree();  //Flash SSP模块释放
}

四 数据读取

(1)读扇区的接口如下,其中相关操作在芯片说明书中也有提及:

/**************************************************************************
* 函数名称: flash_read_status
* 功能描述: 从flash内存中读寄存器状态
* 输入参数:
* 输出参数:
* 返 回 值:
* 其它说明:
**************************************************************************/
uint8_t flash_read_status(void)
{
	uint8_t status;

	SPI_FLASH_CS_LOW();				 		/* 选中SPI Flash                */
	ssp_xfer_byte(0x05);					        
	status = ssp_xfer_byte(0xff);				        
	SPI_FLASH_CS_HIGH();	    			/* P0.2--1,CS = 1 释放SPI Flash */
	return status;							/* Return Reg 1's Content		*/
}

/**************************************************************************
* 函数名称: flash_read_data
* 功能描述: 从flash内存中读数据
* 输入参数:
* 输出参数:
* 返 回 值:
* 其它说明:
**************************************************************************/
uint8_t flash_read_data (uint32_t RAddr, uint32_t *buf, uint32_t RLength)
{
	uint8_t tmp;
	uint32_t i;

	if (RLength == 0)
	{
		return 0;
	}

	while(1)
	{
		tmp = flash_read_status( );
		tmp &= 0x01;
		if(tmp == 0x00)
			break;
		for(i=0; i < 10; i++);
	}

	SPI_FLASH_CS_LOW();				 					/* P0.2--0,CS = 0 选中SPI Flash */
	ssp_xfer_byte(0x03);
	ssp_xfer_byte((RAddr & 0x00FF0000) >> 16);
	ssp_xfer_byte((RAddr & 0x0000FF00) >> 8);
	ssp_xfer_byte((RAddr & 0x000000FF));
	for (i=0; i<(RLength/4); i++)
	{

		buf[i] =(ssp_xfer_byte(0xff) << 24) | (ssp_xfer_byte(0xff) << 16) |
                (ssp_xfer_byte(0xff) << 8)  | (ssp_xfer_byte(0xff));
	}
	SPI_FLASH_CS_HIGH();								/* P0.2--1,CS = 1 释放SPI Flash */

	return 1;
}

(2)读扇区内容,并将读到的数据映射到MCU内部地址(起始地址0x28A00000)中:

/**************************************************************************
* 函数名称: flashSSPRead
* 功能描述: 映射外部flash数据
* 输入参数:
* 输出参数:
* 返 回 值:
* 其它说明:
**************************************************************************/
void flashSSPRead(uint32_t WAddr, uint32_t DEF_INE)
{
	uint32_t *ramdata;
	int i;
	int j;
	ramdata = (uint32_t *)DEF_INE;
	for(i = 0;i < 118;i ++)  //循环次数根据实际图片大小定
	{
        for (j = 0; j < BUFFER_SIZE; j++) 
        {
            Rx_Buf[j] = 0;
        }
        
        flash_read_data(WAddr, Rx_Buf, BUFFER_SIZE * 4);  //该接口沿用之前的定义即可
        for(j = 0;j < 64;j ++)
        {
            *ramdata = 0;
            *ramdata = (Rx_Buf[j]) & 0xFFFFFFFF;  //将外部flash收上来的Rx_Buf中的数据转存到ramdata中
            ramdata  = ramdata + 1;
        }

        WAddr = WAddr + 0x100;
	}
}

void Flash_SSP_Entry(void)
{
    int i = 0;
    uint32_t addr = 0x00000;
    
    for(i = 0;i < 1;i ++)  //根据存储用到多少个扇区决定,我这边只存了一个图,所以只取一次即可
    {
        flashSSPRead(addr, 0x28A00000 + addr);  //取0x00000的Flash内部地址的数据映射到MCU内部0x28A00000地址
        addr += 0x10000;  //一个扇区存储0x10000
    }
    
    flashSSPFree();  //Flash SSP模块释放
}

(3)经过上面的步骤,图片数据即存储到了Flash内部地址0x00000处,并映射到了MCU内部地址0x28A00000 处,MCU内部调用此图片,只需要将该图片定义的指针指向该地址即可:

extern GUI_CONST_STORAGE GUI_BITMAP bmbrazil;

GUI_CONST_STORAGE GUI_BITMAP bmbrazil = {
  34, // xSize
  24, // ySize
  136, // BytesPerLine
  32, // BitsPerPixel
  (unsigned char *)0x28A00000,  // Pointer to picture data
  NULL,  // Pointer to palette
  GUI_DRAW_BMP8888
};

void func(void)
{
    //实际调用该图片
    GUI_DrawBitmap(&bmbrazil , 0, 0);
}

 

 

猜你喜欢

转载自blog.csdn.net/sinat_33408502/article/details/109820324