LoginSignup
9
5

More than 1 year has passed since last update.

STM32 DMAを使ったUART通信ではまる

Last updated at Posted at 2021-09-24

はじめに

UARTでDMAを使いたかった。ところが...

送信時,どうも連続して送ろうとすると失敗する。

受信時,配列に最初の1このデータしか入力されない。

Mem側をIncrement指定しているのに,デバッガで止めてみると無視されている。
MINC=1になってほしいのに0になっている。

GetImage.png

レジスタを触って解決するのは何か気持ちが悪いので,解決方法を探ってみた。

https://community.st.com/s/question/0D50X0000Bmob3u/dma-not-working-in-cubemx-generated-code-order-of-initialization

DMAをめぐるトラブルは結構あるみたい。

https://community.st.com/s/question/0D50X0000BVnBhASQV/bug-report-dma-and-adc-initialization-order-changed-in-stm32f4-hal-v1241-causing-incorrect-adc-operation

このあたりの情報で解決した。Device Configuration Tool - Project Manager - Advanced Setting で MX_DMA_Init を上の方にもっていく。

見つけた解決法

以下,手順を覚書。

RX/TXでDMAを追加します。
image.png

さらにこの画面で,

image.png

こんな感じにします。

image.png

さらに USART2 global interrupt を有効にします。これをしないと,送信終了,受信終了がわかりません。
image.png

main関数の前です。送信完了がわかるようにします。また,受信完了したら再度受信スタンバイします。ここではついでにLEDをToggleしてます。

main.c
/* USER CODE BEGIN 0 */

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
    huart2.gState = HAL_UART_STATE_READY;
}

uint8_t UART2_RX_Buffer[8];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
    if (huart->Instance == USART2) {
        HAL_UART_Receive_DMA(&huart2, UART2_RX_Buffer, 8);
    }
}
/* USER CODE END 0 */

そしてmain関数の序盤です。

  • 送信完了を検知してから次のデータを送らないと,無視されてしまいます。
  • 受信待機開始します。
main.c
    /* USER CODE BEGIN 2 */

    HAL_UART_Transmit_DMA(&huart2, (uint8_t*) "Boot NUCLEO\r\n", 13);
    while (huart2.gState != HAL_UART_STATE_READY) {
    } // 送信完了を確認
    HAL_UART_Transmit_DMA(&huart2, (uint8_t*) "Type any key.\r\n", 14);
    while (huart2.gState != HAL_UART_STATE_READY) {
    } // 送信完了を確認
    HAL_UART_Transmit_DMA(&huart2,
            (uint8_t*) "Then toggle LED each 8 letters.\r\n", 33);

    HAL_UART_Receive_DMA(&huart2, UART2_RX_Buffer, 8);

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1) {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */

補足

色々な事情で,NUCLEO-F303K8 (CPU:STM32F303K8) だけでなく,STM32G0 の CPU 2種類も,同様であることを確認しました。

また暫定ですが,ADCでDMAを使いたい場合も,DMA初期化をADC初期化の前に持ってくる必要がありそうです。

参考URL

みなさんに感謝です!

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5