Forum: Mikrocontroller und Digitale Elektronik UART löst keinen Interrupt aus?


von Daniel (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem:

Ich arbeite mit dem C8051F120 schon eine lange Zeit und nie gab es 
Probleme mit der UART0 Schnittstelle. Jetzt habe ich mal ein komplett 
neues Projekt angefangen und bin der Meinung alles wichtige eingestellt 
zu haben, aber aus irgend einem Grund wird der Interrupt 4 für die UART0 
nicht ausgelöst, wenn ich Daten an den µC sende.

Folgendes habe ich alles schon Probiert:

- Timer Einstellungen sind OK, für Timer 1 als Baudratengenerator für 
UART
- Interrupt Enable Bits habe ich überprüft: ES0 = 1 und EA = 1
- Ausserdem habe ich Daten vom µC an den PC gesendet, diese kommen auch 
mit der eingestellten Baudrate (115200) ordentlich am PC an.

Nun meine Frage an euch: Woran kann es noch liegen, dass der Interrupt 
nicht ausgelöst wird?

Viele Grüße,
Daniel

von Nico (nico123)


Lesenswert?

Allgemeine Interruptfreigabe vergessen?

von Anhalter (Gast)


Lesenswert?

Daniel schrieb:
> Nun meine Frage an euch: Woran kann es noch liegen, dass der Interrupt
> nicht ausgelöst wird?

An Zeile 42 Deines Programms.

von Daniel (Gast)


Lesenswert?

Nico ... schrieb:
> Allgemeine Interruptfreigabe vergessen?

Eigentlich ist diese über das EA bit mit 1 gesetzt?

von Route_66 H. (route_66)


Lesenswert?

@ Nico
> Allgemeine Interruptfreigabe vergessen?
Daniel schrieb
> EA = 1

von Daniel (Gast)


Lesenswert?

Ich habe parallel dazu eine zweite Interrupt-Routine für den PCA 
Überlauf, diese wird in regelmäßigen Abständen auch ausgeführt.

von Daniel (Gast)


Lesenswert?

Was ich auch noch getestet habe ist: Ich habe mal das RI0 bit in der 
Main-Routine auf 1 gesetzt, dann wurde der Interrupt auch ausgelöst, nur 
beim Empfangen von Daten über die UART wird dieses Bit aus irgend einem 
Grund nicht gesetzt.

von Nico (nico123)


Lesenswert?

Löscht Du das Interrupt-Flag (RI0)?

von Daniel (Gast)


Lesenswert?

Nico ... schrieb:
> Löscht Du das Interrupt-Flag (RI0)?

In der Interrupt-Routine ja, falls es gesetzt war - das wird vorher 
überprüft.

Hintergrund: Bei diesem Controller wird die UART Interrupt Routine bei 
erfolgreichem senden und erfolgreichem empfangen aufgerufen.

von Nico (nico123)


Lesenswert?

Und der Empfänger ist auch wirklich aktiv?
Zeig doch mal deinen Code!

von Daniel (Gast)


Lesenswert?

Nico ... schrieb im Beitrag #2851578:
> S. 154 Dat

Nein, aber ich werds gleich mal probieren. Bisher war das eigentlich 
nicht notwendig.

von Nico (nico123)


Lesenswert?

Den Post habe ich gelöscht, das gilt nur fürs löschen des EA-Bits!

von Daniel (Gast)


Lesenswert?

Ok, hier mal ein bischen Code:
1
void Timer_Init()
2
{
3
  SFRPAGE   = TIMER01_PAGE;
4
  TCON      = 0x40; // Timer 1 enabled
5
  TMOD      = 0x20; // Timer 1 = Mode 2: 8-bit counter/timer with auto-reload
6
  CKCON     = 0x10; // Timer 1 uses the system clock
7
  TH1       = 0xD0; // Reloadwert: -(88473600 / 115200 / 16)
8
}
9
10
void UART_Init()
11
{
12
  SFRPAGE   = UART0_PAGE;
13
  SCON0     = 0x50; // Mode 1: 8-Bit UART, Variable Baud Rate
14
        // UART0 reception enabled
15
  
16
  SSTA0     = 0x10; // UART0 baud rate divide-by-two disabled
17
}
18
19
static void ISR_UART (void) interrupt 4
20
{
21
  if(RI0)
22
  {
23
    RI0=0;
24
  }
25
}
26
27
void main()
28
{
29
  // Initialisierung
30
  Init_Device(); // --> Timer_Init() & UART_Init()
31
32
  SET_SFRPAGE (LEGACY_PAGE);
33
  ES0 = 1;
34
  EA = 1; // Alle Interrupts einschalten  
35
  
36
  // Main-Loop
37
  while(1)
38
  {
39
40
  }
41
}

Was ich noch dazu sagen muss - vielleicht hilft das ja weiter - es ist 
ein externer CMOS mit 29,4912 MHz angeschlossen und dieser wird mit der 
PLL x3 multipliziert, so dass ein SYSCLK von 88473600 Hz am Timer 
ankommt.

Hier noch der Code zur Initialisierung der PLL:
1
void Oscillator_Init()
2
{
3
    int i = 0;
4
    SFRPAGE   = CONFIG_PAGE;
5
    OSCXCN    = 0x20;
6
    PLL0CN    = 0x04;
7
    CCH0CN    &= ~0x20;
8
    SFRPAGE   = LEGACY_PAGE;
9
    FLSCL     = 0xB0;
10
    SFRPAGE   = CONFIG_PAGE;
11
    CCH0CN    |= 0x20;
12
    PLL0CN    |= 0x01;
13
    PLL0DIV   = 0x01;
14
    PLL0FLT   = 0x01;
15
    PLL0MUL   = 0x03;
16
    for (i = 0; i < 15; i++);  // Wait 5us for initialization
17
    PLL0CN    |= 0x02;
18
    while ((PLL0CN & 0x10) == 0);
19
    CLKSEL    = 0x22;
20
    OSCICN    &= ~0x80;
21
}

von Nico (nico123)


Lesenswert?

Wenn das Senden von Daten funktioniert, dann sind die 
Timer-Einstellungen ja okay!
Woher weiß Du, dass kein Interrupt kommt? Du tust ja nix in der ISR!

von Daniel (Gast)


Lesenswert?

Nico ... schrieb:
> Wenn das Senden von Daten funktioniert, dann sind die
> Timer-Einstellungen ja okay!
> Woher weiß Du, dass kein Interrupt kommt? Du tust ja nix in der ISR!

Ich hab mit dem Debug-Adapter ein Haltepunkt bei RI0 = 0; gesetzt, es 
wird aber niemals dort angehalten. Falls das im Debug Modus nicht 
funktioniert, habe ich ausserdem nach dieser Stelle mal eine LED auf der 
Platine eingeschaltet, das ist aber auch niemals passiert.

Und wie gesagt, ich habe dieses Bit (RI0) mal von Hand auf 1 gesetzt, da 
hält dann auch der Code im Debug Modus an dieser Stelle an.

Ich habe absolut keine Idee, was jetzt gerade schief läuft.

von Nico (nico123)


Lesenswert?

Der Port ist auch richtig zugewiesen und verbunden?

von Georg G. (df2au)


Lesenswert?

Frag mal Fehlerbits ab (sofern vorhanden). Nicht, dass der UART laufend 
Frame Error oder Parity Error produziert. Und schau dir den 
Assemblercode an. Möglich, dass der Compiler entscheidet, dass in der Rx 
Routine nichts benötigt wird und sie wegoptimiert. Der Keil ist da 
gnadenlos.

von Daniel (Gast)


Lesenswert?

Nico ... schrieb:
> Der Port ist auch richtig zugewiesen und verbunden?

Ja ich denke schon, ich hab die Crossbar Konfiguration aus meinem alten 
Projekt übernommen, es ist auch die gleiche Elektronik.

Und wenn ich auf diese Elektronik die alte Firmware aufspiele, 
funktioniert die UART auch. Ich habe schon den kompletten Code an den 
relevanten Stellen verglichen - er ist absolut Identisch - aber 
irgendwas will nicht funktionieren.

Kann es eventuell sein, dass ich irgend eine Compiler-Einstellung 
vergessen oder übersehen habe?

von Daniel (Gast)


Lesenswert?

Georg G. schrieb:
> Frag mal Fehlerbits ab (sofern vorhanden). Nicht, dass der UART laufend
> Frame Error oder Parity Error produziert. Und schau dir den
> Assemblercode an. Möglich, dass der Compiler entscheidet, dass in der Rx
> Routine nichts benötigt wird und sie wegoptimiert. Der Keil ist da
> gnadenlos.

Hallo Georg,

das iss natürlich noch ne gute Idee (mit dem wegoptimieren).
Das sehe ich mir gleich mal an, das kann gut möglich sein, obwohl ich im 
Map-File die Routine als Segment sehen kann.

von Daniel (Gast)


Lesenswert?

Daniel schrieb:
> Georg G. schrieb:
>> Frag mal Fehlerbits ab (sofern vorhanden). Nicht, dass der UART laufend
>> Frame Error oder Parity Error produziert. Und schau dir den
>> Assemblercode an. Möglich, dass der Compiler entscheidet, dass in der Rx
>> Routine nichts benötigt wird und sie wegoptimiert. Der Keil ist da
>> gnadenlos.
>
> Hallo Georg,
>
> das iss natürlich noch ne gute Idee (mit dem wegoptimieren).
> Das sehe ich mir gleich mal an, das kann gut möglich sein, obwohl ich im
> Map-File die Routine als Segment sehen kann.

also im Debug Modus ist Assembler Code für diese Routine vorhanden und 
Frame oder Parity Errors sind da auch keine.

von Jim M. (turboj)


Lesenswert?

Blöde Frage, aber den Watchdog hast Du ausgeschltet?

von Daniel (Gast)


Lesenswert?

Jim Meba schrieb:
> Blöde Frage, aber den Watchdog hast Du ausgeschltet?

Ja:
1
void Reset_Sources_Init()
2
{
3
  WDTCN    = 0xDE;
4
  WDTCN    = 0xAD;  // disable Watchdog
5
6
  SET_SFRPAGE (LEGACY_PAGE);
7
  RSTSRC  = RSTOPTIONS;   // enable reset sources
8
}

von Daniel (Gast)


Lesenswert?

Danke an alle,

die mir Tips zum suchen gegeben haben.

Ich habe den Fehler jetzt gefunden.

Der Tip mit dem Reset hat mich auf eine Idee gebracht.

Ihr konntet das nicht wissen, aber ich will euch mal das Problem 
erläutern.

Um in bestimmten Situationen Strom zu sparen, ist an meiner Elektronik 
zwischen Reset-Pin und Rx-Leitung der UART ein Schalter.

Damit kann man den Controller komplett runter fahren und ihn dann über 
die Rx Leitung wieder aufwecken.

Mein Fehler war einfach nur, dass ich vergessen habe diese Verbindung 
beim Initialisieren der Elektronik zu unterbrechen, somit kam nie ein 
Signal bis zum Controller, da dieser beim Datenemfang gleich wieder 
resettet wurde.


Schönes Wochenende wünsche ich euch
und nochmals vielen Dank.

Daniel

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.