你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32CubeIDE GuiLite图形库移植经验分享

[复制链接]
攻城狮Melo 发布时间:2023-4-6 16:38
一、GuiLite       
        GuiLite图形库,仅4千行C++代码,0依赖,单一头文件库(GuiLite.h)的跨平台开源GUI库,支持支持的操作系统有iOS/macOS/WatchOS,Android,Linux(ARM/x86-64),Windows(包含VR),RTOS等,甚至无操作系统的单片机上也能流畅运行。

二、创建工程

        实现了LCD屏幕点亮功能。

        【2】现在CubeIDE工作空间创建一个名为stm32L496VGTx_GUI的文件目录,并将前面工程的stm32L496VGTx_lcm.ioc文件拷贝到该目录下,修改该文件名为stm32L496VGTx_GUI.ioc。

        在CubeIDE中,在菜单栏的“新建-> Create a New STM32 Project from an Existing STM32CubeMX Configuration files(.ioc)”,进入创建,基于已有ioc创建一个新工程,如下图所示,特别注意,选择C++支持,因为GuiLite库是C++库。

77b7c5fa691448e28c500c6f201140a5.png

        【3】完成工程创建后,禁用syscalls.c文件,在工程目录下创建源目录ICore,并移植前面工程的源文件,实现lpuart1串口驱动、按键及LED灯驱动、LCD屏幕驱动,如下图所示;由于前面博文中实现LCD的DMA刷新数据时,使用了SPI回调及全局变量,需要到Core/Src/spi.c文件增加如下内容:
  1. volatile uint8_t one_frame_done;
  2. void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
  3. {
  4.         one_frame_done = 1;
  5. }
复制代码

1605f3e1bd77401e93684107453c004c.png


三、GuiLite库及Hello3D样例移植
        在ICore目录下创建guilite文件夹,将GuiLite库即GuiLite.h文件拷贝到该文件目录,将Hello3D样例的UIcode.cpp源文件拷贝到该文件目录。

        【1】由于GuiLite.h内的thread_sleep函数调用了延时函数,而样例给出的延时函数过于复杂,本文另外设置了新的延时函数,在ICore目录下新建delay目录,并在该目录下创建了delay.h和delay.c源码。

        delay.h
  1. #ifndef DELAY_DELAY_H_
  2. #define DELAY_DELAY_H_
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif

  6. #include "stm32l4xx_hal.h" //HAL库文件声明
  7. void delay_us(uint32_t us); //C文件中的函数声明

  8. #ifdef __cplusplus
  9. }
  10. #endif
  11. #endif /* DELAY_DELAY_H_ */
复制代码


        delay.c

  1. #include "delay.h"

  2. void delay_us(uint32_t us) //利用CPU循环实现的非精准应用的微秒延时函数
  3. {
  4.     uint32_t delay = (HAL_RCC_GetHCLKFreq() / 8000000 * us); //使用HAL_RCC_GetHCLKFreq()函数获取主频值,经算法得到1微秒的循环次数
  5.     while (delay--); //循环delay次,达到1微秒延时
  6. }
复制代码

        由于现在采用的是C++编译语言,因此可以看到 delay.h文件中,和以前不一样的是,增加了extern "C"声明,为了严禁,移植过来的print.h、usart.h、key.h、led.h、oled.h本文都增加了extern "C"声明。
  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif

  4. //you code

  5. #ifdef __cplusplus
  6. }
复制代码

        【2】调整文件GuiLite.h,首先,同样的在文件前面增加了delay.h头文件的引用,以及为了统一,将其宏定义#pragma once进行了替换,结果如下
  1. #ifndef GUILITE_H_
  2. #define GUILITE_H_
  3. #include "../delay/delay.h"
复制代码

        在GuiLite.h文件中找到thread_sleep函数,该函数有几处,需要条件编译的地方暂时不用管找到STM32需要的,如下。
  1. extern "C" void delay_ms(unsigned short nms);
  2. void thread_sleep(unsigned int milli_seconds)
  3. {//MCU alway implemnet driver code in APP.
  4.                 delay_ms(milli_seconds);
  5. }
复制代码

        调整为
  1. //extern "C" void delay_ms(unsigned short nms);
  2. void thread_sleep(unsigned int milli_seconds)
  3. {//MCU alway implemnet driver code in APP.
  4.         uint32_t tt = ((uint32_t)milli_seconds)*1000;
  5.         delay_us(tt);
  6. }
复制代码

        【3】在main.c文件,引用各外设驱动头文件
  1. /* USER CODE BEGIN Includes */
  2. #include "../../ICore/key/key.h"
  3. #include "../../ICore/led/led.h"
  4. #include "../../ICore/print/print.h"
  5. #include "../../ICore/usart/usart.h"
  6. #include "../../ICore/oled/oled.h"
  7. /* USER CODE END Includes */
复制代码

        在main.c文件中参考Hello3D样例的main.c源文件(Hello3D/BuildSTM32F103-Keil/USER/main.c · idea4good/GuiLiteSamples - Gitee.com)进行声明GuiLite库调用前置声明如下,主要就是需要改写调用本文LCD屏幕支持依据坐标值及颜色值,进行点绘制功能函数。
  1. /* USER CODE BEGIN 0 */
  2. //Transfer GuiLite 32 bits color to your LCD color
  3. #define GL_RGB_32_to_16(rgb) (((((unsigned int)(rgb)) & 0xFF) >> 3) | ((((unsigned int)(rgb)) & 0xFC00) >> 5) | ((((unsigned int)(rgb)) & 0xF80000) >> 8))
  4. //Encapsulate your LCD driver:
  5. void gfx_draw_pixel(int x, int y, unsigned int rgb)
  6. {
  7.     //LCD_Fast_DrawPoint(x, y, GL_RGB_32_to_16(rgb));//注释参考样例的
  8.         OLED_WritePixel(x, y, GL_RGB_32_to_16(rgb));//新增本工程支持绘制点函数调用(oled.h)
  9. }
  10. //Implement it, if you have more fast solution than drawing pixels one by one.
  11. //void gfx_fill_rect(int x0, int y0, int x1, int y1, unsigned int rgb){}

  12. //UI entry
  13. struct DISPLAY_DRIVER
  14. {
  15.         void (*draw_pixel)(int x, int y, unsigned int rgb);
  16.         void (*fill_rect)(int x0, int y0, int x1, int y1, unsigned int rgb);
  17. } my_driver;
  18. extern void startHello3D(void* phy_fb, int width, int height, int color_bytes, struct DISPLAY_DRIVER* driver);
  19. /* USER CODE END 0 */
复制代码


        在Hello3D样例的main主函数中,先初始化延时函数、在配置中断和LCD屏幕初始化,然后进行3D效果绘制渲染输出。

  1. delay_init();
  2.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  3.         LCD_Init();

  4.         //Link your LCD driver & start UI:
  5.         my_driver.draw_pixel = gfx_draw_pixel;
  6.         my_driver.fill_rect = NULL;//gfx_fill_rect;
  7.         startHello3D(NULL, 240, 320, 2, &my_driver);
  8.         while(1);
复制代码

        在本博文移植中,在main函数内进行外设初始设置,例如lpuart1中断接收开启、lcd初始化,主要是LCD初始化。
  1.   /* USER CODE BEGIN 2 */
  2.   ResetPrintInit(&hlpuart1);
  3.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
  4.   HLPUSART_RX_STA = 0;
  5.   //
  6.   OLED_init();
  7.   //设置OLED蓝色背景显示
  8.   BSP_LCD_Clear_DMA(LCD_DISP_BLUE);
  9.   printf("OLED_Clear_DMA\r\n");
  10.   /* USER CODE END 2 */
复制代码

        然后在main函数主循环中,通过按键KEY2按键进入3D效果绘制渲染输出,读者可以屏蔽串口接收功能、按键KEY0、KEY1的亮屏功能,直接进入KEY2下的3D效果绘制渲染功能是OK的。注意startHello3D调用需要根据自身屏幕宽、高设值,本文开发板支持240*240像素显示。
  1.   /* USER CODE BEGIN WHILE */
  2.   while (1)
  3.   {
  4.           if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始
  5.                   //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
  6.                   OLED_printf(10,10,"%.*s",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
  7.                   HLPUSART_RX_STA=0;//接收错误,重新开始
  8.                   HAL_Delay(100);//等待
  9.           }
  10.           if(KEY_0())
  11.           {
  12.                   BSP_LCD_login(24,108);
  13.           }
  14.           if(KEY_1())
  15.             {
  16.                   BSP_LCD_img_DMA();
  17.             }
  18.           if(KEY_2())
  19.             {
  20.                   my_driver.draw_pixel = gfx_draw_pixel;
  21.                   my_driver.fill_rect = NULL;//gfx_fill_rect;
  22.                   startHello3D(NULL, 240, 240, 2, &my_driver);
  23.             }
  24.     /* USER CODE END WHILE */
复制代码

四、编译及测试
        完成代码移植及改写后,进行运行配置设置,点击编辑及运行按钮,将程序下载到开发板上。

2f01fdf679234e349c31a2a72f836efa.png

         按键KEY2进入GuiLite库的3D绘制效果,按键KEY2按下时,屏幕会较慢地进行背景色(黑色)逐点绘制,因此较慢。最终处理的是一个3D立方体缓慢旋转刷新显示的动态画面,效果如下图(手指是拍摄时屏幕镜面映射效果,哈哈)。

722f590bf3e54cb2bc457cca2ee1d67e.png

366b7d4b58f54925bde9496b94657fa6.png
————————————————
版权声明:py_free-物联智能
如有侵权请联系删除
收藏 评论4 发布时间:2023-4-6 16:38

举报

4个回答
shenxiaolin_mai 回答时间:2023-8-10 10:14:10
不知道c++库可以用在keil上么?还是非常开心的。
shenxiaolin_mai 回答时间:2023-8-10 10:14:39
感谢分享,更详细一点就好了
lospring 回答时间:2023-8-10 10:15:03

内容很详细,谢谢分享

STMWoodData 回答时间:2023-8-10 10:21:30

这个GUI效果真不错,有空可以尝试移植一下看看。

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版