mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Software UART Empfang (ATmega8)


Autor: Mento (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche momentan - auf einem ATmega8 - mit einem Software-UART 
Daten von einem anderen ATmega8 zu empfangen und auf PortC auszugeben, 
allerdings kommt nur Kauderwelsch raus.
Die Baudrate ist genau ein Timer durchlauf mit Vorteiler 1024, bei 16 
MHz Takt. Also sehr sehr langsam.

Hier der Code:

void init_SoftUART(void)
{
  MCUCR  |= (1<<ISC01);      //Bei Fallender Flanke.
  GICR  |= (1<<INT0);        //INT0 aktivieren.
  GIFR   = (1<<INTF0);      //Interrupt Flag zur sicherheit löschen.

  //Timer2 für Software-UART.
  TCCR2 = (1<<CS02) | (1<<CS00); //Vorteiler auf 1024.

}


ISR (INT0_vect)
{
  TCNT2 = 170; //Timer2 auf die Mitte der Bits sezten.
  GICR  &= ~(1<<INT0); //INT0 deaktivieren.
  TIFR = (1<<TOV2);
  TIMSK |= (1<<TOIE2);  //Timer2 interrupt aktivieren.
}


ISR (TIMER2_OVF_vect)
{
  static int8_t curBit = -1;
  static uint8_t receiveByte = 0;
  static uint8_t curByte = 0;

  switch (curBit) {
    case -1:
      break;
    case 8:
      curBit = -2;

      PORTC = receiveByte;

      UARTreceiveBytes[curByte] = receiveByte;
      receiveByte = 0;

      curByte = !curByte;

      GICR  |= (1<<INT0); //INT0 aktivieren.
      TIMSK &= ~(1<<TOIE2);  //Timer2 interrupt deaktivieren.
      break;
    default:
      receiveByte >>= 1;
      if (PINB &= (1<<PD2)) {
        receiveByte |= (1<<7);
      }
      break;
  }
  curBit++;
}


Könnt ihr mir helfen oder müsst ihr noch mehr wissen?
Ach ja: Das senden Funktioniert einwandfrei, hab ich mit einem Oszi 
überprüft.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
      if (PINB &= (1<<PD2)) {
Das "&=" würde ich nochmal überdenken. ;-)

Autor: Mento (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das "=" Zeichen hab ich irgendwie übersehen, allerdings funktioniert 
es ohne es auch noch nicht.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mento schrieb:
> Ja, das "=" Zeichen hab ich irgendwie übersehen, allerdings funktioniert
> es ohne es auch noch nicht.

Beim Wiederaktivieren des INT0 Interrupts muss auch das entsprechende 
Flag gelöscht werden.

Wenn es dann immer noch nicht geht, poste bitte mal, was genau gesendet 
und was genau statt dessen empfangen wird.

PS: Wieso ist eigentlich 170 die Mitte?

Autor: Mento (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es funktioniert noch immer nicht. Das mit 170 war zu Testzwecken, 
ursprünglich ist dort 128 gestanden und steht auch jetzt wieder dort.

Hier noch der aktuelle Code:
void init_SoftUART(void)
{
  MCUCR  |= (1<<ISC01);      //Bei Fallender Flanke.
  GICR  |= (1<<INT0);        //INT0 aktivieren.
  GIFR   = (1<<INTF0);      //Interrupt Flag zur sicherheit löschen.
  
  //Timer2 für Software-UART.
  TCCR2 = (1<<CS02) | (1<<CS00); //Vorteiler auf 1024.
  
}


ISR (INT0_vect)
{
  TCNT2 = 128; //Timer2 auf die Mitte der Bits sezten.
  GICR  &= ~(1<<INT0); //INT0 deaktivieren.
  TIFR = (1<<TOV2);
  TIMSK |= (1<<TOIE2);  //Timer2 interrupt aktivieren.
}


ISR (TIMER2_OVF_vect)
{
  static int8_t curBit = -1;
  static uint8_t receiveByte = 0;
  static uint8_t curByte = 0;
  
  switch (curBit) {
    case -1:
      break;
    case 8:
      curBit = -2;
      
      PORTC = receiveByte;
      
      UARTreceiveBytes[curByte] = receiveByte;
      receiveByte = 0;
      
      curByte = !curByte;
      
      GIFR = (1<<INTF0);
      GICR  |= (1<<INT0); //INT0 aktivieren.
      TIMSK &= ~(1<<TOIE2);  //Timer2 interrupt deaktivieren.          
      break;
    default:
      receiveByte >>= 1;
      if (PINB & (1<<PD2)) {
        receiveByte |= (1<<7);
      }
      break;
  }
  curBit++;
}

Und noch der Code des Senders:
ISR (TIMER2_OVF_vect) {
  static int8_t curBit = -1;
  if (UARTsendBytes[0]) {
    switch (curBit) {
      case -1: //Start-Bit
        UARTPort &= ~(1<<UARTPin);
        break;
      case 8: //Stop-Bit
        UARTPort |= (1<<UARTPin);
        break;
      default: //Daten-Bit
        if (UARTsendBytes[0] & (1<<curBit)) {
          UARTPort |= (1<<UARTPin);
        } else {
          UARTPort &= ~(1<<UARTPin);
        }
        break;
    }
    curBit++;
    if (curBit > 8) {
      curBit = -1;
      
      UARTsendBytes[0] = UARTsendBytes[1]; //Nächstes Byte zum versenden. 
      UARTsendBytes[1] = 0;
    }
  }
}

Es werden jeweils zwei Bytes versandt, das erste gibt die Art der 
Nachricht an und das zweite die Daten.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mento schrieb:

> Es werden jeweils zwei Bytes versandt, das erste gibt die Art der
> Nachricht an und das zweite die Daten.

Ich will nicht wissen, was die Daten bedeuten (das ist völlig 
irrelevant), ich will wissen, wie die Daten aussehen.
Was wird empfangen, wenn du 0x55 sendest?
Was wird empfangen, wenn du 0xf0 sendest?
Was wird empfangen, wenn du 0x0f sendest?

Autor: Mento (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tut mir leid, ich hab dich falsch verstanden.

Hier die Ergebnisse (ich hab jeweils viermal gesendet, und jedes mal ist 
etwas anderes herausgekommen):
Bei 0x55:
100011
011111
000111
111111

Bei 0xF0:
001111
100011
011111
110001

Bei 0x0F:
100011
100001
111000
001111

Ich glaub aber nicht, dass du daraus schlau wirst.
Ich hab nur immer die ersten 6 Bits da PortC nicht mehr Pins hat.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das sieht ja eher zufällig aus. Sicher, dass du überhaupt den richtigen 
Pin einließt? Die dazugehörige Zeile sieht ja auch etwas verdächtig aus.
if (PINB & (1<<PD2)) {
Tatsächlich einlesen tust du PB2. Dem Code nach könntest du aber auch 
eigentlich PD2 einlesen wollen.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallöchen,

was soll das

curByte = !curByte;

bewirken? Eine logische Negation deines Emfangszählers!?!

Und

(PINB & (1<<PD2))

ist zwar nicht verkehrt, aber Port B und ein Pin von Port D sollte man 
nicht mischen!
Außerdem, kann es sein, dass deine SoftUART am Port D angeschlossen ist?


Gruß

Autor: Mento (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab es jetzt hinbekommen, es waren mehrere Sachen falsch. Unter 
anderem das mit PinB statt PinD und auch der Vorteiler des Timers da ich 
zuerst Timer0 verwendet hatte, bei welchem der Vorteiler anders ist als 
beim Timer2.

Hier der Code, falls es irgendjemanden interessiert:
void init_SoftUART(void)
{
  MCUCR  |= (1<<ISC01);      //Bei Fallender Flanke.
  GICR  |= (1<<INT0);        //INT0 aktivieren.
  GIFR   = (1<<INTF0);      //Interrupt Flag zur sicherheit löschen.
  
  //Timer2 für Software-UART.
  TCCR2 = (1<<CS22) | (1<<CS21) | (1<<CS20); //Vorteiler auf 1024.
  
}


ISR (INT0_vect)
{
  TCNT2 = 128; //Timer2 auf die Mitte der Bits sezten.
  GICR  &= ~(1<<INT0); //INT0 deaktivieren.
  TIFR = (1<<TOV2);
  TIMSK |= (1<<TOIE2);  //Timer2 interrupt aktivieren.
}


ISR (TIMER2_OVF_vect)
{
  static int8_t curBit = -1;
  static uint8_t receiveByte = 0;
  static uint8_t curByte = 0;
  
  switch (curBit) {
    case -1:
      break;
    case 8:
      curBit = -2;
      
      UARTreceiveBytes[curByte] = receiveByte;
      receiveByte = 0;
      
      curByte = !curByte;
      
      GIFR = (1<<INTF0);
      GICR  |= (1<<INT0); //INT0 aktivieren.
      TIMSK &= ~(1<<TOIE2);  //Timer2 interrupt deaktivieren.          
      break;
    default:
      receiveByte >>= 1;
      if (PIND & (1<<PD2)) {
        receiveByte |= (1<<7);
      }
      break;
  }
  curBit++;
}

Danke an euch alle.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nochmal die Frage:
Was soll das

curByte = !curByte;

bewirken? Eine logische Negation deines Emfangszählers!?!

Ich halte diese Zeile für falsch, mindestens aber gefährlich da 
'curByte' static ist und als Arrayindex benutzt wird.

Meines Wissens ist !0 im C "Quasi" Standard nicht eindeutig definiert 
außer, das es nicht Null ist. Es kann also 0x01 oder 0xFF oder sonstwas 
sein, ganz nach belieben des Compilers.

Oder liege ich falsch, mal so an die wahren C Experten gerichtet?

Gruß

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:

> Ich halte diese Zeile für falsch, mindestens aber gefährlich da
> 'curByte' static ist und als Arrayindex benutzt wird.

Sie ist weder falsch noch gefährlich. Sie sorgt dafür, dass immer 
abwechselnd UARTreceiveBytes[0] und UARTreceiveBytes[1] beschrieben 
werden.

> Meines Wissens ist !0 im C "Quasi" Standard nicht eindeutig definiert
> außer, das es nicht Null ist.

Ich weiß ja nicht, was bei dir dieses "Quasi" ist, aber im richtigen 
Standard ist das Ergebnis des !-Operators eindeutig definiert.

Zitat C-Standard ISO99:
The result of the logical negation operator ! is 0 if the value of
its operand compares unequal to 0, 1 if the value of its operand
compares equal to 0.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.