STM32F4 HAL DMA UART TX

时间:2015-02-12 15:27:59

标签: fifo stm32 uart dma stm32f4discovery

我正试图在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 7channel 4mem to periphperiph inc disabledmem inc enabledmem and periph align byte,{{1 },normal mode (not circular)low priority

UART设置为fifo disabled9600 baud8 bit word1 stop bitno parityno hw control

我正在试图弄清楚使用FIFO是否会帮助我,尽管我还不完全确定我是否理解它。如果我想发送一个字节的数据,我可以用FIFO做吗?这里有1字的最小限制吗?

我已经设置了一个我目前没有使用的16 oversampling。我确实想知道在这个中断期间是否有需要清除的标志但是不确定..

任何帮助表示赞赏!

3 个答案:

答案 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发送功能。