Forum: Compiler & IDEs Interrupts sperren + Verzögerung


von Miriam (Gast)


Lesenswert?

Hallo,

ich nutze den Codevision-Compiler habe folgenden Code :
1
   
2
PORTD.5 = 1;             
3
#asm("CLI")
4
display_string("Testausgabe",25,40,6); 
5
#asm("SEI") 
6
PORTD.5 = 0;

Die Funktion display_string sendet über die SPI-Schnittstelle Daten an 
das Display und lies das Ack über SPI zurück.

Die SPI-Schnittstelle funktioniert nicht über Interrupt. Alle 50ms wird 
ein Timerinterrupt ausgeführt.

Wenn ich nun den Ausgang D5 mit dem Oszi beobachte, so messe ich, dass 
er für die Ausgabe "Testausgabe" für 10ms High ist. Manchmal aber auch 
für 60ms.

Kann ich nun daraus schließen, dass das Display an der sporadischen 
Verzögerung schuld ist??

von Route_66 (Gast)


Lesenswert?

Hallo!
Nein.

von Peter D. (peda)


Lesenswert?

Miriam schrieb:
> Wenn ich nun den Ausgang D5 mit dem Oszi beobachte, so messe ich, dass
> er für die Ausgabe "Testausgabe" für 10ms High ist. Manchmal aber auch
> für 60ms.

Daran sieht man schön, daß es unklug ist, LCD-Ausgaben in Interrupts 
oder unter Interruptsperre zu machen.
10ms sind nämlich verdammt lang, da können viele andere Interrupts 
verloren gehen.
Die 60ms scheinen, daß Du auch im Interrupt mit PORTD rum machst.


Peter

von Route_66 (Gast)


Lesenswert?

Hallo!
> Die 60ms scheinen, daß Du auch im Interrupt mit PORTD rum machst.

Nicht unbedingt.
Was kann zwischen Zeile 1 und Zeile 2 passieren?
Was passiert nach der Zeile 5, wenn zwischenzeitlioch der Timer 
übergelaufen ist?

von Miriam (Gast)


Lesenswert?

Woher kann ich wissen was passiert wenn der Timer überläuft, eigentlich 
einen Interrupt ausführen möchte, aber nicht darf?

Wie löse ich die Ausgabe am Display geschickter? Soll ich besser auch 
die SPI-Kommunikation über Interrupt lösen?

von Peter II (Gast)


Lesenswert?

Miriam schrieb:
> Woher kann ich wissen was passiert wenn der Timer überläuft, eigentlich
> einen Interrupt ausführen möchte, aber nicht darf?

steht im Datenblatt, aber ich würde einfach davon ausgehen das ebend 
nichts passiert. Der Timer wird deswegen nicht stehen bleiben.

von Karl H. (kbuchegg)


Lesenswert?

Miriam schrieb:

> Wie löse ich die Ausgabe am Display geschickter?

Geschickter als was?
Das da oben ist ja nicht wirklich ein Codeausschnitt, mit dem man 
irgendwas anfangen kann.

von Peter D. (peda)


Lesenswert?

10ms für das LCD ist auch viel zu lang.
Ein Zeichen dauert max 50µs, Du gibst 11 aus, d.h. nach 550µs sollte es 
fertig sein. Es sind aber 9450µs mehr.
Da ist also irgendwas faul in der LCD-Routine.


Peter

von Route_66 (Gast)


Lesenswert?

Hallo!
> Woher kann ich wissen was passiert wenn der Timer überläuft, eigentlich
> einen Interrupt ausführen möchte, aber nicht darf?

Der Interrupt wird sofort nach Zeile 4 ausgeführt, noch bevor Du in 
Zeile 5 den Ausgang PORTD.5 zurücksetzt! Der Timer-INT kann aber auch 
schod nach der ersten Zeile zuschlagen, dann hast Du PORTD.5 schon 
gesetzt und der INT wird erst in der zweiten Zeile verboten.
Also: Zeitmessungen komplett! in CLI/SEI schachteln.
1. und 2. sowie 4. und 5. Zeile tauschen.

von Route_66 (Gast)


Lesenswert?

Hallo!
@peda Woher weist Du, welches Display wie über SPI angeschlossen ist?
Miriam hat ja nicht einmal von LCD geschrieben.

von Route_66 (Gast)


Lesenswert?

Ergänzung: Natürlich sind 10 ms für eine Displayausgabe viiiieeeel zu 
lang.

von Miriam (Gast)


Lesenswert?

Die Ausgabe in der iLCD-Routine funktioniert nach folgendem Schema:
1
while ( (ack != 0x06) && (run <= MAX_SPI_RUN) )
2
{
3
spi(DC1);                
4
spi(len);                 spi(ESC);                spi('Z');                
5
spi('L');                 spi(x);                  
6
spi(y);                
7
for (i = 0; i < (len-6); i++)   
8
 {
9
  sum = sum + (int)str[i];
10
  spi(str[i]);
11
 }
12
sum = sum + DC1 + (int)len + ESC + 'Z' + 'L' + x + y + NUL;
13
bcc = (unsigned char) (sum % 256);
14
spi(NUL);
15
spi(bcc);
16
      
17
delay_us(100);
18
ack = spi(0x00);
19
versuche++; 
20
}

Die SPI-Kommunikation ist auf eine Datenrate von 115,195 kHz 
eingestellt. Laut Datenblatt des Displays kann unter 100kHz im "NonStop" 
Betrieben werden, ab 100 kHz sollte man zwischen den einzelnen Bytes 
min. 100usec Pause lassen. Wenn ich diese zwischen die einzelnen 
spi-Sende Befehle einfüge, braucht das Display jedoch wesentlich länger.

von Dosmo (Gast)


Lesenswert?

Du mußt in Zeile 58 ein
POKE 0xD00F
einbauen.

Im Ernst: Du wirst keine gescheite Analyse Deines Problems bekommen, 
wenn Du nur ein paar Brocken von Deinem Programm rausrückst.
Wo ist der Timer-Interrupt?
Wie sieht main() aus?

von Peter D. (peda)


Lesenswert?

Miriam schrieb:
> Die Ausgabe in der iLCD-Routine funktioniert nach folgendem Schema:

Ich vermute mal, das ist ein eDIPTFT43-A.

Daß das wirklich funktionieren soll, kann ich mir nicht vorstellen.

Die korrekte Methode ist, man fragt vorher ab, ob für das Kommando 
genügend Platz im Puffer ist. Und dann schickt man es ab und kriegt ACK 
zurück.

Es kann sein, daß das dauernde Senden, bis es zufällig mal klappt, 
Schuld daran ist, daß es so lange dauert.


Peter

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.