Forum: Mikrocontroller und Digitale Elektronik Atmega 162 - UART/Interrupt geht nicht


von Steffan K. (martin09)


Lesenswert?

Hi :)
Ich versuche mit dem Atmega 162 einen String über UART zu empfangen.
Zurzeit löst aber nichtmal der Interrupt aus.Sitze schon seit 3Tagen 
dran und finde den Fehler einfach nicht.Hab im Forum leider nichts 
gefunden,was mir helfen würde und das UART Tutorial hab ich auch schon 
gelesen.
Hättet ihr vlt eine Idee woran es liegen könnte?

UART Initialisierung
1
void initusart1(void)
2
{
3
unsigned char x;
4
#ifdef UBRR1L
5
  UBRR1L = (TAKT / (16ul * BAUD))-1;
6
  UCSR1B |=(1<<TXEN1)|(1<<RXEN1);
7
  UCSR1C |=(1<<URSEL1)|(1<<UCSZ11)|(1<<UCSZ10);
8
#else
9
  UBRR = (TAKT / (16 * BAUD))-1;
10
  UCR |=(1<<TXEN)|(1<<RXEN);
11
#endif
12
  x=UDR1;
13
}

UART empfangen
1
unsigned char empf1 (void)
2
{
3
#ifdef UCSR1A
4
  while(!(UCSR1A & (1<<RXC1)));
5
#else
6
  while(!(USR & (1<<RXC)));
7
#endif
8
return UDR1;}

Interrupt
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <string.h>
5
#define TAKT 8000000UL 
6
#define BAUD 9600UL  
7
8
9
ISR(SIG_USART1_RECV){  //habs auch schon mit ISR(USART1_RXC_vect)  versucht          
10
11
cli();
12
          
13
strcpy (test,"test");
14
15
sei();
16
}

Main
1
int main(void)
2
{
3
4
DDRB = 0x00;
5
initusart1();    // UART initialisieren  
6
UCSR1B |= (1<<RXCIE1);  //Interrupt freigeben UART1
7
sei();      //Interrupt freigeben Global
8
return 0;
9
}

Am Prozessor hängt ein externer Quarz von 8MHz
Der String wird mit einer Baudrate von  9600 gesendet(Datenbyte 
8,Stoppbits 1)

Ich hoffe ich habe keine wichtigen Informationen vergessen.
Vielen Dank schonmal im voraus!

Gruss

von *.* (Gast)


Lesenswert?

Ich würde in "main" nach dem "sei()" eine Endlosschleife einfügen, sonst 
ist das Progrämmchen ja gleich "durch".

von Stefan E. (sternst)


Lesenswert?

Beim Verlassen von main werden die Interrupts global deaktiviert, also 
Endlosschleife einfügen (wie auch schon vom Vorboster geschrieben).

Desweiteren nimm die cli und sei aus dem Interrupt raus. Die sind nicht 
nur unnötig, sondern sogar kontraproduktiv.

Und da du im Interrupt das Empfangsregister nicht aussließt, kannst du 
dich schon mal auf eine Art "Endlosinterrupt" freuen.

von Steffan K. (martin09)


Lesenswert?

Also Endlosschleife ist drin und cli und sei draußen.

Könntest du mir bitte das mit dem Empfangsregister nochmal näher 
erläutern?
Ich wäre ja froh wenn der Interrupt überhaupt mal auslösen würde.

Gruss

von Stefan E. (sternst)


Lesenswert?

Steffan Kleritchi wrote:

> Könntest du mir bitte das mit dem Empfangsregister nochmal näher
> erläutern?

Du musst im Interrupt das Datenregister (UDR1) auslesen. Dadurch wird 
das Interruptflag gelöscht. Ansonsten würde der Interrupt nach Verlassen 
der ISR sofort wieder auslösen.

> Ich wäre ja froh wenn der Interrupt überhaupt mal auslösen würde.

Wie stellst du fest, dass er nicht auslöst?

von Steffan K. (martin09)


Lesenswert?

> Wie stellst du fest, dass er nicht auslöst?

In der If-Schleife im Main,ist ein String vergleich,der mir den "test" 
vom Interrupt mit dem "test1" vergleicht und eine LED einschaltet.Wenn 
ich den Befehl "strcpy (test,"test");" aus dem Interrupt raushole und 
ins main schreibe funktioniert das auch soweit,die LED geht an.
Sprich,..Interrupt löst aus,test wird in den String test geschreiben,er 
beendet den Interrupt,test wird mit test1 verglichen und die LED geht 
an.So zumindest mein Plan.
Normal steht im Interrupt folgendes,zum einlesen des Strings.
1
          empfang = empf1();
2
          if(empfang=='X') //Anfangskennung des gesendeten Strings        
3
            {
4
            test[0] = empfang;
5
            for(zahl=1;zahl<=10;zahl++) 
6
              {            
7
              test[zahl] = empf1();
8
              }
9
    
10
            }

Wie lese ich denn das UDR1 aus?Reicht da ein Befehl z.B. X = UDR1; ?Sry, 
für die blöde Frage,aber arbeite zum ersten mal mit der 
UART-Schnittstelle.

Gruss

von Stefan E. (sternst)


Lesenswert?

Um zu testen, ob der Interrupt überhaupt auslöst, solltest du den 
einfachsten Weg gehen, um zusätzliche Fehlerquellen auszuschließen. 
Schalte zum Testen also einfach die LED direkt im Interrupt an.

> Wie lese ich denn das UDR1 aus?
> Reicht da ein Befehl z.B. X = UDR1;

Ja.

von Steffan K. (martin09)


Lesenswert?

Stimmt,warum einfach wenns auch schwer geht ^^.
Also ich schalte die LEDs jetzt im Interrupt ein.
Das UDR1 Register lese ich auch aus.
Leider löst der Interrupt trotzdem nicht aus.

Gruss

von Stefan E. (sternst)


Lesenswert?

1
UCSR1C |=(1<<URSEL1)|(1<<UCSZ11)|(1<<UCSZ10);
Hier steht im Augenblick quasi:
1
UCSR1C = UBRRH | (1<<URSEL1)|(1<<UCSZ11)|(1<<UCSZ10);
Da UBRRH null sein sollte, stört es nicht weiter, aber ändere es doch 
besser von "|=" in "=".

Du wirst wohl die übliche Checkliste abarbeiten müssen. Angefangen 
damit, ob der Prozessor überhaupt mit dem erwarteten Takt läuft (ist 
vielleicht noch der interne RC-Oszillator aktiv?). Dann die Hardware 
checken, Verkabelung, Pegelwandler, etc (kommen überhaupt irgendwelche 
Signale beim µC an?).

von martin09 (Gast)


Lesenswert?

so,hab jetzt nochmal alles durchgemessen.
Passt alles bis auf den Quarz,..Dieser schwingt jetzt nur noch mit 0,125 
MHz anstatt mit den ursprünglichen 8MHz.
Weis vlt jemand an was das liegen könnte?

Gruss

von Johannes M. (johnny-m)


Lesenswert?

CKDIV8-Fuse gesetzt?

von martin09 (Gast)


Lesenswert?

nein.wenn sie gesetzt ist wird der takt doch durch 8geteilt oder? Dann 
hätte ich ja noch zumindest 1Mhz.Aber von 8Mhz auf 0,125Mhz ist das ja n 
Faktor von 64.
Oder hab ich das mit der Fuse falsch verstanden?

Gruss

von spess53 (Gast)


Lesenswert?

Hi

>,..Dieser schwingt jetzt nur noch mit 0,125 MHz anstatt mit den >ursprünglichen 
8MHz.

Womit gemessen? Wenn DSO, evtl. mal Zeitbasis wechseln.

CKDIV8 hat nichts mit dem Oszillator zu tun.

MfG Spess

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.