gaoyang9992006 发表于 2025-2-5 11:59

STM32L562E-DK开发板的BSP学习

该工程所在位置   STM32Cube_FW_L5_V1.5.0\Projects\STM32L562E-DK\Examples\BSP\MDK-ARM
打开工程,找到main.c的main函数,查看硬件初始化函数
static void SystemHardwareInit(void)
{
/* Init LEDs*/
if (LedInitialized != SET)
{
    if (BSP_LED_Init(LED9) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }
    if (BSP_LED_Init(LED10) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }
    LedInitialized = SET;
}

/* Init User push-button in EXTI Mode */
if (ButtonInitialized != SET)
{
    if (BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }
    ButtonInitialized = SET;
}

/* Initialize the LCD */
if (LcdInitialized != SET)
{
    LCD_UTILS_Drv_t lcdDrv;

    /* Initialize the LCD */
    if (BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }

    /* Set UTIL_LCD functions */
    lcdDrv.DrawBitmap= BSP_LCD_DrawBitmap;
    lcdDrv.FillRGBRect = BSP_LCD_FillRGBRect;
    lcdDrv.DrawHLine   = BSP_LCD_DrawHLine;
    lcdDrv.DrawVLine   = BSP_LCD_DrawVLine;
    lcdDrv.FillRect    = BSP_LCD_FillRect;
    lcdDrv.GetPixel    = BSP_LCD_ReadPixel;
    lcdDrv.SetPixel    = BSP_LCD_WritePixel;
    lcdDrv.GetXSize    = BSP_LCD_GetXSize;
    lcdDrv.GetYSize    = BSP_LCD_GetYSize;
    lcdDrv.SetLayer    = BSP_LCD_SetActiveLayer;
    lcdDrv.GetFormat   = BSP_LCD_GetFormat;
    UTIL_LCD_SetFuncDriver(&lcdDrv);

    /* Clear the LCD */
    UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);

    /* Set the display on */
    if (BSP_LCD_DisplayOn(0) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }

    LcdInitialized = SET;
}

/* Initialize the TouchScreen */
if (TsInitialized != SET)
{
    TS_Init_t TsInit;

    /* Initialize the TouchScreen */
    TsInit.Width       = 240;
    TsInit.Height      = 240;
    TsInit.Orientation = TS_ORIENTATION_PORTRAIT;
    TsInit.Accuracy    = 10;
    if (BSP_TS_Init(0, &TsInit) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }

    /* Configure TS interrupt */
    if (BSP_TS_EnableIT(0) != BSP_ERROR_NONE)
    {
      Error_Handler();
    }

    TsInitialized = SET;
}
}该函数对LED 、按钮、LCD屏幕、触摸屏进行初始化,并由初始化完成标志位变量进行置位。
LED的初始化函数如下
int32_t BSP_LED_Init(Led_TypeDef Led)
{
int32_t          status = BSP_ERROR_NONE;
GPIO_InitTypeDef GPIO_Init;

/* Enable the GPIO_LED Clock */
if (Led == LED9)
{
    LED9_GPIO_CLK_ENABLE();
}
else /* Led = LED10 */
{
    /* Enable VddIO2 for GPIOG */
    __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWREx_EnableVddIO2();
    LED10_GPIO_CLK_ENABLE();
}

/* configure the GPIO_LED pin */
GPIO_Init.Pin   = LED_PIN;
GPIO_Init.Mode= GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull= GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(LED_PORT, &GPIO_Init);

HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);

return status;
}该函数对IO所在的时钟进行了启用,并对IO进行配置,配置为输出高电平。
按钮的配置,如下
int32_t BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode)
{
int32_t               status = BSP_ERROR_NONE;
GPIO_InitTypeDef      GPIO_Init;
uint32_t            BSP_BUTTON_IT_PRIO = {BSP_BUTTON_USER_IT_PRIORITY};
uint32_t            BUTTON_EXTI_LINE   = {BUTTON_USER_EXTI_LINE};
BSP_EXTI_LineCallback ButtonCallback   = {BUTTON_USER_EXTI_Callback};

/* Enable the BUTTON clock */
BUTTON_USER_GPIO_CLK_ENABLE();

GPIO_Init.Pin   = BUTTON_PIN;
GPIO_Init.Pull= GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;

if (ButtonMode == BUTTON_MODE_GPIO)
{
    /* Configure Button pin as input */
    GPIO_Init.Mode = GPIO_MODE_INPUT;
    HAL_GPIO_Init(BUTTON_PORT, &GPIO_Init);
}

if (ButtonMode == BUTTON_MODE_EXTI)
{
    /* Configure Button pin as input with External interrupt */
    GPIO_Init.Mode = GPIO_MODE_IT_RISING;
    HAL_GPIO_Init(BUTTON_PORT, &GPIO_Init);

    if (HAL_EXTI_GetHandle(&hpb_exti, BUTTON_EXTI_LINE) == HAL_OK)
    {
      if (HAL_EXTI_RegisterCallback(&hpb_exti, HAL_EXTI_RISING_CB_ID, ButtonCallback) == HAL_OK)
      {
      /* Enable and set Button EXTI Interrupt to the lowest priority */
      HAL_NVIC_SetPriority(BUTTON_IRQn, BSP_BUTTON_IT_PRIO, 0x00);
      HAL_NVIC_EnableIRQ(BUTTON_IRQn);
      }
      else
      {
      status = BSP_ERROR_PERIPH_FAILURE;
      }
    }
    else
    {
      status = BSP_ERROR_PERIPH_FAILURE;
    }
}

return status;
}可配置为IO模式和中断模式
<div>static void BUTTON_USER_EXTI_Callback(void)</div><div>{</div><div>BSP_PB_Callback(BUTTON_USER);</div><div>}</div><div>
</div><div><div>__weak void BSP_PB_Callback(Button_TypeDef Button)</div><div>{</div><div>/* Prevent unused argument(s) compilation warning */</div><div>UNUSED(Button);</div><div>
</div><div>/* This function should be implemented by the user application.</div><div>   It is called into this driver when an event on Button is triggered. */</div><div>}</div></div>
层层嵌套,不知道这么做目的是不是为了可移植性。

LCD的硬件接口初始化采用如下函数
int32_t BSP_LCD_Init(uint32_t Instance, uint32_t Orientation)
{
int32_t status = BSP_ERROR_NONE;

if ((Instance >= LCD_INSTANCES_NBR) || (Orientation > LCD_ORIENTATION_LANDSCAPE_ROT180))
{
    status = BSP_ERROR_WRONG_PARAM;
}
else
{
    /* Power up LCD */
    ST7789H2_PowerUp();

    /* Probe the LCD driver */
    if (ST7789H2_Probe(Orientation) != BSP_ERROR_NONE)
    {
      status = BSP_ERROR_COMPONENT_FAILURE;
    }
}

return status;
} 根据函数定义到定义引脚的宏,知道了供电控制引脚、复位引脚、背光引脚,
#define LCD_POWER_GPIO_PORT               GPIOH
#define LCD_POWER_GPIO_PIN                GPIO_PIN_0
#define LCD_POWER_GPIO_CLOCK_ENABLE()   __HAL_RCC_GPIOH_CLK_ENABLE()
#define LCD_RESET_GPIO_PORT               GPIOF
#define LCD_RESET_GPIO_PIN                GPIO_PIN_14
#define LCD_RESET_GPIO_CLOCK_ENABLE()   __HAL_RCC_GPIOF_CLK_ENABLE()
#define LCD_BACKLIGHT_GPIO_PORT         GPIOE
#define LCD_BACKLIGHT_GPIO_PIN            GPIO_PIN_1
#define LCD_BACKLIGHT_GPIO_CLOCK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()上电函数就是对LCD供电、复位、以及打开背光
static void ST7789H2_PowerUp(void)
{
GPIO_InitTypeDef GPIO_InitStruct;

/* Initialize and configure the ST7789H2 power pin */
LCD_POWER_GPIO_CLOCK_ENABLE();
GPIO_InitStruct.Mode= GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull= GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pin   = LCD_POWER_GPIO_PIN;
HAL_GPIO_Init(LCD_POWER_GPIO_PORT, &GPIO_InitStruct);

/* Power on the ST7789H2 */
HAL_GPIO_WritePin(LCD_POWER_GPIO_PORT, LCD_POWER_GPIO_PIN, GPIO_PIN_RESET);

/* Initialize and configure the ST7789H2 reset pin */
LCD_RESET_GPIO_CLOCK_ENABLE();
GPIO_InitStruct.Mode= GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull= GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pin   = LCD_RESET_GPIO_PIN;
HAL_GPIO_Init(LCD_RESET_GPIO_PORT, &GPIO_InitStruct);

/* Reset the ST7789H2 */
HAL_GPIO_WritePin(LCD_RESET_GPIO_PORT, LCD_RESET_GPIO_PIN, GPIO_PIN_RESET);
HAL_Delay(1); /* wait at least 10us according ST7789H2 datasheet */
HAL_GPIO_WritePin(LCD_RESET_GPIO_PORT, LCD_RESET_GPIO_PIN, GPIO_PIN_SET);
HAL_Delay(120); /* wait maximum 120ms according ST7789H2 datasheet */

/* Initialize GPIO for backlight control and enable backlight */
LCD_BACKLIGHT_GPIO_CLOCK_ENABLE();
GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull      = GPIO_NOPULL;
GPIO_InitStruct.Speed   = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pin       = LCD_BACKLIGHT_GPIO_PIN;
HAL_GPIO_Init(LCD_BACKLIGHT_GPIO_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(LCD_BACKLIGHT_GPIO_PORT, LCD_BACKLIGHT_GPIO_PIN, GPIO_PIN_SET);
}该LCD采用了并口发送数据
/** @defgroup STM32L562E-DK_LCD_Private_Functions STM32L562E-DK LCD Private Functions
* @{
*/
/**
* @briefProbe the ST7789H2 LCD driver.
* @paramOrientation LCD_ORIENTATION_PORTRAIT, LCD_ORIENTATION_LANDSCAPE,
*                     LCD_ORIENTATION_PORTRAIT_ROT180 or LCD_ORIENTATION_LANDSCAPE_ROT180.
* @retval BSP status.
*/
static int32_t ST7789H2_Probe(uint32_t Orientation)
{
int32_t                  status;
ST7789H2_IO_t            IOCtx;
uint32_t               st7789h2_id;
static ST7789H2_Object_t ST7789H2Obj;
uint32_t               lcd_orientation;

/* Configure the LCD driver */
IOCtx.Address   = LCD_FMC_ADDRESS;
IOCtx.Init      = LCD_FMC_Init;
IOCtx.DeInit      = LCD_FMC_DeInit;
IOCtx.ReadReg   = LCD_FMC_ReadReg16;
IOCtx.WriteReg    = LCD_FMC_WriteReg16;
IOCtx.SendData    = LCD_FMC_Send;
IOCtx.GetTick   = LCD_FMC_GetTick;

if (ST7789H2_RegisterBusIO(&ST7789H2Obj, &IOCtx) != ST7789H2_OK)
{
    status = BSP_ERROR_BUS_FAILURE;
}
else if (ST7789H2_ReadID(&ST7789H2Obj, &st7789h2_id) != ST7789H2_OK)
{
    status = BSP_ERROR_COMPONENT_FAILURE;
}
else if (st7789h2_id != ST7789H2_ID)
{
    status = BSP_ERROR_UNKNOWN_COMPONENT;
}
else
{
    Lcd_CompObj = &ST7789H2Obj;
    Lcd_Drv = (LCD_Drv_t *) &ST7789H2_Driver;
    if (Orientation == LCD_ORIENTATION_PORTRAIT)
    {
      lcd_orientation = ST7789H2_ORIENTATION_PORTRAIT;
    }
    else if (Orientation == LCD_ORIENTATION_LANDSCAPE)
    {
      lcd_orientation = ST7789H2_ORIENTATION_LANDSCAPE;
    }
    else if (Orientation == LCD_ORIENTATION_PORTRAIT_ROT180)
    {
      lcd_orientation = ST7789H2_ORIENTATION_PORTRAIT_ROT180;
    }
    else
    {
      lcd_orientation = ST7789H2_ORIENTATION_LANDSCAPE_ROT180;
    }
    if (Lcd_Drv->Init(Lcd_CompObj, ST7789H2_FORMAT_RBG565, lcd_orientation) < 0)
    {
      status = BSP_ERROR_COMPONENT_FAILURE;
    }
    else
    {
      status = BSP_ERROR_NONE;
    }
}

return status;
}采用FMC地址给屏幕发送数据
#define LCD_REGISTER_ADDR FMC_BANK1_1
#define LCD_DATA_ADDR   (FMC_BANK1_1 | 0x00000002UL)

#define LCD_FMC_ADDRESS   1Ustatic void Display_DemoDescription(void)
{
char desc;

/* Set font */
UTIL_LCD_SetFont(&Font20);

/* Clear the LCD */
UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);

/* Set the LCD Text Color */
UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_DARKBLUE);
UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_WHITE);

/* Display LCD messages */
UTIL_LCD_DisplayStringAt(0, 10, (uint8_t *)"STM32L562E-DK BSP", CENTER_MODE);
UTIL_LCD_DisplayStringAt(0, 35, (uint8_t *)"drivers example", CENTER_MODE);

/* Draw Bitmap */
UTIL_LCD_DrawBitmap(80, 65, (uint8_t *)st**);

UTIL_LCD_SetFont(&Font8);
UTIL_LCD_DisplayStringAt(0, 220, (uint8_t *)"Copyright (c) STMicroelectronics 2019", CENTER_MODE);

UTIL_LCD_SetFont(&Font12);
UTIL_LCD_FillRect(0, 145, 240, 50, UTIL_LCD_COLOR_BLUE);
UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_WHITE);
UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_BLUE);
UTIL_LCD_DisplayStringAt(0, 150, (uint8_t *)"Press User push-button", CENTER_MODE);
UTIL_LCD_DisplayStringAt(0, 165, (uint8_t *)"to start :", CENTER_MODE);
sprintf(desc,"%s example", BSP_examples.DemoName);
UTIL_LCD_DisplayStringAt(0, 180, (uint8_t *)desc, CENTER_MODE);
}


编译工程烧录




效果不错,这个工程里出现了函数指针结构体,比较难的一个知识点。
typedef int32_t (*ST7789H2_Write_Func)(void *, uint16_t, uint8_t *, uint32_t);
typedef int32_t (*ST7789H2_Read_Func)(void *, uint16_t, uint8_t *, uint32_t);
typedef int32_t (*ST7789H2_Send_Func)(void *, uint8_t *, uint32_t);

typedef struct
{
ST7789H2_Write_Func   WriteReg;
ST7789H2_Read_Func    ReadReg;
ST7789H2_Send_Func    SendData;
void                  *handle;
} ST7789H2_ctx_t;


页: [1]
查看完整版本: STM32L562E-DK开发板的BSP学习