打印
[STM32N6]

【STM32N6570-DK测评】6、BSP+Utilities下LCD相关库函数使用

[复制链接]
42|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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-DKstm32n6570_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);
功能
  • 初始化LCD硬件,包括配置控制器(如LTDC)、背光、像素格式等。
  • 底层操作

  • 硬件初始化

    • 配置GPIO(数据线、控制信号线)。
    • 初始化显示控制器(如STM32的LTDC或FSMC接口)。
    • 设置像素格式(如RGB565、ARGB8888)。

  • 背光控制

    • 启用背光电源(如PWM调光)。

  • 显存分配

    • 为帧缓冲区(Framebuffer)分配内存(内部SRAM或外部SDRAM)




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


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

119

帖子

0

粉丝