Ich empfange hier Frames mit 4 Byte Payload, wobei sich die Nachricht nach dem 2ten Byte wiederholt.. also doppelt vorhanden ist. Das mach ich, weil ich recht schnell ohne großes Sicherheitsnetzt (nur CCA beim Senden) viele Statusmeldungen mit mehreren Modulen verschicke.. da kommen schon mal Fehler durch, trotz meiner kleinen CRC. Insgesamt kommt noch eine 16Bit CRC vom RF230 automatisch erzeugt über das ganze. Aber genug der Vorrede.. Laut dem Datenblatt vom dem RF230 kann man während des Empfangs schon mit dem Lesen der empfangenen Bytes beginnen. Zuerst lese ich also 32µs nach dem RX_START Interrupt nur die PHR ein (1byte via 802.15.4 brauchte 32µs), um zu entscheiden, ob die Nachricht überhaupt von mir ist (meine Nachrichten sind immer gleich lang) sonst kann ich das Empfangen gleich wieder beenden und auf das nächste SFD warten. Das funktioniert problemlos. Danach warte ich 64µs und lese dann byte 1&2 meiner eigentlichen Nachricht nochmal zusammen mit dem PHR-byte ein und schaue nach, ob mein selbstgebasteltes CRC stimmt (Bit2:0 von byte 2), sonst kann ich auch hier wieder den Empfang abbrechen. Ohne Störungen auch dies Problemlos. Keine Ausfälle. Nun vergehen wieder 64µs bis byte 3&4 meiner Nachricht eintrudeln, welche genau das gleiche wie byte 1&2 enthalten sollten. Da ich jetzt aber nicht schon wieder PHR + byte 1&2 einlesen will (4µs/byte) habe ich es hier mit SRAM-Lesezugriff versucht. Das verursacht aber sehr häufig Fehler.. byte 3&4 != byte 1&2. Im Vergleich mit dem Lesen von byte 3&4 im Rahmen eines kompletten Lesevorganges mit PHR enstehen keine Fehler, dh. byte 3&4 == byte 1&2. Selbst wenn ich mittels SRAM-Zugriff byte 1&2 (wie im Code aufgeführt) einlese werden Fehler angezeigt, obwohl ichs nur mit dem vorher per normalem Lesezugriff erhaltenen vergleiche.. was mache ich falsch?! Die entsprechenden Codeschnipsel:
1 | ISR (INT5_vect) // kommt 8µs nachdem das PHR-Octet begonnen hat (per Octet 32µs) |
2 | {
|
3 | initialize_timer4B_us (32); // Timer 4 Compare Match in 32us |
4 | // 32µs warten, dann PHR einlesen
|
5 | poll_timer4B_CompareMatch(); |
6 | initialize_timer4B_us (64); // Timer 4 Compare Match in 62ms |
7 | uint8_t rec_PHR = spi_read_framePHR(); // PHR einlesen |
8 | if (rec_PHR == 6) // 1. Test ob's zu uns gehört: ((byte1 + byte2)* 2) + (16Bit-CRC) <=> 6) |
9 | {
|
10 | // 64µs warten, dann 1st Frame einlesen
|
11 | poll_timer4B_CompareMatch(); // Timer 4 Output Compare B Flag pollen |
12 | initialize_timer4B_us (62+16); // Timer 4 Compare Match in 62ms |
13 | uint16_t rec_frame = spi_read_frame(); // die ersten 2 byte einlesen |
14 | if (crc_calc (crc_poly, (rec_frame>>8), rec_frame) != 0) goto Abbruch; // CRC-Check |
15 | // wenn CRC check sagt 'recFrame' ist defekt oder nicht unseres -> Abbruch
|
16 | // 64µs warten, dann das 2nd Frame einlesen
|
17 | poll_timer4B_CompareMatch(); // Timer 4 Output Compare B Flag pollen |
18 | |
19 | // Compare 1st mit 2nd Frame
|
20 | /* abwechselnd mit spi_read_SRAMframe(addr) oder spi_read_2ndframe() */
|
21 | /* die folgende Art des Einlesens verursacht übermässig Fehler, egal ob 0x02 oder 0x00 als Adresse genutzt wird */
|
22 | if (rec_frame != spi_read_SRAMframe(0x00)) goto Abbruch; // 2nd Frame einlesen und Vergleichen |
23 | /* diese Art des Einlesens verursacht keine Fehler */
|
24 | if (rec_frame != spi_read_2ndframe()) goto Abbruch; // 2nd Frame einlesen und Vergleichen |
25 | |
26 | ....
|
27 | }
|
28 | |
29 | static void initialize_timer4B_us (uint16_t time_us) |
30 | {
|
31 | uint16_t timer4 = TCNT4; // Timer/Counter4 Zähler auslesen |
32 | OCR4B = timer4 + time_us; // Timer 4B mit ...µs bis Output Compare B Flag starten |
33 | TIFR4 |= (1<<OCF4B); // Timer 4 Output Compare B Flag reset |
34 | }
|
35 | |
36 | static void poll_timer4B_CompareMatch (void) |
37 | {
|
38 | while (!((1<<OCF4B) == (TIFR4 & (1<<OCF4B)))) {} // Timer 4 Output Compare B Flag pollen |
39 | }
|
Und hier die beiden Funktionen, um die es geht:
1 | // 2 byte Payload bei Adresse aus den Speicher des RF230 lesen ================
|
2 | static uint16_t spi_read_SRAMframe (uint8_t addr) |
3 | {
|
4 | PORTB &= ~(1<<PB0); // SEL low |
5 | uint16_t two_bytes_read=0; |
6 | SPDR = 0x00; // SPI read SRAMframe |
7 | // do 17 clock-cycles nothing
|
8 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
9 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
10 | SPDR = addr; // Startadresse fürs lesen der bytes |
11 | // do 17 clock-cycles nothing
|
12 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
13 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
14 | SPDR = 0x00; // SPI create SCK |
15 | // do 17 clock-cycles nothing
|
16 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
17 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
18 | two_bytes_read |= (SPDR << 8); // lies & schieb 'first_byte' um 8 Stellen nach links |
19 | SPDR = 0x00; // SPI create SCK |
20 | // do 17 clock-cycles nothing
|
21 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
22 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
23 | two_bytes_read |= SPDR; // lies 'second_byte' |
24 | PORTB |= (1<<PB0); // SEL high |
25 | return (two_bytes_read); // give back 2 bytes |
26 | } // ======================================================================= */ |
27 | |
28 | |
29 | // 1 Frame mit 2 byte Payload aus den Speicher des RF230 lesen ================
|
30 | static uint16_t spi_read_2ndframe (void) |
31 | {
|
32 | PORTB &= ~(1<<PB0); // SEL low |
33 | uint16_t two_bytes_read=0; |
34 | SPDR = 0x20; // SPI read Frame |
35 | // do 17 clock-cycles nothing
|
36 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
37 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
38 | SPDR = 0x00; // SPI create SCK, skip PHR |
39 | // do 17 clock-cycles nothing
|
40 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
41 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
42 | SPDR = 0x00; // SPI create SCK, skip 1st byte |
43 | // do 17 clock-cycles nothing
|
44 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
45 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
46 | SPDR = 0x00; // SPI create SCK, skip 2nd byte |
47 | // do 17 clock-cycles nothing
|
48 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
49 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
50 | SPDR = 0x00; // SPI create SCK |
51 | // do 17 clock-cycles nothing
|
52 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
53 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
54 | two_bytes_read |= (SPDR << 8); // lies & schieb 'first_byte' um 8 Stellen nach links |
55 | SPDR = 0x00; // SPI create SCK |
56 | // do 17 clock-cycles nothing
|
57 | __asm__ __volatile__ (" nop \n nop \n nop \n nop \n nop \n nop \n nop \n" |
58 | "nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n nop \n":: ); |
59 | two_bytes_read |= SPDR; // lies 'second_byte' |
60 | PORTB |= (1<<PB0); // SEL high |
61 | return (two_bytes_read); // give back 2 bytes |
62 | } // ======================================================================= */ |
Grüsse und Danke fürs Lesen