I have a device which spits out an ASCII stream of comma separated values which starts with a ! and ends with a # at 115200 baud. I'm trying to read the values with an EK-LM3S9B96 but I can't figure out the best way to do it. Currently this is what I am doing
TMainState mainState; int iBuff = 0; char commandBuff[32]; char delim[] = {","};
memset(commandBuff, 0, sizeof(commandBuff)); mainState = STATE_IDLE; while(1){ switch(mainState) { case STATE_IDLE: if(UARTCharsAvail(UART1_BASE)){ commandBuff[iBuff] = UARTCharGetNonBlocking(UART1_BASE); if(commandBuff[iBuff] == '!'){ mainState = STATE_CMD_RECEIVING; break; } break; } break; case STATE_CMD_RECEIVING: if(UARTCharsAvail(UART1_BASE)){ commandBuff[iBuff] = UARTCharGetNonBlocking(UART1_BASE); if(commandBuff[iBuff] == '#'){ mainState = STATE_CMD_RECEIVED; commandBuff[iBuff] = 0; break; } if(commandBuff[iBuff] == '!'){ // We missed a stop bit mainState = STATE_IDLE; iBuff = 0; break; } if(iBuff++ >= 32) iBuff = 0; } break; case STATE_CMD_RECEIVED: mainState = STATE_IDLE; memset(commandBuff, 0, sizeof(commandBuff)); iBuff = 0; break; } }
Even as I was writing it, it didn't feel right. The problem is if I miss a character everything is out of sync and I seem to be missing quite a few. That part doesn't make sense. I'm not doing anything else and I enabled the FIFO's on the UART. I'm only sending about 25 bytes every 100ms. Any suggestions on the missing bytes?
I could really use some suggestions on a better way to handle ASCII data streams in an efficient manor. This problem seems to come up quite often and this is always my solution. Even when I try to brainstorm and think I have come up with something new, it turns out to be this and I remember it's the exact same thing I did last time.
Hello Ryan,
Have you seen the command line example in the StellarisWare directories? If you go to the install location and look in Stellarisware\utils there is a cmd.c and cmd.h example that parses a command string. Will that help you?
Regards,
Craig
It helps a little bit but it's not the same in that it doesn't need to worry about pulling a string out of larger buffer of strings. My secondary device sends
"!ANG:,123.45,678.90,123.45#" (Euler angles)
every 100ms so it's not like at any point I know that the next character is the first character in the command. I do if I received the stop byte but sometimes I miss it or some of the other bytes which throws everything else off. I have to wait for the '!' before I know it's the start of the string where as the cmdline.c just assumes it is being passed a string which starts with the start byte. The code is helpful although I can't really use it until I find a reliable way to pull the right 27 characters out of a stream of data.
uartstdio.c looks a little more promising.
I would use a ring buffer big enough for one command line and let the UART ‘receive’ interrupt store the received bytes into this buffer, this way you should never miss any incoming bytes.
Then from in the main function, just poll the ring buffer byte count.
Another thing I would add is a CRC check, gives a way to check if the data is valid.