因为是用STM32CubeMX生成初始化代码,凭直觉只在”DMA Settings”里增加了USART1_TX的一项:
结果在程序里调用HAL_UART_Transmit_DMA()时只能调用一次,第二次以后都没有输出,然后google,
原来还要在NVIC Settings里打开USART1 global interrupt:
然后就可以多次发送HAL_UART_Transmit_DMA()了。
启用NVIC USART中断句柄(使用DMA非循环模式时,用来检测最后一个字节发送完毕)
然来在HAL_UART_Transmit_DMA()函数的定义文件stm32f1xx_hal_uart.c就有How to use this driver, 里面有讲:
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
The UART HAL driver can be used as follows:
(#) Declare a UART_HandleTypeDef handle structure.
(#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:
(##) Enable the USARTx interface clock.
(##) UART pins configuration:
(+++) Enable the clock for the UART GPIOs.
(+++) Configure the USART pins (TX as alternate function pull-up, RX as alternate function Input).
(##) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()
and HAL_UART_Receive_IT() APIs):
(+++) Configure the USARTx interrupt priority.
(+++) Enable the NVIC USART IRQ handle.
(##) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA()
and HAL_UART_Receive_DMA() APIs):
(+++) Declare a DMA handle structure for the Tx/Rx channel.
(+++) Enable the DMAx interface clock.
(+++) Configure the declared DMA handle structure with the required
Tx/Rx parameters.
(+++) Configure the DMA Tx/Rx channel.
(+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle.
(+++) Configure the priority and enable the NVIC for the transfer complete
interrupt on the DMA Tx/Rx channel.
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
(used for last byte sending completion detection in DMA non circular mode)
————————分界线———————————
完成以上之后,是可以多次发送,但还是有一个问题, 两次发送之间的时间不能太小,如果上次还没有完成发送,第二次发送的内容就发不出去。
所以解决这个间隔时间问题,还要在发送完的的回调函数里增加状态设置:
1 2 3 4 5 6 7 |
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle) { if(&huart1 == UartHandle) { UartHandle->State = HAL_UART_STATE_READY; } } |
同时,在调用HAL_UART_Transmit_DMA()之前,要等待状态成为HAL_UART_STATE_READY,如封装成一个函数:
1 2 3 4 5 |
void Console_Log(char *message) { while(huart1.State != HAL_UART_STATE_READY); HAL_UART_Transmit_DMA(&huart1, (uint8_t *)message, strlen(message)); } |
这样就可以调用2次Console_Log()连续2次,中间不用加延时。