cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 USART3 DMA Transmit problem

ASSAAD.ASSAAD
Associate II
Posted on December 18, 2014 at 13:32

Hello Everyone

I am tryint to send data through usart3 by dma ; I can send data without DMA but when configure to use the DMA I could not send ; Could you guide me to check my mistakes ; the code is :

void init_usart(void){ 
GPIO_InitTypeDef GPIO_InitStructure; 
USART_InitTypeDef USART_InitStructure; 
/* enable peripheral clock for USART2 */ 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); 
/* GPIOA clock enable */ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 
/* GPIOA Configuration: USART2 TX on PA2 */ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 

/* Connect USART3 pins to AF2 */ 
// TX = b10 
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); 
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); 
USART_InitStructure.USART_BaudRate = 115200; 
USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
USART_InitStructure.USART_StopBits = USART_StopBits_1; 
USART_InitStructure.USART_Parity = USART_Parity_No; 
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; 
USART_Init(USART3, &USART_InitStructure); 
USART_Cmd(USART3, ENABLE); // enable USART3 
} 
//--- 
void DMA_Configuration(void) 
{ 
DMA_InitTypeDef DMA_InitStructure; 
// NVIC_InitTypeDef NVIC_InitStructure; 
// 
// /* Configure the Priority Group to 2 bits */ 
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
// 
// /* Enable the UART4 RX DMA Interrupt */ 
// NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn; 
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
// NVIC_Init(&NVIC_InitStructure); 
// 
/* DMA1 clock enable */ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); 
DMA_DeInit(DMA1_Stream3); 
DMA_InitStructure.DMA_Channel = DMA_Channel_3; 
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Transmit 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer_usart; 
DMA_InitStructure.DMA_BufferSize = (uint16_t)sizeof(Buffer_usart) - 1; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->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_Mode_Normal ;// 
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_Stream3, &DMA_InitStructure); 
/* Enable the USART Tx DMA request */ 
USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE); 
/* Clear the TC bit in the SR register by writing 0 to it */ 
USART_ClearFlag(USART3, USART_FLAG_TC); 
/* Enable DMA Stream Transfer Complete interrupt */ 
// DMA_ITConfig(DMA1_Stream3, DMA_IT_TC, ENABLE); 
/* Enable the DMA Tx Stream */ 
DMA_Cmd(DMA1_Stream3, ENABLE); 
} 

Thank you in advanced ; Hector
8 REPLIES 8
ivani
Associate II
Posted on December 18, 2014 at 13:54

It should be:

DMA_InitStructure.DMA_Channel = DMA_Channel_4;

ASSAAD.ASSAAD
Associate II
Posted on December 18, 2014 at 14:33

Thank you ; I tried 4 too ; but does not work t

ASSAAD.ASSAAD
Associate II
Posted on December 18, 2014 at 14:52

Thank you Ivan it Works ; I mixed between stream4 and channel4;

I dont use interrupt ; I want to send the buffer using DMA;  but  how can I resend the data again ; everytime I want to send shouldI call DMA_Configuration(); or any suggestion ? 

Thank you  

Posted on December 18, 2014 at 15:10

Yes, you would need to reconfigure the DMA transfer for each burst in Normal mode.

0690X0000060MmxQAE.gif

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ivani
Associate II
Posted on December 18, 2014 at 15:40

but  how can I resend the data again

Yes, you should reconfigure the DMA before every transfer. At least I didn't find a good way to use it in a circular mode for transmission (for the reception it is possible).

A very direct approach is to supply the address of the buffer and number of characters to a function, which will configure and enable the DMA for each transfer. If the previous transfer was not yet finished it should wait for it, which is the penalty for the simplification.

A more advanced way will be an implementation of a circular buffer for transmitted characters. But because the DMA is used in a linear mode we have to manage it - when we copy the characters before the end of the buffer we set the DMA once to transmit the number of characters. When we roll back to the beginning of the buffer we set once the DMA to send the characters up to the end of the buffer and then when the DMA TC interrupt is triggered - for a second transfer for the remaining characters.

Sounds a bit complicating but works :-).
ASSAAD.ASSAAD
Associate II
Posted on December 18, 2014 at 15:59

Thank you Clive for the taple it is clear now for me ;

How to renable transmit again over DMA ; for example I called DMA_Confige ; it sends the data in the buffer ; later on  I want to send I call DMA_CONFIG again or is there any other set flag ?

Thank you

ivani
Associate II
Posted on December 18, 2014 at 16:35

Generally, before restarting you need to set again the number of data items, the base address of the buffer in the DMA registers and re-enable the DMA again. But with SPL everything is in a common structure, so all fields should be valid before calling the initialization function. If the configuration structure is a global variable then you may update only the number of characters (you may send different number every time, right?) and (may be) the buffer address if it is different, so you will fill all the remaining fields only once.