cancel
Showing results for 
Search instead for 
Did you mean: 

RX and reTX from USART1 with dma (Stm32f100B)

Gigli.Dario
Associate II
Posted on February 07, 2013 at 01:53

Hi,

excuse me for my bad english,I'm new in the microcontrollers field, so I've some uncertainty on the use of the dma to read and write from USART. At the moment I'm interfacing the stm32f100B with a medical module that trasmittes continuosly datas, so I need reading these datas and to retransmit it by USART1.

I have written a code that reads the datas from USART and retransmittes it, this code works but it is without dma.

But now I need to use the dma to read and write data from USART, so I have written another code with dma but I don't understand where is the error and if I use dma in correct mode, because I don't receive nothing. 

My code is this:

#include ''stm32f10x_conf.h'' 

#include ''stm32f10x.h''

#include ''stm32f10x_dma.h''

#include ''stm32f10x_dma.c''

#include ''stm32f10x_usart.h''

#include ''stm32f10x_usart.c''

#include ''stm32f10x_rcc.c''

#include ''platform_config.h''

uint8_t buffer;

int k=0;

void board_init(void) {

    RCC->APB2ENR = 0

                   // Turn on USART1

                   | RCC_APB2ENR_USART1EN

                   // Turn on IO Port A

                   | RCC_APB2ENR_IOPAEN;

    // Put PA9  (TX) to alternate function output push-pull at 50 MHz

    // Put PA10 (RX) to floating input

    GPIOA->CRH = 0x000004B0;

    // Configure BRR by deviding the bus clock with the baud rate

    USART1->BRR = 8000000/9600;

    // Enable the USART, TX, and RX circuit

    USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;

}

// DMA_configuration

void DMA_Configuration(void)

{

  DMA_InitTypeDef DMA_InitStructure;

  /* USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */

  DMA_DeInit(USARTy_Tx_DMA_Channel);  

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;

  DMA_InitStructure.DMA_MemoryBaseAddr =buffer;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

  DMA_InitStructure.DMA_BufferSize = 1;

  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_Normal;

  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(USARTy_Tx_DMA_Channel, &DMA_InitStructure);

  /* USARTy RX DMA1 Channel (triggered by USARTy Rx event) Config */

  DMA_DeInit(USARTy_Rx_DMA_Channel);  

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;

  DMA_InitStructure.DMA_MemoryBaseAddr = buffer;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

  DMA_InitStructure.DMA_BufferSize = 1;

  DMA_Init(USARTy_Rx_DMA_Channel, &DMA_InitStructure);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

   /* Enable USARTy TX DMA1 Channel */

  DMA_Cmd(USARTy_Tx_DMA_Channel, ENABLE);

  /* Enable USARTy RX DMA1 Channel */

  DMA_Cmd(USARTy_Rx_DMA_Channel, ENABLE);

    /* Enable USARTy DMA Rx and TX request */

  /* Enable USARTy DMA Rx and TX request */

  USART_DMACmd(USARTy, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);

}

//

/**

 * Receive a single byte from USART1.

 */

int usartdma_rec(void) {

/* Wait until USARTy RX DMA1 Channel Transfer Complete */

  while (DMA_GetFlagStatus(USARTy_Rx_DMA_FLAG) == RESET);

    // read RX data, combine with DR mask (we only accept a max of 9 Bits)

    return USART1->DR & 0x1FF;

}

//Send a single byte by USART1. 

void usartdma_snd(int data) {

    USART1->DR = data;

/* Wait until USARTy TX DMA1 Channel Transfer Complete */

  while (DMA_GetFlagStatus(USARTy_Tx_DMA_FLAG) == RESET);

}

  

int main(void) {

    board_init();

DMA_Configuration();

    for(;;) {

      int rec=usartdma_rec();

      buffer=rec;

  

usartdma_snd(buffer);

  

    }

}

12 REPLIES 12
Gigli.Dario
Associate II
Posted on February 09, 2013 at 18:26

THANK YOU!!! I followed your advice and I solved the problem. I can manage the rx and tx interrupt.

My purpose is to active the interrupt tx only to empty the buffer, so each character received I check if the buffer is full. If it is full, I enable the interrupt tx until the buffer is empty and then I disable it. It work well.

 Is this mode right? Or the use of the tx interrupt is wrong? 

 This is the code:

char StringLoop[6];

/**************************************************************************************/

 

void RCC_Configuration(void)

{

  /* Enable GPIO clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

 

  /* Enable UART clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

}

 

/**************************************************************************************/

 

void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

 

  /* Configure USART Tx as alternate function push-pull */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  // PA.09 USART1.TX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

  /* Configure USART Rx as input floating */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA.10 USART1.RX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

 

/**************************************************************************************/

 

void USART_Configuration(void)

{

  USART_InitTypeDef USART_InitStructure;

 

  /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/

  /* USART configured as follow:

        - BaudRate = 9600 baud

        - Word Length = 8 Bits

        - One Stop Bit

        - No parity

        - Hardware flow control disabled (RTS and CTS signals)

        - Receive and transmit enabled

  */

  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_Rx | USART_Mode_Tx;

 

  /* USART configuration */

  USART_Init(USART1, &USART_InitStructure);

   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  /* Enable the USART1 */

  USART_Cmd(USART1, ENABLE);

 

}

 

/**************************************************************************************/

 

void NVIC_Configuration(void)

{  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   

  NVIC_InitTypeDef NVIC_InitStructure;

 

// Configure the NVIC Preemption Priority Bits

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

 

  /* Enable the USART1 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

 

/**************************************************************************************/

void USART_puts(USART_TypeDef* USARTx, volatile char *s){

while(*s){

// wait until data register is empty

while( !(USARTx->SR & 0x00000040) );

USART_SendData(USARTx, *s);

*s++;

}

}

/**************************************************************************************/

int main(void)

{

  RCC_Configuration();

 

  GPIO_Configuration();

 

  NVIC_Configuration();

 

  USART_Configuration();

  USART_puts(USART1, ''Init complete! Hello World!\r''); // just send a message to indicate that it works

  while(1){

  }

  

}

 

/**************************************************************************************/

void USART1_IRQHandler(void)

{

  static int tx_index = 0;

  static int rx_index = 0;

 if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // Received characters modify string

  {

    StringLoop[rx_index++] = USART_ReceiveData(USART1);

 

    if (rx_index >= (sizeof(StringLoop) - 1))

    {rx_index = 0;

      USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

    }

  }

  if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) // Transmit the string in a loop

  {

    USART_SendData(USART1, StringLoop[tx_index++]);

 

    if (tx_index >= (sizeof(StringLoop) - 1))

    {tx_index = 0;

          USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

}

  }

 }

  /**************************************************************************************/

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

 

  /* Infinite loop */

  while (1)

  {

  }

}

#endif

After I will use four usart to acquire continuosly datas, and I'll use the STM32F4. Do you think that this mode to use the interrupts is efficient?? Or Will I have to use the dma?

Posted on February 09, 2013 at 19:08

I don't think that will work too well under load. You need to create a ring/fifo buffer, or do some buffer management to allow for two such buffers and a continuous stream of data.

You have a receive 6, send 6, receive 6, send 6,... model, where you really need an elastic buffer between the input and output streams.

Processing 4 USARTs on a STM32F4, but you will need to master buffer management. As for DMA, using it for transmit would off load a lot of work from the processor, but receive would take a lot of work and understanding.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Gigli.Dario
Associate II
Posted on February 10, 2013 at 10:18

Thank you so much. I'll try to go on, and if I'll have any problems I'll ask your help.