www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATMega8: USART-RX mit Interrupt


Autor: Zenk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich möchte mit einem ATMega8 über die USART Schnittstelle Zeichen lesen 
und das ganze im Interrupt Betrieb. Ein anderer ATMega8 sendet Zeichen, 
was ich mit dem LogicAnalyzer auch überprüft habe. Die Sendefrequenz, 
Parity, Stopbits etc sind natürlich identisch.

Hab schon in anderen Threads gestöbert aber konnte noch nicht finden 
warum das bei mir nicht funktioniert.
Hier der code:
#include <avr/io.h>

#define F_CPU 8000000L 

#include <util/delay.h>
#include <avr/interrupt.h>
#define BAUD 9600L

#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)      //clever runde
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //reale Baudrate

#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)      //Fehler in Promille

#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematischer Fehler in der Baudrate größer 1% und damit zu hoch!
#endif


ISR (USART_RXC_vect) {
  uint8_t dummy;
  dummy = UDR;
  PORTB ^= (1<<PB0);   
}


int main(void)
{
   
   UBRRH = UBRR_VAL >> 8;
   UBRRL = UBRR_VAL & 0xFF;
   
   
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);      //Asynchron 8N1
  UCSRA = (1<<U2X);
  UCSRB = ( 1 << RXEN ) | (1 << RXCIE);
  sei();

  while (1)
  {

  }

  return 0;                     
}

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Jetzt ohne mal deinen Code näher zu betrachten,
du speicherst in
ISR (USART_RXC_vect) {
  uint8_t dummy;
  dummy = UDR;
  PORTB ^= (1<<PB0);   
}

das Datenbyte nur temporär, dann wird es wieder gelöscht.

Du müsstest z.B. ein globales Array definieren und da die Daten 
reinpacken.

z.B.
uint8_t volatile dummy[255];
uint8_t volatile Counter;


Counter=0;
...


while(1)
  {
  if (Counter==200)
    {
    cli(); //nur als Pseudocode zu verstehen
    .... //tu irgendwas mit den Daten, ist alles Fehlerfrei??
    Counter=0;
    ....
    sei();
    }
  }

ISR (USART_RXC_vect) 
{
  dummy[Counter] = UDR;
  Counter++;
  PORTB ^= (1<<PB0);   
}

Autor: Zenk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich lese UDR nur aus damit das Interrupt Flag gelöscht wird, es geht mir 
erstmals nur darum die LED blinken zu sehn die an PB0 hängt ;)

Autor: Kai B. (kaib) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Zenk,
wie wäre es mit dem Initialisieren von PORTB?
den UART haste jetzt schon initialisiert nur PORTB muss auch 
entsprechend konfiguriert werden.

MfG Kai

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK,

dann fehlt nur noch ein
DDRB |= (1<<PB0);

Autor: Zenk (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hehe, man möge mir eine Tischkante reichen ;)

nun jetzt wird der Interrupt nachweislich ausgelöst, aber so ganz das 
erwünschte Ergebnis ist es noch nicht.

Ich hätte jetzt erwartet dass der Interrupt nur pro Byte und nicht pro 
Bit ausgelöst wird.

Denn wenn ich RX und PB0 am LogicAnalyzer anschaue dann sieht das sehr 
ähnlich aus. Sprich wenn sich bei Rx der logische Zustand ändert, tut 
das der beim PB auch. Ich hab mal ein Bild angehängt. Das obere sich 
verändernde Signal ist Rx, das darunter PB0.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also der Interrupt wird auch nur Byteweise ausgelöst!
Da muss was nicht stimmen.

Autor: Kai B. (kaib) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerade getestet: pro Byte ein Interrupt. von dem her würde ich behaupten 
das deine Messung falsch ist.
Lass mal im Interrupt hochzählen und gebe das aus dann siehste das pro 
Byte der Zähler immer um 1 hochzählt.

Autor: Zenk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also wenn ich eine Variable mitzählen lasse kommt dabei raus dass der 
Interrupt ca 1,6 mal zu oft aufgerufen wird.

Das hier ist der Code des anderen µC der die Bytes sendet:
#include <avr/io.h>

#define F_CPU 8000000L 
#include <util/delay.h>
#define BAUD 9600L

#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)      //clever runde
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //reale Baudrate

#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)      //Fehler in Promille

#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematischer Fehler in der Baudrate größer 1% und damit zu hoch!
#endif


int main(void)
{
   DDRB |= (1<<PB0);
   UBRRH = UBRR_VAL >> 8;
   UBRRL = UBRR_VAL & 0xFF;
  int i = 64;
   
   
  UCSRB = (1<<RXEN)|(1<<TXEN);      //UART TX einschalten
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);      //8 data, 2 stop bits
  
  while (1)
  {

    i++;
    if (i>90) i = 65;

    while (!(UCSRA & (1<<UDRE)))      //warten bis Senden möglich
    {
    }   


    UDR = i;                     //schreibt das Zeichen x auf die Schnittstelle
    PORTB ^= (1<<PB0);
    _delay_ms(500);
  }

  return 0;                     
} 

oder kann das Problem am 8MHz Quarz liegen der bei den 9600 Baud einen 
Fehler macht?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>oder kann das Problem am 8MHz Quarz liegen der bei den 9600 Baud einen
>Fehler macht?

Wirklich Quarz?

MfG Spess

Autor: Zenk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Quarz?                Quarz?

ja Quarz.

was?


Damit will ich sagen: Ich hab keine Ahnung worauf du hinaus willst.

Aber zu meinem Problem, der Faktor 1,6 hat sich bei genauerer Messung 
als Faktor 2 herausgestellt und kam dadurch zustande, dass beim lesenden 
µC U2X gesetzt war, beim sendenden nicht. Tja.
Jetzt werden sogar die richtigen Zeichen erkannt...Ich bin begeistert :)

Danke für die Hilfestellung.


PS: Das LogicAnalyzer Bild erklärt sich dudurch leider dennoch nicht.

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.