我正试图在stm32f405上通过DMA进行UART传输。我的应用程序的这一部分旨在将文本字符串作为命令行界面发送。我让UART的RX部分正常工作(使用1字节的圆形DMA来处理任何进入的东西)但是TX方面证明有点棘手。
如果函数连续调用之间有延迟,我可以使用HAL_UART_Transmit_DMA(&handle, pData[], strlen(pData))
发送数据字符串。一旦我的程序决定一个接一个地发送两个字符串,就会忽略新的数据指针。
使用while(HAL_UART_Transmit_DMA(...) != HAL_OK){}
我可以让程序等待所需的时间并发送连续的字符串。
这有效一段时间(几十次传输),然后由于HAL_NOT_OK而卡住。
作为参考,我的DMA设置为:DMA2 stream 7
,channel 4
,mem to periph
,periph inc disabled
,mem inc enabled
,mem and periph align byte
,{{1 },normal mode (not circular)
,low priority
。
UART设置为fifo disabled
,9600 baud
,8 bit word
,1 stop bit
,no parity
,no hw control
。
我正在试图弄清楚使用FIFO是否会帮助我,尽管我还不完全确定我是否理解它。如果我想发送一个字节的数据,我可以用FIFO做吗?这里有1字的最小限制吗?
我已经设置了一个我目前没有使用的16 oversampling
。我确实想知道在这个中断期间是否有需要清除的标志但是不确定..
任何帮助表示赞赏!
答案 0 :(得分:2)
我已经设置了一个目前尚未使用的tx完整回调。我确实想知道是否>在此中断期间我需要清除任何标志,但不确定。
在再次使用tx complete
之前,您应该等待HAL_UART_Transmit_DMA
回调。类似的东西:
bool txDoneFlag = false;
HAL_UART_Transmit_DMA(...)
while(!txDoneFlag);
txDoneFlag = false;
...
...
void HAL_UART_TxCpltCallback(){
txDoneFlag = true;
}
答案 1 :(得分:1)
HammerFet,我相信你需要使用循环模式(例如DMA_Mode_Circular
)。试一试。
另外,请查看STM32F4 Application Note中非常简短的1.1.8部分,其中说明了以下内容:
正常模式:一旦DMA_SxNDTR寄存器达到零,流就被禁用 (然后,DMA_SxCR寄存器中的EN位等于0)。
如下所示的DMA配置设置示例如下:
volatile char Buffer[] = "first uart test with stm32f4\r\n";
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Stream2);
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // Receive
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_BufferSize = (uint16_t)sizeof(Buffer);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART4->DR;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream2, &DMA_InitStructure);
/* Enable the USART Rx DMA request */
USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);
/* Enable DMA Stream Half Transfer and Transfer Complete interrupt */
DMA_ITConfig(DMA1_Stream2, DMA_IT_TC | DMA_IT_HT , ENABLE);
/* Enable the DMA RX Stream */
DMA_Cmd(DMA1_Stream2, ENABLE);
}
答案 2 :(得分:1)
如果以高波特率(> 1MBaud)进行传输,则传输FIFO非常有用。发生的情况是处理器无法足够快地馈送UART,然后可能发生与缓冲器下溢相关的错误。您还可以更改为UART供电的DMA通道的优先级。
循环模式对TX没有用,因为它会无休止地重新传输缓冲区中的数据,除非你及时更新它。虽然我发现循环缓冲区对于接收数据非常有用。
如果发送的字节数很小(<10Bytes),DMA传输会在一段时间后失败,我也遇到了问题。使用IT功能没有问题。我从来没有找到原因。因此,对于消息&lt; 10个字节,我使用IT发送功能,对于消息&gt; = 10个字节,我使用DMA发送功能。