STM32F072從零配置工程-基於HAL庫的串列埠UART中斷配置
阿新 • • 發佈:2019-07-19
先上一個採用串列埠直接傳輸的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); }
&n