stm 32シリアルポートHALライブラリのDMA送信問題
4018 ワード
本稿ではstm 32 f 411 retのシリアルポート1のDMA方式でデータを送信し,デバッグを開始するとシリアルポートが1回しかデータを送信できないことに気づき,その後システムhangを停止した.ネット上で資料を探したり、試したりすることで、問題はコールバック関数が書かれていない原因であることが分かった.
HALライブラリのDMAを使用するには、DMA割り込みコールバック関数とシリアルポート割り込みコールバック関数を同時に実現する必要がある.
次に、私のdma構成とシリアルポート構成関数を添付します.
dma構成
シリアルピン構成
シリアルポート構成
送信データは次の関数を呼び出せばよい
実際の操作では、シリアルポートの中断にフラグビットを設定して、シリアルポートの送信が完了したことをマークし、メインプログラムで送信関数の呼び出しをフラグビットで制御することができます.
HALライブラリのDMAを使用するには、DMA割り込みコールバック関数とシリアルポート割り込みコールバック関数を同時に実現する必要がある.
void DMA2_Stream7_IRQHandler(void)
{
HAL_DMA_IRQHandler(Uart1Handle.hdmatx);
}
void USART1_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
HAL_UART_IRQHandler(&Uart1Handle);
}
次に、私のdma構成とシリアルポート構成関数を添付します.
dma構成
void HAL_UART1_dma_Init(void)
{
static DMA_HandleTypeDef hdma_tx;
__HAL_RCC_DMA2_CLK_ENABLE(); // DMA2
/*##-3- Configure the DMA streams ##########################################*/
/* Configure the DMA handler for Transmission process */
hdma_tx.Instance = DMA2_Stream7;
hdma_tx.Init.Channel = DMA_CHANNEL_4; // 1 stream7、channel4, DMA
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; // : ->
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; // ,
hdma_tx.Init.MemInc = DMA_MINC_ENABLE; //
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //
hdma_tx.Init.Mode = DMA_NORMAL; // , ,
hdma_tx.Init.Priority = DMA_PRIORITY_LOW; //
hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_tx.Init.MemBurst = DMA_MBURST_INC4;
hdma_tx.Init.PeriphBurst = DMA_PBURST_INC4;
HAL_DMA_Init(&hdma_tx);
/* Associate the initialized DMA handle to the the UART handle */
__HAL_LINKDMA(&Uart1Handle, hdmatx, hdma_tx); // dma handle 1 hdmatx
/*##-4- Configure the NVIC for DMA #########################################*/
/* NVIC configuration for DMA transfer complete interrupt (USARTx_TX) */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 1); // dma
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn); // dma
}
シリアルピン構成
void Init_Usart1(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Enable USARTx clock */
__HAL_RCC_USART1_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(USART1_IRQn,0,0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
シリアルポート構成
void Usart1_Configuration(uint32_t BaudRate)
{
Uart1Handle.Instance = USART1;
Uart1Handle.Init.BaudRate = BaudRate;
Uart1Handle.Init.WordLength = UART_WORDLENGTH_8B;
Uart1Handle.Init.StopBits = UART_STOPBITS_1;
Uart1Handle.Init.Parity = UART_PARITY_NONE;
Uart1Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
Uart1Handle.Init.Mode = UART_MODE_TX_RX;
Uart1Handle.Init.OverSampling = UART_OVERSAMPLING_16;
if(HAL_UART_Init(&Uart1Handle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
}
送信データは次の関数を呼び出せばよい
HAL_UART_Transmit_DMA(&Uart1Handle, (uint8_t*)aTxBuffer, 32)
実際の操作では、シリアルポートの中断にフラグビットを設定して、シリアルポートの送信が完了したことをマークし、メインプログラムで送信関数の呼び出しをフラグビットで制御することができます.