2015-02-12 3 views
3

Я пытаюсь передать UART-передачу через DMA на stm32f405. Эта часть моего приложения предназначена для отправки текстовых строк в виде интерфейса командной строки. У меня есть часть RX UART, работающая с DMA fine (с использованием 1 байтового кругового DMA для обработки всего, что приходит), но сторона TX оказывается немного более сложной.STM32F4 HAL DMA UART 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, normal mode (not circular), low priority, fifo disabled.

UART установлен в 9600 baud, 8 bit word, 1 stop bit, no parity, no hw control, 16 oversampling.

Я пытаюсь выяснить, поможет ли мне использование FIFO, хотя я не совсем уверен, понимаю ли я его еще. Если бы я хотел отправить один байт данных, могу ли я сделать это с FIFO? есть ли ограничение на 1 слово мин?

Я установил tx complete callback, который им в настоящее время не используется. Я действительно задавался вопросом, есть ли какие-то флаги, которые мне нужно будет очистить во время этого прерывания, но не уверены.

Любая помощь оценена!

ответ

1

HammerFet, я считаю, что вам нужно будет использовать круговой режим (например, DMA_Mode_Circular). Попробуйте.

Кроме того, пожалуйста, ознакомьтесь с очень короткий раздел 1.1.8 в STM32F4 Application Note, в котором говорится следующее:

Нормальный режим: когда регистр DMA_SxNDTR достигает нуля, поток отключен (бит EN в тогда регистр DMA_SxCR равен 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

Я настроил ТХ полный обратный вызов, который им не в настоящее время используется. Я действительно задавался вопросом, есть ли> какие-либо флаги, которые мне нужно будет очистить во время этого прерывания, но не уверены.

СЛЕДУЕТ дождаться обратного вызова tx complete перед использованием HAL_UART_Transmit_DMA. Что-то вроде:

bool txDoneFlag = false; 
HAL_UART_Transmit_DMA(...) 
while(!txDoneFlag); 
txDoneFlag = false; 
... 
... 


void HAL_UART_TxCpltCallback(){ 
    txDoneFlag = true; 
} 
1

FIFO для передачи полезно, если вы передаете при высоких скоростях передачи данных (> 1MBaud). Что происходит, так это то, что процессор не может достаточно быстро подать UART, а затем может возникнуть ошибка, связанная с переполнением буфера.Вы также можете изменить приоритет канала DMA, подающего UART.

Круговой режим не очень полезен для TX, так как он будет бесконечно ретранслировать данные в буфере, если вы не обновили его вовремя. Хотя я считаю, что круговые буферы очень полезны для приема данных.

У меня также были проблемы, если количество переданных байтов было небольшим (< 10Bytes), через которое передача DMA завершится через некоторое время. Использование ИТ-функции работало без проблем. Я никогда не мог найти причину. Таким образом, для сообщений < 10 байт я использую функцию передачи ИТ и для сообщений> = 10 байт, я использую функцию передачи DMA.

Смежные вопросы