STemWin 从外部存储器获取并绘制流位图 Streamed Bitmap [3]

前言

  1. 本博文基于emWin V5.50和MDK环境下编写和调试;
  2. 本博客内容介绍STM32利用STemWIn库从搭载了文件系统(FATFS V13c)的SD卡上获取到一个位图流,并显示在LCD的指定位置上的小实验;看本博文需要有一些GUI的基础和位图基础;
  3. 如有不足,还请多多指教;

获取流程

对于一个大的GUI项目来说,如果所有的图标数据都保存在单片机内部ROM中,所占用的内存空间是非常大的,尤其是像单片机这种小容量CPU,内存尤为珍贵。如果把这些图标都保存在外部函数中,虽说在一定程度上增加了响应时间,但是很省内存,在一定程度上降低了成本。为此emWin专门提供了功能函数可以将位于外部存储设备上的流位图文件显示在LCD上,其数据转移流程如下:
在这里插入图片描述
在我的这个实验中这并不是一个简单的从存储器读取数据显示在LCD上,他要经过几个结构层,如下图:
在这里插入图片描述
所以这个实验需要:

  1. 硬件:SD卡,LCD显示器;
  2. 软件:FATFS,SD卡驱动,STemWin,LCD底层驱动(描点函数);

但是 本实验并不介绍上面这些驱动和移植过程,而是着重介绍STemWin提供的相应绘图函数GUI_DrawStreamedBitmapExAuto()

外部存储器流位图获取函数

int GUI_DrawStreamedBitmapExAuto(GUI_GET_DATA_FUNC * pfGetData, const void * p, int x, int y);

描述: 自动识别从外部获取到的不同格式的位图流数据,从而将其显示在以(x,y)为起点的LCD屏幕上;
参数:
pfGetData:外部数据获取函数。GUI_DrawStreamedBitmapExAuto()本身并不能从外部存储器获取位图数据,而是通过一个用户自定义的GetData函数将要显示的位图数据从外部存储器读出来,指针就指向这个GetData函数;GUI_DrawStreamedBitmapExAuto()会多次调用这个函数;
p:用户自定义指针。这个指针很重要,从外部存储器获取数据的方式有很多种。比如不需要FATFS的是直接访问,那么这里的P所指向的变量或结构体,用来将需要读取数据的起始地址,读取数据的大小等这些重要信息传递给pfGetData所指向的函数;同理,外部存储器如果搭载了FATFS,那么这里可以传递文件类型结构体变量,从而获取相应数据;
x,y:这两个参数很好理解,就是LCD屏幕点座标;
返回值: 0 on success, 1 on error.

注意:这里有一个问题,在数据获取的过程中是要占用单片机的RAM的,如果一个位图的大小大于了单片机本身的RAM大小,这很棘手。所以GUI_DrawStreamedBitmapExAuto()提供了分批获取数据的方法。但是每一批获取的数据量必须大于或等于LCD屏幕上一行数据的像素点数据所占用的内存空间; 这一点需要怎么自己设定;

指定位图格式的获取函数: 功能上和Auto没有太大区别,如下
在这里插入图片描述

数据获取函数GetData (两种)

在官方手册的204页,给出了获取函数的要求:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面这是我自己编写的带FATFS的SD卡数据获取函数:
第一种: 分两批获取数据函数

int APP_GetData_Stream(void * p,const U8 ** ppData,unsigned NumBytesReq,U32 offset )
{
	FRESULT res_SD = FR_OK;
	FIL * phFile = (FIL *)p;
	U8  * pData  = (U8 *)*ppData;
	DWORD NumBytesRead;
	
	//将数据读入缓冲区(至少一行像素点数据大小的缓冲区)

	res_SD = f_mount(&FATFS_DEV_SDHC,"1:",1);
	if(res_SD == FR_OK)
	{
		//1.打开文件;
		res_SD = f_open(phFile,"1:AliPay.dta",FA_READ|FA_OPEN_EXISTING);
			if( res_SD == FR_OK )
			{
				printf( "文件打开成功!\r\n");
				
				//2.根据偏移量设置文件读写指针位置
				f_lseek(phFile,offset);
				
				//3.获取文件头信息/单行字节数据;
				
				res_SD = f_read(phFile,pData,NumBytesReq,&NumBytesRead);
					if((res_SD == FR_OK) && (NumBytesReq == NumBytesRead))
					{
						printf("数据获取成功!\r\n");
					}
					else
						printf("数据获取失败!错误代码:%d\r\n",res_SD);	

			}
			else
				printf("文件打开失败!错误代码:%d\r\n",res_SD);
					
		f_close(phFile);

	}
	else
		printf("文件系统挂载失败!错误代码:%d\r\n",res_SD);

	f_mount(NULL,"1:",0);	
	return NumBytesRead;
}

效果图:
在这里插入图片描述

第二种: 多批获取数据函数 (这个函数的功能我并没有实现,测试了很多遍,以后再修补把,这里先把代码写下来)

int APP_GetData(void * p,const U8 ** ppData,unsigned NumBytes,U32 offset )
{
FRESULT res_SD = FR_OK;
static U8 acBuffer[480];
FIL * phFile = NULL;
DWORD NumBytesRead;
phFile = (FIL *)p;

if( NumBytes > sizeof(acBuffer) ) NumBytes = sizeof( acBuffer );

res_SD = f_mount(&FATFS_DEV_SDHC,"1:",1);
if(res_SD == FR_OK)
{
	//1.打开文件;
	res_SD = f_open(phFile,"1:AliPay.dta",FA_READ|FA_OPEN_EXISTING);
		if( res_SD == FR_OK )
		{
			printf( "文件打开成功!\r\n");
			
			//2.根据偏移量设置文件读写指针位置
			f_lseek(phFile,offset);
			
			//3.获取文件头信息/单行字节数据;
			
			res_SD = f_read(phFile,acBuffer,NumBytes,&NumBytesRead);
				if((res_SD == FR_OK) && (NumBytes == NumBytesRead))
					*ppData = acBuffer; //返回缓存区的起始地址;
				else
					printf("数据获取失败!错误代码:%d\r\n",res_SD);	

		}
		else
			printf("文件打开失败!错误代码:%d\r\n",res_SD);
				
	f_close(phFile);

}
else
	printf("文件系统挂载失败!错误代码:%d\r\n",res_SD);

f_mount(NULL,"1:",0);	
return NumBytesRead;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章