STM32F072從零配置工程-基於HAL庫的串口UART中斷配置


先上一個采用串口直接傳輸的Demo;

此處的思路是完全采用HAL庫來實現的,核心是運用HAL_UART_Transmit_IT和HAL_UART_Receive_IT兩個函數來實現的,可以作為一個Demo來測試使用;

直接上代碼,其串口的配置和上一章完全一致,因此忽略不計:

       思路大致是將aTxStartMessage字符串發送出去,接收一個總長度為15個字符的數據到aRxBuffer中,等待接收完畢;

       將接收到的aRxBuffer發送出去,等待發送完成,最后將aTxEndMessage發送出去;

uint8_t aTxStartMessage[] = "\r\n ****UART-Hyperterminal communication based on IT ****\r\n Enter 9 characters using keyboard :\r\n";
uint8_t aTxEndMessage[] = "\r\n Example Finished\r\n";

/* Buffer used for reception */
uint8_t aRxBuffer[18];
  
  while (1)
  {
    if(HAL_UART_Transmit_IT(&huart2, (uint8_t*)aTxStartMessage, sizeof(aTxStartMessage)) != HAL_OK)
    {
        while(1);
    }
    if(HAL_UART_Receive_IT(&huart2, (uint8_t*)aRxBuffer, 15) != HAL_OK)
    {
        while(1);
    }
    while(HAL_UART_GetState(&huart2) != HAL_UART_STATE_READY);
    if(HAL_UART_Transmit_IT(&huart2, (uint8_t*)aRxBuffer, 15) != HAL_OK)
    {
        while(1);
    }
    while(HAL_UART_GetState(&huart2) != HAL_UART_STATE_READY);
    if(HAL_UART_Transmit_IT(&huart2, (uint8_t*)aTxEndMessage, sizeof(aTxEndMessage)) != HAL_OK)
    {
        while(1);
    }
    while(HAL_UART_GetState(&huart2) != HAL_UART_STATE_READY);
  }

 

 

接下來是也是一個Demo,采用HAL庫來實現串口收發中斷,思路和C一個一個接收字符然后發送出去是相似的,只不過是采用串口IT中斷來實現;

  串口的配置不變,因此在此忽略不計;

uint8_t aRxBuffer;

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  
  HAL_UART_Receive_IT(&huart3, &aRxBuffer, 1);
  
  while (1)
  {}
}

void USART2_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart2);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandler)
{
    HAL_UART_Transmit(&huart3, &aRxBuffer, 1, 0);
    HAL_UART_Receive_IT(&huart3, &aRxBuffer, 1);
}

 

 

簡要分析以下這個程序的思路:

       開頭采用HAL_UART_Receive_IT()這個函數和目的不是為了接收數據,而是通過里面的配置開啟中斷,核心在SET_BIT()這兩句話中(開啟EIE、PEIE和RXNEIE這三個中斷);

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if(huart->RxState == HAL_UART_STATE_READY)
  {
    if((pData == NULL ) || (Size == 0U))
    {
      return HAL_ERROR;
    }
    /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter 
       should be aligned on a u16 frontier, as data to be received from RDR will be 
       handled through a u16 cast. */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      if((((uint32_t)pData)&1U) != 0U)
      {
        return  HAL_ERROR;
      }
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    huart->RxXferCount = Size;

    /* Computation of UART mask to apply to RDR register */
    UART_MASK_COMPUTATION(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
    /* Enable the UART Parity Error and Data Register not empty Interrupts */
    SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

 

 

接收數據的過程可以從中斷中了解:

       當接收到數據后判斷ISR寄存器中RXNE中斷標志是否置位和CR1寄存器中RXNE中斷使能是否開啟,然后進入到接收處理函數UART_Receive_IT()中;

       在UART_Receive_IT()中,關閉EIE、PEIE和RXNE中斷,同時調用回調函數HAL_UART_RxCpltCallback();

void USART2_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart2);
}

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{

  /* If some errors occur */
  cr3its = READ_REG(huart->Instance->CR3);
  if(   (errorflags != RESET)
     && (   ((cr3its & USART_CR3_EIE) != RESET)
         || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)) )
  {
    
    /* Call UART Error Call back function if need be --------------------------*/
    if(huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
      /* UART in mode Receiver ---------------------------------------------------*/
      if(((isrflags & USART_ISR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
      {
        UART_Receive_IT(huart);
      }
    }
    return;
  } /* End if some error occurs */
}

HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  /* Check that a Rx process is ongoing */
  if(huart->RxState == HAL_UART_STATE_BUSY_RX)
  {
    if(--huart->RxXferCount == 0U)
    {
      /* Disable the UART Parity Error Interrupt and RXNE interrupt*/
      CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));

      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;

      HAL_UART_RxCpltCallback(huart);

      return HAL_OK;
    }
  }
}

 

 

在主函數中執行重寫的回調函數:

       將接收到的一個字符發送出去,同時開啟接收中斷准備接收下一個字符;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandler)
{
    HAL_UART_Transmit(&huart3, &aRxBuffer, 1, 0);
    HAL_UART_Receive_IT(&huart3, &aRxBuffer, 1);
}

 

 

其實現的功能可以和以下C語言實現的相似:

int c;
while((c = getchar()) != EOF)
{
    putchar(c);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM