PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Im Rinfpuffer suchen



Hemi
25.05.2008, 16:17
Hallo zusammen,

ich habe ein kleines Problemchen, okay, es sind zwei in einem. O:)

Und zwar, habe ich einen UART-Ringpuffer:



#define UART_BUF_SIZE 128

char uart0_buffer[UART_BUF_SIZE];
unsigned char in0_ptr;
unsigned char out0_ptr;


Der Ringpuffer wird von den Funktion (bzw. Interrupt) befüllt:



ISR(USART0_RXC_vect) {
uart0_buffer[in0_ptr] = UDR0;
in0_ptr++;

if (in0_ptr == UART_BUF_SIZE){
in0_ptr = 0;
}
}


Soweit, so gut.

Nun habe ich folgendes Problem: Wie kriege ich das hin, dass ich im Ringpuffer suchen kann?

Angenommen, ich habe eine Nachricht, die so aussieht:



// Bremsbeläge
char brake_pads_msg[] PROGMEM = {0x02, 0x04, 0x01, 0xC8, 0x3E, 0xF1};


Wie kriege ich das hin, dass ich solche Nachrichten im Datenstrom finden kann?

Das war das erste Halbproblem.

Hier das zweite Halbproblem:

Angenommen, ich habe eine Teilnachricht, die ich im Datenstrom suchen will. Diese sieht dann so aus:



// Verbrauch1:
char consumption1_msg[] PROGMEM = {0x02, 0x05, 0x01, 0x92};


Hier ist es etwas schwieriger. Die zweite Stelle dieser Nachricht, also 0x05 gibt die Länge der Nachricht an. Der Punkt ist, dass die Nachricht an sich sich ändert, nur dieser Header ist immer gleich. Das würde bedeuten, dass ich nach diesem Header suchen muss, wenn ich den Header gefunden habe, muss ich die ganze Nachricht extrahieren und dann auswerten.

Hier ein Beispiel der vollständigen Nachricht:

0x02, 0x05, 0x01, 0x92, 0x95, 0x83, 0x82

0x02: Ist der Sender der Nachricht
0x05: Ist wie gesagt die Länge der Nachricht ab dem nächsten Byte
0x01: Ist der Empfänger
0x92: Nummer der Funktion (ist uninteressant für dieses Beispiel)
0x95 und 0x83 sind die Nutzdaten
0x82: XOR CRC

Die Länge wird ab dem dritten Byte bis CRC angegeben und sie ist wie gesagt immer gleich bei dieser Art der Nachrichten.

Vielen Dank im Voraus.

Achja, ganz vergessen, der Mikrocontroller ist ein AtMega162.

Grüsse
Heinrich

Ceos
26.05.2008, 11:57
statt mit einem pointer das array zu befüllen wwürde ich mit 2 inizes arbeiten



int writecount;
int readcount;

ISR(){
Buff[writecount++] = RxByte;
}

...
bytestoread = writecount - readcount;
if (bytestoread < 0) bytestoread += buffsize;
if (bytestoread > 1) { // mehr als 2 bytes empfangen (also auch das längebyte)
if ((bytestoread > buff[readcount+1]+2) // ausreichend bytes anhand der länge im paket ?
&& (getCRC(&buff[readcount]) == buff[buff[readcount+1]+2])) { // crc nachrechnen und mit der im paket vergleichen
doyourwork();
}
}

ACHTUNG dieser code kann rechenfehler beinhalten, aber so ungefähr habe ich das gelöst

gothmog
26.05.2008, 14:58
Hi!

@Ceos: Wieso pointer? Er füllt den Empfangsbuffer doch auch über einen Index.

Gruß
Jonas

geronet
26.05.2008, 18:11
Naja also nach Nachrichten suchen ist doch nicht so schwer:
Mit ner for-Schleife alle Elemente abgehen, jedesmal prüfen ob brake_pads_msg[i] drinsteht, falls ja prüfen ob brake_pads_msg[i+1] dahintersteht usw.
Mit variablen dann halt etwas spezieller schreiben und die Prüfung für Pufferüberlauf nicht vergessen bzw. am Anfang weitersuchen.

Grüsse, Stefan

Hemi
26.05.2008, 23:07
Hallo Leute,

vielen Dank für die Ratschläge.

Ihr meint sowas, oder:




while (out0_ptr < in0_ptr) {
out0_ptr++;
if (uart0_buffer[out0_ptr]== brake_pads_msg[0]) {
if (uart0_buffer[out0_ptr+1]== brake_pads_msg[1]) {
if (uart0_buffer[out0_ptr+2]== brake_pads_msg[2]){
if (uart0_buffer[out0_ptr+3] == brake_pads_msg[3]) {
printf("BrakePads gefunden\n");
}
}
}
}
}


Grüssle
Heinrich

geronet
27.05.2008, 17:10
Jo fast nur dass [out0_ptr+1] halt doch mal auf das letzte Element zeigen kann und mit +1 wäre das dann undefinierter Speicher, also lieber vorher prüfen z.B. so:


while (out0_ptr < in0_ptr)
{
uint8_t i = ++out0_ptr;
if (uart0_buffer[i++]== brake_pads_msg[0])
{
if (i >= UART_BUF_SIZE)
i = 0;
if (uart0_buffer[i++]== brake_pads_msg[1])
{
if (i >= UART_BUF_SIZE)
i = 0;
if (uart0_buffer[i++]== brake_pads_msg[2])
{
if (i >= UART_BUF_SIZE)
i = 0;
if (uart0_buffer[i++] == brake_pads_msg[3])
{
printf("BrakePads gefunden\n");
}
}
}
}
}


Blöde Frage aber kann das überhaupt funktionieren mit dem Ringpuffer bei
(out0_ptr < in0_ptr), wenn out0_ptr z.B. knapp UART_BUF_SIZE ist und in0_ptr z.B. 0 oder 1 ist? Nach der ISR oben is das zumindest möglich.

Grüsse, Stefan