这次我将STemWin给集成了进来,在这个例程中使用了多行文本控件,做了一个终端可显示从SD卡将BMP格式的图片资源拷贝到QSPI FLASH文件系统的过程,图片数据如下,事先已经将其拷贝到SD卡的根目录中:
做这个功能的主要目的是为了后面做一些基于小熊派的开源项目就可以彻底的不需要SD卡来做图片存放,而是直接利用板子上的QSPI FLASH作为图片存储,这个例程充当着一个数据迁移的角色。
1、软件功能简介
1.1、插入SD卡上电
当插入SD卡开机时,程序会自动的将SD卡根目录下的.bmp文件依次拷贝到QSPI FLASH的文件系统上,这里就会调用UI拷贝函数,拷贝的过程会通过LCD以多行文本的形式显示出来。
1.2、不插入SD卡上电
当检测到没有SD卡的时候,程序会调用文件索引函数,将QSPI FLASH文件系统下的BMP图片通过LCD依次显示出来。
先来直观的感受一下:
刷屏现象还是有的,资源有限,没办法。
2、主要函数功能实现
软件上根据野火电子开发板提供的文件系统例程进行了一下简单的改造,其中也加入了GUI的逻辑,以适配STemWin在LCD上的显示效果,主要为以下几个函数:
- 索引盘符根目录下的.bmp格式的文件
FRESULT scan_files (char* src_path)
{
FRESULT res;
DIR dir;
UINT i;
static FILINFO fno;
char UI_Path[100] = {0};
res = f_opendir(&dir, src_path); /* Open the directory */
if (res == FR_OK)
{
for (;;)
{
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
if (fno.fattrib & AM_DIR) /* It is a directory */
{
i = strlen(src_path);
sprintf(&src_path[i], "/%s", fno.fname);
res = scan_files(src_path); /* Enter the directory */
if (res != FR_OK) break;
src_path[i] = 0;
}
else
{
memset(UI_Path, 0, 100);
sprintf(UI_Path, "%s/%sn", src_path, fno.fname);
if(strstr(fno.fname, ".bmp") != 0)
{
LCD_Clear(BLACK);
Lcd_show_bmp(0,0,UI_Path);
HAL_Delay(500);
}
}
}
f_closedir(&dir);
}
return res;
}
- 复制文件
/**
* @brief 复制文件
* @param src_path:源文件路径
* @param dst_path:文件将要复制到的目录(不含文件名)
* @retval result:文件系统的返回值
*/
int copy_file(char *src_path, char *dst_path)
{
FRESULT res = FR_OK;
char *sub_dir = NULL;
char buf[100] = {0};
res = f_open(&SDFile, src_path, FA_READ);
if(res != FR_OK)
{
printf("打开文件失败!n");
return -1 ;
}
//获取子文件路径
sub_dir = strrchr(src_path, '/');
if(NULL == sub_dir)
{
printf("获取子文件路径失败!n");
return -2 ;
}
//拼接成新路径
sprintf(newfn, "%s%s", dst_path, sub_dir);
//printf("正在复制文件 %s ...", newfn);
sprintf(buf,"copy 0:->%s successn",newfn);
MULTIEDIT_AddText(hItem,buf);
res = f_open(&USERFile, newfn, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
if(res != FR_OK)
{
printf("打开文件失败!n");
return -3 ;
}
//拷贝文件
while(res == FR_OK)
{
res = f_read(&SDFile, &read_buf, COPY_UNIT, &real_read_num);
if(res != FR_OK)
{
printf("读取文件失败!n");
return -4 ;
}
res = f_write(&USERFile, &read_buf, real_read_num, &real_write_num);
if(res != FR_OK)
{
printf("写文件失败!n");
return -5 ;
}
if(real_read_num != COPY_UNIT)
break;
GUI_Delay(1);
}
f_close(&SDFile);
f_close(&USERFile);
return res;
}
- 从SD卡根目录拷贝.bmp文件到QSPI FLASH fatfs文件系统的根目录
/*从SD卡拷贝UI文件到QSPI FLASH*/
FRESULT copy_ui_files (char* src_path)
{
FRESULT res;
DIR dir;
UINT i;
static FILINFO fno;
char UI_Path[100] = {0};
res = f_opendir(&dir, src_path); /* Open the directory */
if (res == FR_OK)
{
for (;;)
{
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
if (fno.fattrib & AM_DIR) /* It is a directory */
{
i = strlen(src_path);
sprintf(&src_path[i], "/%s", fno.fname);
res = scan_files(src_path); /* Enter the directory */
if (res != FR_OK) break;
src_path[i] = 0;
}
else
{
memset(UI_Path, 0, 100);
sprintf(UI_Path, "%s/%s", src_path, fno.fname);
if(strstr(fno.fname, ".bmp") != 0)
copy_file(UI_Path, "1:");
}
GUI_Delay(1);
}
f_closedir(&dir);
}
return res;
}
利用STemWin的GUIBuilder生成基本界面及功能函数,并对其进行简单改造,在这里主要使用了框架窗口,然后在其之上绘制了多文本控件:
代码语言:javascript复制static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
{
{ FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 240, 240, 0, 0x64, 0 },
{ MULTIEDIT_CreateIndirect, "Multiedit", ID_MULTIEDIT_0, 0, 0, 230, 220, 0, 0x0, 0 },
// USER START (Optionally insert additional widgets)
// USER END
};
在回调函数_cbDialog
中添加如下代码:
/*********************************************************************
*
* _cbDialog
*/
static void _cbDialog(WM_MESSAGE * pMsg)
{
int NCode;
int Id;
uint8_t ret ;
// USER END
switch (pMsg->MsgId)
{
case WM_INIT_DIALOG:
hItem = pMsg->hWin;
FRAMEWIN_SetText(hItem, "BearPi Copy Ui Console");
hItem = WM_GetDialogItem(pMsg->hWin, ID_MULTIEDIT_0);
MULTIEDIT_SetBkColor(hItem, MULTIEDIT_CI_EDIT, GUI_BLACK);
MULTIEDIT_SetTextColor(hItem, MULTIEDIT_CI_EDIT, GUI_MAKE_COLOR(0x0000FF00));
printf("开始拷贝文件:n");
ret = copy_ui_files(src_dir);
if(ret != FR_OK)
{
MULTIEDIT_AddText(hItem, "Open SD card Fail!n");
MULTIEDIT_AddText(hItem, "Copy 0:==>1: Failn");
MULTIEDIT_AddText(hItem, "View QSPI_FLASH UI Resource:n");
GUI_Delay(1000);
LCD_Clear(BLACK);
HAL_Delay(500);
scan_files(dst_dir);
LCD_Clear(BLACK);
HAL_Delay(500);
MULTIEDIT_AddText(hItem, "View Success!n");
}
else
{
MULTIEDIT_AddText(hItem, "Open SD card Successn");
MULTIEDIT_AddText(hItem, "Copy 0:==>1: Successn");
GUI_Delay(100);
}
break;
default:
WM_DefaultProc(pMsg);
break;
}
}
当在主程序调用以下函数时,则会自动运行以上程序。
代码语言:javascript复制WM_HWIN CreateFramewin(void)
{
WM_HWIN hWin;
hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
return hWin;
}
获取完整demo:
码云仓库:https://gitee.com/morixinguan/bear-pi/tree/master/22.SD_Card_Copy_to_QSPI_Flash
获取方法:
代码语言:javascript复制git clone https://gitee.com/morixinguan/bear-pi.git
即可获取本次实验工程全部代码。
我的码云项目开源主页:https://gitee.com/morixinguan