Hi,
erstmal vielen Dank für die ausführlichen Antworten! Bitte lest erst den
ganzen Text von mir. Ich habe unten einen aktualisierten Code, wodurch
vieles einfacher zu verstehen ist.
Lothar M. schrieb:
>> receivedByte |= (receivedBit << 0);
> Ähm, was tut diese Zeile?
Diese Zeile soll das erste aus 8 Datenbits einlesen. Danach werden dann
die restlichen 7 Datenbits gelesen. (Hier habe ich noch das Paritybit
vergessen.)
Lothar M. schrieb:
> Dieser Code ist auf einem AVR extrem ungünstig, weil der nämlich keinen
> Barrelshifter hat
Ok, das wusste ich nicht, bzw. ich habe mir darüber überhaupt keine
Gedanken gemacht. Ich werde mir das noch einmal genau anschauen, um es
zu verstehen. Das Einsparungspotenzial scheint ja immens zu sein.
Lothar M. schrieb:
> Was ergibt das in Echtzeit? Eher 1us oder eher 1ms?
In Echtzeit ergibt das nach folgender Rechnung 24,8us:
1/4 * 372/3750000 = 2,48 * 10^-5 s = 0,0000248s = 24,8us
Kann es sein, dass mein Code zu langsam ist und ich deshalb die
Wartezeiten falsch angepasst habe?
Lothar M. schrieb:
> Denn es gilt ja X=Y/2.
Muss es nicht X = Y + Y/2 sein? Ich möchte ja 1,5 Bits abwarten. Das
Startbit und bis zur Mitte des ersten Bits. (X=Y/2 gilt für den Code in
diesem Beitrag.)
Lothar M. schrieb:
> Quarzfrequenz
3,75MHz
Peter D. schrieb:
> Ich hab keine Ahnung, was etu oder 372 bedeuten soll.
ETU bedeutet elementary time unit und beschreibt nur die Länge eines
Bits. 372 ist einfach eine Konstante.
Nochmal zum Protokoll:
Ein Bit hat die Länge von einer etu (in diesem Fall 24,8us). Es gibt ein
Startbit, 8 Datenbits und ein Paritybit. Es soll immer zur Mitte der
Bits "gelesen" werden. Siehe Bild.
Mir sind selber noch ein paar Fehler aufgefallen, nachdem Lothar nach
der einen Zeile gefragt hat. Mein aktualisierter Code sollte viel besser
verständlich sein:
1 | uint8_t receiveByte(int etu)
|
2 | {
|
3 | uint8_t receivedByte = 0x00;
|
4 | uint8_t receiveMask = 0x01;
|
5 | volatile int8_t parityCounter = 0;
|
6 | startBitFlag = 0;
|
7 | PCICR |= (1 << PCIE1); //Pin Change Interrupt anschalten
|
8 | PCMSK1 |= (1 << PCINT14);
|
9 | while(startBitFlag != 1); //warte auf Startbit
|
10 | startBitFlag = 0;
|
11 | PCICR = 0x00; //Pin Change Interrupt ausschalten
|
12 | PCMSK1 = 0x00;
|
13 | receiveLock = 1; //receiveLock aktivieren (warten bis erstes Bit vorbei, dann nächstes einlesen)
|
14 | startTimer2(Y/2);
|
15 | while(receiveLock); //Abwarten bis Mitte des Startbits
|
16 | receiveLock = 1;
|
17 | startTimer2(Y); //Weiter warten bis zur Mitte des 1. Datenbits
|
18 | for (int i = 0; i < 8; i++) //8 Bits lesen (8 Datenbits)
|
19 | {
|
20 | while(receiveLock);
|
21 | receivedByte |= receiveMask;
|
22 | receiveMask <<= 1; // <<<< Maske schieben
|
23 | if(receivedBit == 1)
|
24 | parityCounter++;
|
25 | receiveLock = 1;
|
26 | }
|
27 | while(receiveLock); //Paritybit empfangen
|
28 | stopTimer2();
|
29 | if(receivedBit) //Letztes Bit ist das Paritybit
|
30 | {
|
31 | parityCounter++;
|
32 | }
|
33 | if (parityCounter % 2)
|
34 | {
|
35 | uart0_putstring("Error 1: Parity Check failed.\n");
|
36 | }
|
37 | return receivedByte;
|
38 | }
|
Ich denke mit der aktualisierten Fassung, habe ich auch Lothars
Anmerkungen zu dieser Zeile: "receivedByte |= (receivedBit << 0);" und
die Anmerkung "X=Y/2" verstanden und verbessert.
Gruß Niclas