cancel
Showing results for 
Search instead for 
Did you mean: 

UART problem betwen stm32f407 and fpga

Bogdan
Senior
Posted on April 30, 2017 at 10:03

Hello,

i have a design where a fpga sends a packet of 10bytes at a baud of 57970 to USART2 of the stm32f407VE device.

The idea was to use USART2  where RX pin is receiving data from the fpga,  and the TX pin sends the data to a PC.

The problem is that when i try to store the incoming data into a string i store wrong chars.... 

The data packet has the following format   Byte1,byte2,byte3....byte9, 0A   - the last byte is '\n' indicating the end of the packet

What i am doing wrong?  Is the fpga to fast for the uart of the stm32?

I am using the RX interrupt feature, see the code bellow

#define MAX_STRLEN 9 // this is the maximum string length of our string in characters

volatile char received_string[MAX_STRLEN+1]; // this will hold the recieved string

The uart init routine

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 ; // Pins 5 (TX) and 6 (RX) are used

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; 

GPIO_Init(GPIOD, &GPIO_InitStruct);

GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2); //

GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);

USART_InitStruct.USART_BaudRate = 57970; 

USART_InitStruct.USART_WordLength = USART_WordLength_8b;

USART_InitStruct.USART_StopBits = USART_StopBits_1; // we want 1 stop bit (standard)

USART_InitStruct.USART_Parity = USART_Parity_No; // we don't want a parity bit (standard)

USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 

USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

USART_Init(USART2, &USART_InitStruct);

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); 

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; 

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 

NVIC_Init(&NVIC_InitStructure); 

USART_Cmd(USART2, ENABLE);

And the interrupt handler

void USART2_IRQHandler(void)

{

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//enter interrupt when STM32 receice data.

{

static uint8_t cnt = 0;// string lenght

char t = USART2->DR; // the character from the USART2 data register is saved in t

      if( (t != '\n') && (cnt <

MAX_STRLEN

) ){

                                                                     received_string[cnt] = t;

                                                                     cnt++;

                                                                    } 

      else{ // otherwise reset the character counter and print the received string

           cnt = 0;

           USART_puts(USART2, received_string);

         }

USART_ClearITPendingBit(USART2, USART_IT_RXNE);

GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

}

}

Bellow is a logic capture on the RX (fpga side) and TX(to the pc side) of the uart2

0690X00000606p7QAA.png
5 REPLIES 5
S.Ma
Principal
Posted on April 30, 2017 at 14:57

Interrupts are supposed to run quick as a flash. Sending the whole string within the interrupt is non ideal practice. When you have received your string, set a flag in the isr. If the isr comes back while flag is set, deal with it. In the main loop polling, wait for the flag set, send to usart the whole string then clear the flag, to get started. I would not oversimplify using rx tx for different device when stm32 has many usart. Use 2 of them so different baud rate can be used.

Bogdan
Senior
Posted on April 30, 2017 at 18:37

Hello,

i modified the interrupt handler in the following manner using another USART module for tx. 

For the moment i send only 1 char in the IRQ just to see how its working

Now my IRQ handler looks like bellow, 

void USART2_IRQHandler(void)

{

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//enter interrupt when STM32 receice data.

{

   t = USART2->DR;

   ss[0]=t;

    USART_puts(USART1, ss); // SEND 1 byte via usart1

USART_ClearITPendingBit(USART2, USART_IT_RXNE);

GPIO_ToggleBits(GPIOD, GPIO_Pin_1);

}

}

I also added a GPIO toggle (''PB12'') from the picture bellow just to see where i am in the irq

But i am facing another issue, from the logic analyzer screen shot bellow,   if the packet contains 0x00 bytes,   on the USART DR register when i read it its empty( ''MCU out''). Why?

 0690X00000606v2QAA.png

Bogdan
Senior
Posted on April 30, 2017 at 18:57

Ok figgured  it quickly... used directly the unsigned int value, without converting it to char... and now its ok

 USART_SendData(USART1,USART2->DR);  

Posted on April 30, 2017 at 18:42

Ah... 0x00 in ascii is NULL.... but how can i add even 00? 

Posted on April 30, 2017 at 19:58

Beware that as soon as the baudrate is different between both usart, using main loop polling will be required. It is simple coding and far easier to debug, unless using an rtos...