STM32マイコンでUARTの受信をする際に必須となるエラー処理について紹介します。
UARTの送信は一方的にマイコンから送るだけのため、そこまで大変ではありません。一方、受信は調歩同期方式ならではのエラー(フレーミング、バッファ オーバーラン エラー等)が発生するため、エラー処理を入れないとUARTの受信処理の安定性が悪化します。
更に厄介なのがSTM32マイコンのHALライブラリではUARTの受信割込みやDMA転送を使用した際に受信エラーが発生すると以降の受信処理が行われません。コマンドをUARTで処理する場合、受信エラー以降の受信が行われず、応答なし状態となっていまいます。
受信処理を継続して行うためにはエラー処理を加える必要があります。
実装としてはエラーが発生するとHAL_UART_ErrorCallbackが呼び出されます。
※設定によりますが、HAL_UART_ErrorCallbackが呼び出されないエラーがあったため、HAL_UART_ErrorCallback内でクリアせずにwhile内等でのクリア処理に変更しました。
UARTのエラーフラグを確認してクリアするHAL_UART_Abort関数を実行して受信処理を再開させます。
なお、HAL_UART_Abort関数は割込みを解除する関数ですが、各種エラーをクリアさせる機能も入っています。個々のエラーフラグだけをクリアするだけでは再開できないことが多々あるため、HAL_UART_Abort関数でレジスタをクリアさせる方法が確実です。
if(huart->Instance==USART1){
if ( __HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) ||
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) ||
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) ||
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_PE) ){
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) ||
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) ||
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_PE) ){
HAL_UART_Abort(&huart1);
HAL_UART_Receive_DMA(&huart1, (uint8_t*)&UART_Data, 1);//DMAの場合
HAL_UART_Receive_DMA(&huart1, (uint8_t*)&UART_Data, 1);//DMAの場合
//HAL_UART_Receive_IT(&huart1, (uint8_t*)&UART_Data, 1);//割込みの場合
}
}
}
上記処理をmain.cのwhile内等に配置することでエラー処理することができます。
以前に通常の処理ではうまく受信できるがタイミングによって受信できなくなるといった不具合に悩まされました。原因がフレーミングエラーと分かりました。電源投入直後のノイズ等でエラーが発生してしまったようです。上記の処理を加えることでエラー時に処理を再開させ、安定して通信を継続できるようになりました。
※一部HALライブラリ依存があったため、修正しました