STM32のUSARTでDMA受信
はじめに
STM32のUSARTでHAL関数を使ってDMA受信する方法をまとめました。
単純にHALの受信関数のみ使うと受信するデータ列のサイズは固定長である必要が有ります。
ここでは可変長サイズでも対応可の方法を集めました。
環境
OS:Windows10 Pro 2004
IDE:STM32CubeIDE 1.3.0
デバイス:STM32F407 Discovery kit
循環バッファ方式
Topic: 'Best' way to load UART data to ring buffer with STM32/HAL (Read 25675 times)
DMA設定
USART受信のDMAをCircularモードに設定します。
これにより、バッファの末端を超えると先頭からデータを格納する循環バッファになります。
実装
データ受信をポーリング監視する場合の実装です。
#define USART_RX_BUFFSIZE 128
static UART_HandleTypeDef* pHuart;
static uint8_t RxBuff[USART_RX_BUFFSIZE];
static uint32_t rd_ptr;
#define DMA_WRITE_PTR ( (USART_RX_BUFFSIZE - pHuart->hdmarx->Instance->NDTR) % (USART_RX_BUFFSIZE) )
void USART2_Init(void)
{
pHuart = &huart2;
memset(RxBuff, 0, sizeof(RxBuff));
rd_ptr = 0;
__HAL_UART_DISABLE_IT(pHuart, UART_IT_PE);
__HAL_UART_DISABLE_IT(pHuart, UART_IT_ERR);
HAL_UART_Receive_DMA(pHuart, RxBuff, USART_RX_BUFFSIZE);
}
int USART2_RX_IsEmpty(void)
{
return (rd_ptr == DMA_WRITE_PTR);
}
uint8_t USART2_RX_Read(void)
{
uint8_t c = 0;
if(rd_ptr != DMA_WRITE_PTR) {
c = RxBuff[rd_ptr++];
rd_ptr %= USART_RX_BUFFSIZE;
}
return c;
}
DMA_WRITE_PTRがDMAによる次書き込み位置を表し、rd_ptrが次読み取り位置を表しています。
なお、バッファサイズ指定を柔軟にする為に、参考記事からは終端越えの処理を変えています。
IDLEイベント方式
データ受信後、一定時間経過した時に発生するイベントです。
参考
受信データがパケット形式で間隔を空けて送られてくる場合などに使えます。
設定
実装
#define USART_RX_BUFFSIZE 128 // 受信パケットサイズより大きくします
static UART_HandleTypeDef* pHuart;
static uint8_t RxBuff[USART_RX_BUFFSIZE];
static uint32_t rd_ptr;
#define DMA_WRITE_PTR ( (USART_RX_BUFFSIZE - pHuart->hdmarx->Instance->NDTR) % (USART_RX_BUFFSIZE) )
void USART2_Init(void)
{
pHuart = &huart2;
memset(RxBuff, 0, sizeof(RxBuff));
rd_ptr = 0;
__HAL_UART_DISABLE_IT(pHuart, UART_IT_PE);
__HAL_UART_DISABLE_IT(pHuart, UART_IT_ERR);
__HAL_UART_ENABLE_IT(pHuart, UART_IT_IDLE); // <= 追加
HAL_UART_Receive_DMA(pHuart, RxBuff, USART_RX_BUFFSIZE);
}
・・・
void USART2_EventHandler(void)
{
int rxlen = 0;
if(__HAL_UART_GET_FLAG(pHuart, UART_FLAG_IDLE) != RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(pHuart);
HAL_UART_DMAStop(pHuart);
// データ受信処理
rxlen = DMA_WRITE_PTR; // 受信データ長(受信データ長がバッファサイズと同じ場合は0に戻る為注意)
HAL_UART_Receive_DMA(pHuart, RxBuff, USART_RX_BUFFSIZE); // DMA受信再スタート
}
}
stm32f4xx_it.c
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
USART2_EventHandler(); // <= 追加
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
Author And Source
この問題について(STM32のUSARTでDMA受信), 我々は、より多くの情報をここで見つけました https://qiita.com/forest1/items/64f885570a4f32a4d5a0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .