2017-04-30 01:03 AM
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 stringThe 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
2017-04-30 05:57 AM
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.
2017-04-30 09:37 AM
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?
2017-04-30 09:57 AM
Ok figgured it quickly... used directly the unsigned int value, without converting it to char... and now its ok
USART_SendData(USART1,USART2->DR);
2017-04-30 11:42 AM
Ah... 0x00 in ascii is NULL.... but how can i add even 00?
2017-04-30 12:58 PM
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...