本帖最后由 sujingliang 于 2025-5-10 11:18 编辑
通常在ST开发板中处理与屏幕相关的功能,需要用到LTDC和DMA2D,其中涉及硬件功能的开启和引脚的定义,如果不是官方开发板还需要初始化LCD,为了方便绘图还需要自己写一些绘制图形的函数。
这些工作占用很多的时间,费时费力。而且对于不同开发板还要重复进行这些工作。
那么如何快速地跳过以上工作,直接进入绘图创意阶段呢。ST给了解决方案就是BSP LCD+Utilities LCD通用绘图库。
BSP LCD库负责与开发板硬件驱动,并提供基本的绘图接口函数。
Utilities LCD通用绘图库建立在BSP LCD提供的基本接口函数之上,并扩展了一些与硬件无关的绘图函数可以在各个开发板通用。
下面用例子开启绘图实践
一、准备
首先准备一个空的工程,可以点灯程序或者用STM32CubeMX配置一个最简单工程。
需要了解的:
| 路径 | 主要文件 | BSP LCD | C:\Users\用户名\STM32Cube\Repository\STM32Cube_FW_N6_V1.1.1\Drivers\BSP\STM32N6570-DK | stm32n6570_discovery_lcd.c
stm32n6570_discovery_lcd.h | Utilities LCD | C:\Users\用户名\STM32Cube\Repository\STM32Cube_FW_N6_V1.1.1\Utilities\lcd | stm32_lcd.c
stm32_lcd.h |
在工程中添加BSP和Utilities LCD的源文件
将上述路径加到Include Paths里。
另外把C:\Users\用户名\STM32Cube\Repository\STM32Cube_FW_N6_V1.1.1\Drivers\BSP\Components\Common也加到Include Paths里,因为用到其中lcd.h
在stm32n6xx_hal_conf.h中开启
- #define HAL_DMA2D_MODULE_ENABLED
- #define HAL_LTDC_MODULE_ENABLED
- #define HAL_RIF_MODULE_ENABLED
将上面这些库函数加入工程。
RIF(Resource Isolation Framework,资源隔离框架) 主要作用是为硬件主设备(Master)和从设备(Slave)设置安全(Secure)和特权(Privileged)属性,确保系统在 多核/多域环境(如ARM TrustZone)下的安全隔离和权限控制。
由于建立工程是选择了安全域应用,需要配置RIF,防止非安全域(Non-Secure)非法访问安全域(Secure)资源。
二、RIF初始化
main函数中:
- /* Update the RIF config for the used peripherals */
- RIMC_MasterConfig_t RIMC_master = {0};
- RIMC_master.MasterCID = RIF_CID_1;
- RIMC_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;
- HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_DCMIPP, &RIMC_master);
- HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_DMA2D, &RIMC_master);
- HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_LTDC1 , &RIMC_master);
- HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_LTDC2 , &RIMC_master);
- HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_VENC , &RIMC_master);
- HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_DMA2D , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
- HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_DCMIPP , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
- HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_CSI , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
- HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDC , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
- HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDCL1 , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
- HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDCL2 , RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
上面多配置了一些外设,实际用到的是DMA2D、LTDC。
三、LCD配置
继续在main函数中增加:
- /* Init LCD */
- BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
功能
简单地说这个BSP函数完成了所有LCD的硬件和软件驱动,包括LCD驱动、硬件配置、LTDC、DMA2D等等,这些使用者不用考虑:
可以和MX_LTDC_Init(void);MX_DMA2D_Init(void);void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef* hdma2d);void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc)甚至中断回调说再见了。
再增加一句:
- UTIL_LCD_SetFuncDriver(&LCD_Driver);
完成了 Utilities LCD到 BSP LCD的绑定,可以用 Utilities LCD进行绘图操作了。
在stm32n6xx_hal_conf.h中有如下说明:
- 1. How To use this driver:
- --------------------------
- - This driver is a generic driver that provides basic display services. It should
- be used by any platform once LCD is initialized and following draw methods are
- registered:
- BSP_LCD_DrawBitmap
- BSP_LCD_DrawHLine
- BSP_LCD_DrawVLine
- BSP_LCD_FillRect
- BSP_LCD_ReadPixel
- BSP_LCD_WritePixel
- BSP_LCD_GetXSize
- BSP_LCD_GetYSize
- BSP_LCD_SetActiveLayer
- - At application level, once the LCD is initialized, user should call UTIL_LCD_SetFuncDriver()
- API to link board LCD drivers to BASIC GUI LCD drivers.
- User can then call the BASIC GUI services:
- UTIL_LCD_SetFuncDriver()
- UTIL_LCD_SetLayer()
- UTIL_LCD_SetDevice()
- UTIL_LCD_SetTextColor()
- UTIL_LCD_GetTextColor()
- UTIL_LCD_SetBackColor()
- UTIL_LCD_GetBackColor()
- UTIL_LCD_SetFont()
- UTIL_LCD_GetFont()
- UTIL_LCD_Clear)
- UTIL_LCD_ClearStringLine()
- UTIL_LCD_DisplayStringAtLine()
- UTIL_LCD_DisplayStringAt()
- UTIL_LCD_DisplayChar()
- UTIL_LCD_GetPixel()
- UTIL_LCD_SetPixel()
- UTIL_LCD_FillRGBRect()
- UTIL_LCD_DrawHLine()
- UTIL_LCD_DrawVLine()
- UTIL_LCD_DrawBitmap()
- UTIL_LCD_FillRect()
- UTIL_LCD_DrawLine()
- UTIL_LCD_DrawRect()
- UTIL_LCD_DrawCircle()
- UTIL_LCD_DrawPolygon()
- UTIL_LCD_DrawEllipse()
- UTIL_LCD_FillCircle()
- UTIL_LCD_FillPolygon()
- UTIL_LCD_FillEllipse()
就是在绑定过程中BSP需提供一些基本的函数注册到UTIL,然后就可以使用UTIL开头的绘图函数。
四、一个简单的例子
上面通过2个函数完成了LCD配置,下面开始画图
- UTIL_LCD_SetFont(&Font16);
- UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_WHITE);
- UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_BLUE);
- UTIL_LCD_Clear(UTIL_LCD_COLOR_BLUE);
-
- UTIL_LCD_DisplayStringAtLine(0, (uint8_t *)"Hello STM32!");
-
- UTIL_LCD_DrawRect(10, 50, 100, 50, UTIL_LCD_COLOR_RED);
- UTIL_LCD_FillCircle(150, 75, 25, UTIL_LCD_COLOR_GREEN);
设置字体、前景色、背景色、清屏、显示字符串,画矩形,画圆
五、一个动图的例子
- void Run_Circle_Animation(void)
- {
- int32_t x, y;
- float angle = 0.0f;
- float angle_step = 2 * 3.14159f / ANIMATION_STEPS;
-
- // 轨道参数(椭圆)
- uint16_t orbit_x_radius = LCD_WIDTH/2 - CIRCLE_RADIUS - 10;
- uint16_t orbit_y_radius = LCD_HEIGHT/2 - CIRCLE_RADIUS - 10;
-
- while(1)
- {
- // 计算圆形位置
- x = LCD_WIDTH/2 + (int32_t)(orbit_x_radius * cosf(angle));
- y = LCD_HEIGHT/2 + (int32_t)(orbit_y_radius * sinf(angle));
-
- // 清除上一帧
- UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_BLACK);
- UTIL_LCD_FillCircle(x, y, CIRCLE_RADIUS,UTIL_LCD_COLOR_BLUE);
-
- // 更新角度
- angle += angle_step;
- if(angle >= 2*3.14159f) angle = 0;
-
- // 计算新位置
- x = LCD_WIDTH/2 + (int32_t)(orbit_x_radius * cosf(angle));
- y = LCD_HEIGHT/2 + (int32_t)(orbit_y_radius * sinf(angle));
-
- // 绘制新圆形
- UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_RED);
- UTIL_LCD_FillCircle(x, y, CIRCLE_RADIUS,UTIL_LCD_COLOR_RED);
-
- // 绘制轨道(椭圆)
- UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_BLUE);
- UTIL_LCD_DrawEllipse(LCD_WIDTH/2, LCD_HEIGHT/2, orbit_x_radius, orbit_y_radius,UTIL_LCD_COLOR_WHITE);
-
- HAL_Delay(DELAY_MS);
- }
- }
六、LCD打印日志
lcd_trace库函数位于:C:\Users\用户\STM32Cube\Repository\STM32Cube_FW_N6_V1.1.1\Utilities\lcd_trace
可以提供在LCD上打印日志的功能
在工程中添加lcd_trace的源文件,添加Include Paths
配置使用微库use MicroLIB
加入如下代码:
- UTIL_LCD_TRACE_Init();
-
- UTIL_LCD_TRACE_SetHeader((uint8_t*)"Trace header");
-
- UTIL_LCD_TRACE_SetFooter((uint8_t*)"this is footer");
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- LCD_UsrTrace("Hello World!\n");
- LCD_DbgTrace("Hello World! LCD_DbgTrace\n");
- LCD_ErrTrace("System Clock: %d MHz\n", SystemCoreClock/1000000);
- HAL_Delay(1000);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
七、总结
BSP和Utility下提供的库功能还是非常丰富的,可以极大减少个人代码量,快速进入应用逻辑的开发阶段。如果说有缺点就是需要去学习去适应,理解各个库之间的调用关系。
|