HAL库函数怎么初始化多个USART

STM429HAL库函数,如果使用两个USART或两个SPI,其对应的底层MSP初始化函数怎么定义?怎么解决两个MSP初始化函数重复定义?

在 STM32 HAL 库中,对于不同的外设,每个外设都有对应的初始化函数。对于 USART 和 SPI 这样的外设,如果使用多个相同类型的外设,需要分别调用它们各自的初始化函数。

在初始化函数中,通常会初始化外设的时钟、引脚、模式等参数。如果使用多个相同类型的外设,每个外设的初始化参数可能会不同。因此,需要为每个外设分别定义一个初始化函数,并在初始化时传入相应的参数。

当使用多个相同类型的外设时,可能会出现重复定义的问题。为了解决这个问题,可以使用 static 关键字来限制初始化函数的作用域,使得它只在当前文件中可见。这样,不同的文件可以分别定义各自的初始化函数,不会互相干扰。

例如,假设我们有两个 USART 外设,分别是 USART1 和 USART2。在初始化时,需要分别调用 HAL_UART_Init 函数,并传入相应的参数。为了避免重复定义问题,我们可以在不同的文件中分别定义这两个初始化函数,并使用 static 关键字来限制它们的作用域。例如:

// usart1.c 文件
#include "usart.h"

static void USART1_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  /* USART1 clock enable */
  __HAL_RCC_USART1_CLK_ENABLE();
  
  /* GPIO clock enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  
  /* USART1 GPIO configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  /* USART1 interrupt Init */
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(USART1_IRQn);
}

void USART1_Init(void)
{
  UART_HandleTypeDef huart;
  
  /* USART1 configuration */
  huart.Instance = USART1;
  huart.Init.BaudRate = 115200;
  huart.Init.WordLength = UART_WORDLENGTH_8B;
  huart.Init.StopBits = UART_STOPBITS_1;
  huart.Init.Parity = UART_PARITY_NONE;
  huart.Init.Mode = UART_MODE_TX_RX;
  huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart.Init.OverSampling = UART_OVERSAMPLING_16;
  
  /* USART1 MSP initialization */
  USART1_MspInit(&huart);
  
  /* USART1 initialization */
  HAL_UART_Init(&huart);
}
// usart2.c 文件
#include "usart.h"

static void USART2_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  /* USART2 clock enable */
  __HAL_RCC_USART2_CLK_ENABLE();
  
  /* GPIO clock enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  
  /* USART2 GPIO configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO


该回答引用GPTᴼᴾᴱᴺᴬᴵ
在使用STM32 HAL库函数初始化多个USART或SPI时,每个外设都有对应的底层MSP(MCU Support Package)初始化函数。这些函数负责配置外设的时钟、GPIO、中断等,并在HAL库函数中被调用。

针对您的问题,可以采用以下两种方法解决:

1.定义不同的MSP初始化函数
在HAL库中,每个外设的MSP初始化函数名称都以该外设的名称为前缀,例如USART的MSP初始化函数名称为HAL_UART_MspInit(),而SPI的MSP初始化函数名称为HAL_SPI_MspInit()。因此,可以在代码中为每个外设定义不同的MSP初始化函数,避免重复定义。例如,如果您需要初始化两个USART和两个SPI,可以按照如下方式定义不同的MSP初始化函数:

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART1)
  {
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
  
    /* USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
  else if(huart->Instance==USART2)
  {
    /* USART2 clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();
  
    /* USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
  if(huart->Instance==USART1)
  {
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();
    
    /* USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
  }
  else if(huart->Instance==USART2)
  {
    /* Peripheral clock disable */
    __HAL_RCC_USART2_CLK_DISABLE();
  
    /* USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
  }
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi->Instance==SPI1)
  {
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
  
    /* SPI1 GPIO Configuration    
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI 
    */
    GPIO_InitStruct.Pin = GPIO_PIN


第二种方法是使用外部变量。在每个文件中定义一个变量,例如:

在usart.c文件中定义:

USART_HandleTypeDef huart1;

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
  if(uartHandle->Instance==USART1)
  {
    /* 初始化USART1的底层硬件资源 */
  }
}


在usart2.c文件中定义:

USART_HandleTypeDef huart2;

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
  if(uartHandle->Instance==USART2)
  {
    /* 初始化USART2的底层硬件资源 */
  }
}


在main.c文件中声明这些变量:

extern USART_HandleTypeDef huart1;
extern USART_HandleTypeDef huart2;


这样就可以在主函数中使用USART1和USART2了。

请注意,使用外部变量可能会导致代码结构混乱,因此建议仅在必要时使用。

希望这些方法能够帮助到您。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^