【第3版emWin教程】第17章 emWin6.x的2D图形库之绘制流位图(QSPI Flash内存映射方案)

教程不断更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

第17章       emWin6.x的2D图形库之绘制流位图(QSPI Flash内存映射方案)

学习本章节前务必先掌握上个章节位图的使用,流位图相比位图的好处就是可以将其存储到任何可以存储数据的外部介质中,比如SD卡,  QSPI Flash和SPI Flash等,有没有文件系统均可,而位图需要存储到内部Flash,而且比较占用空间。

目录

17.1 初学者重要提示

17.2 下载算法存放位置(操作前必看)

17.3 如何生成流位图

17.3.1   转换JPEG格式的图片为流位图

17.3.2   转换PNG格式的图片为流位图

17.3.3   转换ICO格式的图片为流位图

17.4 内部Flash和QSPI Flash程序调试下载配置(重要必看)

17.4.1        将流位图文件转换为C数组格式文件

17.4.2        设置流位图文件到外部QSPI Flash。

17.4.3 下载配置

17.4.4 调试配置

17.5 流位图的显示方法(QSPI Flash内存映射方式)

17.6 实验例程说明(RTOS)

17.7 实验例程说明(裸机)

17.8 总结


17.1 初学者重要提示

1、  对于需要大量图标以及背景图片的场合,使用流位图是最佳选择,优势有两点:

  •   与位图不同,流位图可以存储到任何外部存储器,这样就可以存储很多图标和背景图片。
  •   与BMP,JPEG,PNG,GIF格式的图片不同,流位图已经是原始的图片数据,不需要进行解码就可以立即进行显示,显示速度最快。

2、  STM32H7花式玩转QSPI Flash相关章节都已经发布:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=101064

这里强烈推荐看:第83章 STM32H7 的内部 Flash 和 QSPI Flash都运行程序的混合方式(强烈推荐)。

3、  下载本章节相关例子前,务必先添加好QSPI Flash的下载算法。本章使用的方法支持内部Flash和外部QSPI Flash可以同时下载,同时仿真。 如此以来,大家可以方便的将流位图存到外部QSPI Flash,简单易用,大大方便大家项目实战。

4、  2D绘图的所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数的位置

下图是英文版手册里面API函数的位置:

 

5、  流位图绘制非常的实用,望初学者务必掌握。

17.2 下载算法存放位置(操作前必看)

(注:例子下载地址 http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

编译例子:V7-060_QSPI Flash的MDK下载算法制作,生成的算法文件位于此路径下:

生成算法文件后,需要大家将其存到到MDK安装目录,有两个位置可以存放,任选其一,推荐第2种:

  •   第1种:存放到MDK的STM32H7软包安装目录里面:\Keil\STM32H7xx_DFP\2.6.0\CMSIS\Flash(软包版本不同,数值2.6.0不同)。
  •   第2种:MDK的安装目录 \ARM\Flash里面。

17.3 如何生成流位图

本小节配套的两个图片已经放在了本章教程配套例子的Doc文件夹里面。从各类图标网站下载的图标主要是PNG,JPEG,ICO格式的。这里重点把三种格式做个说明。

首先下载小软件BmpCvt小软件,小软件BmpCvt版本支持BMP,GIF,PNG和JPEG图片格式的转换:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=107218

17.3.1   转换JPEG格式的图片为流位图

  •   第1步:打开BmpCvt.exe ,直接将JPEG格式的图片拖到此软件里面即可,或者点击File->Open进行加载也是可以的。

  •   第2步:点击File->Save as,弹出如下窗口

上面截图中共分了4步进行操作,其中第2步修改名字是因为原有的名字太长了,不方便程序代码的调用。

  •   第3步:第2步操作完毕后,弹出如下窗口:

点击OK按钮后会在桌面出现一个新文件,即pic.dta,这个就是流位图文件:

17.3.2   转换PNG格式的图片为流位图

  •   第1步:打开BmpCvt.exe ,直接将刚刚转换出的的PNG格式图片拖到此软件里面即可,或者点击File->Open进行加载也是可以的。

  •   第2步:点击File->Save as,弹出如下窗口

上面截图中共分了4步进行操作,其中第2步修改名字是因为原有的名字太长了,不方便程序代码的调用。

  •   第3步:第2步操作完毕后,弹出如下窗口

点击OK按钮后会在桌面出现一个新文件,即pic1.dta文件,这个就是流位图文件:

17.3.3   转换ICO格式的图片为流位图

软件BmpCvt.exe 不支持ICO格式的图片,这里我们需要使用软件GIMP将其修改为PNG格式。

GIMP软件下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=100389

  •   第1步:直接拖动ICO图标到GIMP:

  •   第2步:选择导出为:

  •   第3步:选择PNG

默认,直接导出

至此,图片就从ICO格式转换成了带透明层的PNG格式图片。

  •   第4步:打开BmpCvt.exe ,直接将刚刚转换出的的PNG格式图片拖到此软件里面即可,或者点击File->Open进行加载也是可以的。

点击File->Save as,弹出如下窗口

上面截图中共分了4步进行操作,其中第2步修改名字是因为原有的名字太长了,不方便程序代码的调用。

操作完毕后,弹出如下窗口:

点击OK按钮后会在桌面出现一个新文件,即pic1.dta文件,这个就是流位图文件:

17.4 内部Flash和QSPI Flash程序调试下载配置(重要必看)

将下面两个地方配置后,就可以像使用内部Flash一样使用QSPI Flash进行调试了。并且这种方式可以方便的调试程序,内部Flash和外部Flash都做调试。

17.4.1        将流位图文件转换为C数组格式文件

为了方便将bin文件添加到MDK工程中,我们这里使用小软件B2C.exe将其转换为C格式文件(此软件已经放到本章配套例子V7-511_emWin6.x实验_2D图形库之流位图绘制(QSPI Flash RTOS) 的Doc文件里面)。

转换后生成的文件为pic.c :

__align(4) const unsigned char _acpic[8208UL + 1] = {
  0x42, 0x4D, 0x08, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 
  省略未写

}

为了防止访问出错,生成的C文件前面加上了4字节对齐__align(4)。

17.4.2        设置流位图文件到外部QSPI Flash。

下面将流位图文件下载到QSPI Flash,需要大家先在这里添加QSPI Flash地址范围:

然后设置资源文件到外部QSPI Flash:鼠标右击文件分组GUI/Pic,选择Options。

17.4.3 下载配置

注意这里一定要够大,否则会提示算法文件无法加载:

我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。推荐使用AXI SRAM(地址0x24000000),因为这块RAM空间足够大。

如果要下载程序到内部Flash和外部QSPI Flash里面,需要做如下配置,两个下载算法都要添加进来:

17.4.4 调试配置

注意这里一定要够大,否则会提示算法文件无法加载:

我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。

如果要做调试下载,需要做如下配置:

17.5 流位图的显示方法(QSPI Flash内存映射方式)

emWin提供的流位图显示函数非常多,初学容易犯迷糊。仔细看一下这些函数,会发现这些函数主要分为两大类,一类是以Ex结尾的函数,这种函数显示流位图是边从外部存储器加载数据边显示,显示速度相对较慢,另一类是不以Ex结尾的函数,这种函数直接从指定的地址读取数据进行显示(注意,这里的地址需是总线式地址,比如外部SDRAM,外部SRAM,内部Flash和内部SRAM都可以),显示速度相对较快。

本章教程,我们主要讲解不以Ex结尾的函数,这类函数主要分为以下三种类型:

  •   GUI_DrawStreamedBitmapAuto()

此函数可以直接显示BmpCvtST.exe转换出来的XXXX.dta流位图文件,支持任意颜色格式的位图显示。

  •   GUI_CreateBitmapFromStream()

此函数的作用是将流位图转换成位图,支持任意格式的流位图转换,然后用户再调用位图函数GUI_DrawBitmap()进行显示。

  •   GUI_CreateBitmapFromStreamXXXXX()

这种类型的函数是转换特定类型的流位图为位图,相比函数GUI_CreateBitmapFromStream的好处就是消耗的内存空间较小。这种类型的函数比较多,主要有以下20多种:

下面我们通过实例来说明这种三种流位图函数的使用方法:

  •   第1步:将17.3.1小节生成的流位图文件pic.dta和17.3.2小节生成的pic1.dta文件都转换为C格式文件后,添加工程中,并按本章17.4章节设置即可。
  •   第2步:初始化QSPI Flash,并设置内存映射模式:

bsp_InitQSPI_W25Q256();  /* 配置QSPI Flash */

QSPI_MemoryMapped();     /* 内存映射模式 */ 

  •   第3步:显示加载到emWin动态内存的流位图。

分别采用如下三种方法显示流位图:

方法1:直接调用函数 GUI_DrawStreamedBitmapAuto(_acBuffer, 0, 0)进行显示

方法2:GUI_CreateBitmapFromStream(&Bitmap, &Palette, _acBuffer);

GUI_DrawBitmap(&Bitmap, 0, 0);

方法3:GUI_CreateBitmapFromStream565(&Bitmap, &Palette, _acBuffer);

GUI_DrawBitmap(&Bitmap, 0, 0);

结合第1步,完整的代码如下:

/*
*********************************************************************************************************
*                                   变量
*********************************************************************************************************
*/
/* 用于选择使用的显示方法:Method1,Method2和Method3 */
#define Method1

#if !defined Method1
    GUI_BITMAP Bitmap;
    GUI_LOGPALETTE Palette;
#endif

/*
*********************************************************************************************************
*    函 数 名: _ShowStreamBitmap
*    功能说明: 显示流位图
*    形    参: sFilename  要读取的文件名
*                     x  要显示的x轴坐标位置
*                     y  要显示的y轴坐标位置
*    返 回 值: 无
*********************************************************************************************************
*/
static void _ShowStreamBitmap(const unsigned char *_acBuffer, int x, int y) 
{
    
    /* 显示方法一 */
#if defined Method1
    GUI_DrawStreamedBitmapAuto(_acBuffer, x, y);
    
    /* 显示方法二 */
#elif defined Method2    
    GUI_CreateBitmapFromStream(&Bitmap, &Palette, _acBuffer);
     GUI_DrawBitmap(&Bitmap, x, y);
    
    /* 显示方法三 仅支持RGB565格式的图片显示 */
#elif defined Method3    
    GUI_CreateBitmapFromStream565(&Bitmap, &Palette, _acBuffer);
     GUI_DrawBitmap(&Bitmap, x, y);
#endif

}

用户要显示流位图,调用函数_ShowStreamBitmap即可显示,应用实例和显示效果看本章教程配套的例子。

17.6 实验例程说明(RTOS)

配套例子:

V7-511_emWin6.x实验_2D图形库之流位图绘制(QSPI Flash RTOS)

实验目的:

  1. 学习emWin6.x的流位图显示。
  2. emWin功能的实现在MainTask.c文件里面。

实验内容:

1、K1按键按下,串口或者RTT打印任务执行情况(串口波特率115200,数据位8,奇偶校验位无,停止位1)。

2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。

     (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。

3、默认上电是通过串口打印信息,如果使用RTT打印信息:

MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可

#define Enable_RTTViewer  1

4、各个任务实现的功能如下:

App Task Start   任务 :启动任务,这里用作BSP驱动包处理。

App Task MspPro任务 :消息处理,这里用作LED闪烁。

App Task UserIF  任务 :按键消息处理。

App Task COM   任务 :暂未使用。

App Task GUI    任务 :GUI任务。

μCOS-III任务调试信息(按K1按键,串口打印):

RTT 打印信息方式:

程序设计:

  任务栈大小分配:

μCOS-III任务栈大小在app_cfg.h文件中配置:

#define  APP_CFG_TASK_START_STK_SIZE                      512u

#define  APP_CFG_TASK_MsgPro_STK_SIZE                     2048u

#define  APP_CFG_TASK_COM_STK_SIZE                        512u

#define  APP_CFG_TASK_USER_IF_STK_SIZE                    512u

#define  APP_CFG_TASK_GUI_STK_SIZE                        2048u

任务栈大小的单位是4字节,那么每个任务的栈大小如下:

App Task Start   任务 :2048字节。

App Task MspPro任务 :8192字节。

App Task UserIF  任务 :2048字节。

App Task COM   任务 :2048字节。

App Task GUI    任务 :8192字节。

  系统栈大小分配:

μCOS-III的系统栈大小在os_cfg_app.h文件中配置:

#define  OS_CFG_ISR_STK_SIZE                      512u     

系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB

emWin动态内存配置:

GUIConf.c文件中的配置如下:

#define EX_SRAM   1/*1 used extern sram, 0 used internal sram */

#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*24)
#else
#define GUI_NUMBYTES  (100*1024)
#endif

通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

#define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

#define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

emWin界面显示效果:

800*480分辨率界面效果。

 

17.7 实验例程说明(裸机)

配套例子:

V7-510_emWin6.x实验_2D图形库之流位图绘制(QSPI Flash裸机 )

实验目的:

  1. 学习emWin6.x的流位图显示。
  2. emWin功能的实现在MainTask.c文件里面。

emWin界面显示效果:

800*480分辨率界面效果。

emWin动态内存配置:

GUIConf.c文件中的配置如下:

#define EX_SRAM   1/*1 used extern sram, 0 used internal sram */

#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*24)
#else
#define GUI_NUMBYTES  (100*1024)
#endif

通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

#define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

#define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

17.8 总结

本章节主要为大家简单讲解这么多,流位图是非常实用的,望初学者务必多练习并熟练掌握。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里提供一个基于emWin图形库的实时曲线波形demo,其中x轴刻度为时间,y轴刻度为数据。 首先,需要在开发板上安装emWin图形库,并且连接好显示器。接下来,我们需要编写一个C程序来实现实时曲线波形的绘制。 以下是示例代码: ```c #include "GUI.h" #include "DIALOG.h" #define MAX_POINTS 100 // 最大数据点数 #define X_SIZE 240 // x轴长度 #define Y_SIZE 320 // y轴长度 #define X_OFFSET 40 // x轴偏移量 #define Y_OFFSET 40 // y轴偏移量 #define X_TICKS 5 // x轴刻度数 #define Y_TICKS 5 // y轴刻度数 // 数据点结构体 typedef struct { int x; int y; } POINT; // 数据点数组 static POINT _aPoint[MAX_POINTS]; // 数据点数 static int _NumPoints = 0; // 绘制实时曲线波形 static void _DrawGraph(void) { int i; GUI_SetColor(GUI_RED); GUI_DrawLine(X_OFFSET, Y_SIZE - Y_OFFSET, X_SIZE - X_OFFSET, Y_SIZE - Y_OFFSET); GUI_DrawLine(X_OFFSET, Y_SIZE - Y_OFFSET, X_OFFSET, Y_OFFSET); for (i = 0; i <= X_TICKS; i++) { GUI_DrawLine(X_OFFSET + i * (X_SIZE - 2 * X_OFFSET) / X_TICKS, Y_SIZE - Y_OFFSET, X_OFFSET + i * (X_SIZE - 2 * X_OFFSET) / X_TICKS, Y_SIZE - Y_OFFSET + 4); } for (i = 0; i <= Y_TICKS; i++) { GUI_DrawLine(X_OFFSET - 4, Y_SIZE - Y_OFFSET - i * (Y_SIZE - 2 * Y_OFFSET) / Y_TICKS, X_OFFSET, Y_SIZE - Y_OFFSET - i * (Y_SIZE - 2 * Y_OFFSET) / Y_TICKS); } GUI_SetColor(GUI_GREEN); for (i = 0; i < _NumPoints - 1; i++) { GUI_DrawLine(_aPoint[i].x, _aPoint[i].y, _aPoint[i + 1].x, _aPoint[i + 1].y); } } // 添加新的数据点 static void _AddPoint(int x, int y) { if (_NumPoints >= MAX_POINTS) { memmove(&_aPoint[0], &_aPoint[1], (MAX_POINTS - 1) * sizeof(POINT)); _NumPoints--; } _aPoint[_NumPoints].x = x; _aPoint[_NumPoints].y = y; _NumPoints++; } // 主函数 void MainTask(void) { int i = 0; GUI_Init(); while (1) { // 模拟生成新的数据 int y = rand() % (Y_SIZE - 2 * Y_OFFSET) + Y_OFFSET; _AddPoint(X_OFFSET + i * (X_SIZE - 2 * X_OFFSET) / X_TICKS, Y_SIZE - y); i++; if (i > X_TICKS) { i = 0; _NumPoints = 0; } // 绘制实时曲线波形 GUI_Clear(); _DrawGraph(); GUI_Delay(100); } } ``` 上述代码中,我们定义了一个数据点结构体`POINT`,并且定义了一个数据点数组`_aPoint`,最大数据点数为100。`_NumPoints`变量表示当前数据点数。 `_DrawGraph`函数用于绘制实时曲线波形,其中通过GUI_DrawLine函数绘制出x轴和y轴,以及刻度线。`_AddPoint`函数用于添加新的数据点,并且如果数据点数超过最大值,则将最早的数据点删除。 在主函数中,我们模拟生成新的数据点,并且调用`_AddPoint`函数添加新的数据点。如果数据点数超过x轴刻度数,则将最早的数据点删除。最后,调用`_DrawGraph`函数绘制实时曲线波形。 通过上述代码,我们可以实现一个基于emWin图形库的实时曲线波形demo,其中x轴刻度为时间,y轴刻度为数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值