2015-10-13 11:51 PM
Hey guys. First of all im new to this kind of stuff, so dont judge me please.
I've been working for days on USART. I learned to transmit and receive strings via usart in normal mode, but as i try to do it with interrupts everything fall apart.First I have tried to init usart interupts, and use it with single characters - it worked nicely, but now im trying to do it with multiple chars using ring buffer as a storage. After all i will try to parse the string that i got. I searched every thread but it seems that i cant find the right answer to this.Maybe anyone have some examples of this? (ring buffer struct functions and implementation of it into usart interrupt receiver?)struct bufer { char buf[buffsize]; int start; int end; int count;};struct bufer buf = {0};void UartBufferInit(void) { buf.start = 0; buf.end = 0;}bool UartBufferEmpty(void) { return (buf.start == buf.end) ? TRUE : FALSE;}bool UartBufferFull(uint8_t c) { return (((buf.end + 1) % buffsize) == buf.start) ? TRUE : FALSE;}bool PutIntoBuffer(uint8_t c) { if(!UartBufferFull()){ buf.buf[buf.end] = c; buf.end = (buf.end +1) % buffsize; return TRUE; } else { return FALSE; }}void USART1_IRQHandler(void) { static char CopyOfBuf[buffsize]; static int rx_index = 0; if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { char rx = USART_ReceiveData(USART1); if ((rx == '\r') || (rx == '\n')) { if(rx_index != 0) { memcpy(CopyOfBuf, buf.buf, sizeof(buf.buf)+1); PutIntoBuffer(CopyOfBuf); } } }}2015-10-14 12:15 AM
Well there's definitely some confusing on your part between characters, and strings, at a C level.
The routine doesn't use rx_index, or advance it, and the memcpy() exceeds the length of the buffer. For strlen() you might need a +1 to account for the NUL, but the sizeof() gives the length of the buffer allocation, which is buffsize. Not sure I can get my head around what you need/want to achieve here, as you're better of parsing the data out of the FIFO/ring, and just stuffing the characters in one by one, as they arrive. The interrupt code looks to be a poor hack of some line buffering code example, which you don't cite.void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
char rx = USART_ReceiveData(USART1);
PutIntoBuffer(rx);
}
}
2015-10-14 01:05 AM
I made some changes in the code. Now Interrupt handler looks like:
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
PutIntoBuffer(USART_ReceiveData(USART1));
}
}
For the check i use RTOS task to blink leds.
__task void packetread (void) {
for(;;) {
static char CopyOfBuf[buffsize];
strcpy(CopyOfBuf, buf.buf);
if (strncmp(CopyOfBuf, ''set'', 3)) {
os_tsk_create(STSblink, 1);
} else if(strncmp(CopyOfBuf, ''gps'', 3)) {
os_tsk_create(GPS_blink, 1);
} else {
snd(''wrong command
'');
}
os_dly_wait(50);
}
}
and as far as i can see it just doesnt compares the string. Instead of it it jumps to STSblink task. Maybe do you know why?
In my opinion i made some mistakes in ring buffer write routine, please check it and give your opinion.
struct bufer {
char buf[buffsize];
int head;
int tail;
int count;
};
struct bufer buf = {0};
void UartBufferInit(void) {
buf.head = 0;
buf.tail = 0;
}
bool UartBufferEmpty(void) {
return (buf.head == buf.tail) ? TRUE : FALSE;
}
bool UartBufferFull(void) {
return (((buf.tail + 1) % buffsize) == buf.head) ? TRUE : FALSE;
}
bool PutIntoBuffer(uint8_t c) {
if(!UartBufferFull()){
buf.buf[buf.tail] = c;
buf.tail = (buf.tail +1) % buffsize;
return TRUE;
} else {
return FALSE;
}
}
2015-10-14 01:51 AM
I think a key part of your problem is that string functions expect NUL termination, you don't provide for, or handle that.
When pulling data out, you want to do it a character at a time, forming a string, and when you encounter a CR or LF character, you replace that with a NUL (ZERO), and then process that string.2015-10-14 04:40 AM
And what is the best way to search in a buffer for end symbols. I cant do something like if (buf.buf == ' ') thing, cuz of the size of the buffer.
Im trying it with strncmp, but seems that is not quite good idea too.__task void packetread (void) {
for(;;) {
static char CopyOfBuf[buffsize];
if (strncmp(buf.buf, ''
'', 2) == 0){
strcpy(CopyOfBuf, buf.buf);
if (strncmp(CopyOfBuf, ''set'', 3 ) == 0) {
os_tsk_create(STSblink, 1);
} else if(strncmp(CopyOfBuf, ''gps'', 3) == 0) {
os_tsk_create(GPS_blink, 1);
} else {
snd(''wrong command
'');
}
}
os_dly_wait(50);
}
}
2015-10-14 08:04 AM
Well you can't take it out of the ring buffer assuming it's going to be a linear run of characters that doesn't wrap, because at some point it will wrap, and the data won't always start at the beginning.I did post some explicit examples of using a LINE buffer, that are better suited to GPS NMEA streams which have specific start characters, and termination characters.
https://community.st.com/0D50X00009Xkh8gSAB
https://community.st.com/0D50X00009Xkh8gSAB#comment-69622
If you're going to pursue the FIFO/ring buffer, you going to need to extract a character at a time, placing them in a linear buffer. Once you've closed the string out with a NUL, *THEN* you can use string functions. You can't strcpy() out of the buffer because it's unbounded.Edit: Fixed DEADLINK