本帖最后由 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下提供的库功能还是非常丰富的,可以极大减少个人代码量,快速进入应用逻辑的开发阶段。如果说有缺点就是需要去学习去适应,理解各个库之间的调用关系。
|