#はじめに
UARTでDMAを使いたかった。ところが...
送信時,どうも連続して送ろうとすると失敗する。
受信時,配列に最初の1このデータしか入力されない。
Mem側をIncrement指定しているのに,デバッガで止めてみると無視されている。
MINC=1になってほしいのに0になっている。
レジスタを触って解決するのは何か気持ちが悪いので,解決方法を探ってみた。
DMAをめぐるトラブルは結構あるみたい。
このあたりの情報で解決した。Device Configuration Tool - Project Manager - Advanced Setting で MX_DMA_Init を上の方にもっていく。
見つけた解決法
以下,手順を覚書。
さらにこの画面で,
こんな感じにします。
さらに USART2 global interrupt を有効にします。これをしないと,送信終了,受信終了がわかりません。
main関数の前です。送信完了がわかるようにします。また,受信完了したら再度受信スタンバイします。ここではついでにLEDをToggleしてます。
/* 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関数の序盤です。
- 送信完了を検知してから次のデータを送らないと,無視されてしまいます。
- 受信待機開始します。
/* 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
みなさんに感謝です!