2019-04-20 02:06 AM
USART1 interrupt only receives one string, processes it well and returns it back as expected. But when i issue the second string, the check USART_IT_RXNE status flag is always false. I tried to reset it right after the preceeding string is sent but all in vain. Here is my code...Am using the tiny STM32F303K8
void USART_puts(USART_TypeDef* usar_tx, volatile char* str)
{
while (*str)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
USART_SendData(usar_tx, *str);
str++;
}
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
static int cnt = 0;
char ch = USART_ReceiveData(USART1);
if (ch != '\r')
{
rcvd_str[cnt++] = ch;
}
else
{
rcvd_str[cnt] = '\r';
cnt = 0;
USART_puts(USART1, rcvd_str);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
}
What on earth am i doing wrong or missing.
Solved! Go to Solution.
2019-04-20 03:06 AM
Paramount rule: Inside an interrupt, no delay no pending loops no waiting.
Of course, if main is busy, you have to handle any possible incoming....
UART transmit can be done in main loop as polling.
Also, interrupt pending bit usually is cleared by HW when you read the data register.
make your int cnt global and make it negative when you have received your message and discard any incoming until done.
This avoids managing both a cnt and a flag.
2019-04-20 03:06 AM
Paramount rule: Inside an interrupt, no delay no pending loops no waiting.
Of course, if main is busy, you have to handle any possible incoming....
UART transmit can be done in main loop as polling.
Also, interrupt pending bit usually is cleared by HW when you read the data register.
make your int cnt global and make it negative when you have received your message and discard any incoming until done.
This avoids managing both a cnt and a flag.
2019-04-20 03:49 AM
Well, i got it to fire by introducing a new boolean variable that gets set whenever all the string is recieved and processed. It seems to work for all multiple strings that i throw at it but now its having another symptom. It Sends the string back three times....lemmi show u what i did...
char rcvd_str[50];
int cnt = 0;
bool str_buildup = false;
void USART1_IRQHandler(void)
{
if (USART1->ISR & USART_ISR_RXNE)
{
//static int cnt = 0;
const char ch = USART_ReceiveData(USART1);
if (ch != '\n' && ch != '\r')
{
rcvd_str[cnt++] = ch;
}
else
{
rcvd_str[cnt] = '\r';
cnt = 0;
str_buildup = true;
}
}
}
// Now in main
while (1)
{
if (str_buildup == true)
{
USART_puts(USART1, rcvd_str);
memset(rcvd_str, 0, sizeof rcvd_str);
str_buildup = false;
}
}
i thought the problem would be that rcvd_str wasnt reset, so i tried to reset it at the end of every puts, but it doesnt seem to give me the desired results
This is what happens to me when i execute it in RealTerm. Am sending a string like "$GPRMC,141527.00,A,5740.2263174,N,01150.9873244,E,1.299,265.9,290319,0.0,E,A*39"
But its sending it back three times and on everytime, appends a BELL control character. At times it appends a BSL (Back slash)
2019-04-20 04:46 AM
Need to terminate the string properly.
Might need to clear overrun, framing, noise type errors.
Use TXE not TC to determine if USART can take data.
2019-04-20 05:01 AM
NMEA data may exceed 50 characters.
Variables that change via interrupt should be volatile.
2019-04-20 07:04 AM
It somehow refused to burge when i use the TXE flag. But i finally got a working copy that am saving for future reference. Yes, NMEA data might exceed 50 but just in this moment, am running only a GPRM command and according to the data i've collected, the whole string is roughly those number of characters as shown above. My ambition is to chop off gps coordinates and speed that i will later on transmit to some other receiver via telemetry for further processing. But your approach too helped me debug the code well. Thanks mate