interrupt-reihenfolge und timingproblem für pic16fxxx

Gast #3548793
Lesenswert?

Hallo

ich nutze den ccs c Compiler v4.128  und habe
für einen Zeitmesser ein gängiges Beispiel
hergenommen.
Das Beispiel funktioniert auch wunderbar, nur
wenn ein EXT mit einem Timer0 Überlauf
zusammentrifft, dann kommt es zu einem falschen
Ergebnis.


#int_TIMER0
void  TIMER0_isr(void)
{
      Counter0 = Counter0 + 1;
}
#int_EXT
void  EXT_isr(void)
{
      anzahl0 = (Counter0 * 65536) + get_timer0() ;
      if (anzahl0 < 100000)
      {
          output_high(PIN_C0);
      }
      else
      {
         output_low(PIN_C0);
      }
      set_timer0(0);
      Counter0 = 0;
}
void main()
{
   while(TRUE)
   {
   }
}

Ich weiß theoretisch, daß
Interrupts nacheinander abgearbeitet werden, warum
also kommt beim zeitnahen Zusammentreffen
des EXT und des Timer0 Überlaufes zu einem
Fehler und was kann man dagegen machen?

Der Fehler sieht so aus, daß wohl der Counter
nicht hochgezählt ist aber der get_timer0()
noch recht niedrig ist, also übergelaufen ist.


Auch ein disable_interrupts entweder im ext
oder timer0 Interrupt brachte kein Ergebnis.

Vielen Dank im Voraus für eure Ratschläge
#3548848
Lesenswert?

pic_ler schrieb:
> Der Fehler sieht so aus, daß wohl der Counter
> nicht hochgezählt ist aber der get_timer0()
> noch recht niedrig ist, also übergelaufen ist.

Das wird wahrscheinlich daran liegen, dass der Timer überläuft, während 
der PIC die EXT_isr(void) abarbeitet. Der Timer geht automatisch wieder 
auf 0, der PIC kann Counter0 erst erhöhen, sobald er die EXT_isr(void) 
fertig hat.

Nam könnte es lösen, wenn man nicht mit dem EXT Interrupt, sondern mit 
dem Input Capture arbeitet.
Das funktioniert so: Bei einer Fallenden, Seigenden, oder bei jeder 2., 
4. Oder 16. steigenden Flanke (einstellbar)  am CCP Pin wird ein 
Interrupt ausgelöst und gleichzeitig (per Hardware) der Wert von Timer1 
ins CCPRx kopiert. Du hast in diesem Register also den Timerwert exakt 
zum Zeitpunkt der Flanke am CCP Pin stehen.
Du musst jetzt dafür sorgen, dass, wenn die Interrupts zur gleichen Zeit 
auftreten, die ISR des CCP-Interrupt vor der des Timer-Interrupt 
ausgeführt wird.
Gast #3548873
Lesenswert?

Hallo Max

danke für Deine Antwort,
ich bin Anfänger in der PIC-Programmierung
und mit CCP habe ich noch garnichts gemacht.

Deine Erklärung mit dem Überlauf klingt verständlich.

Wenn ich das also richtig verstehe ist das so,
daß der Timer unabhängig läuft und einen
Überlauf verursachen kann auch wenn ich z. B.
gerade in die EXT-Routine einsteige und das
programm erst nach der Abarbeitung in den
int_Timer0 springt.

Gibt es keine andere Lösung als mit CCP?
Wie könnte ein Pseudocode für den CCP aussehen?

Vielen Dank :)
#3548916
Lesenswert?

pic_ler schrieb:
> Gibt es keine andere Lösung als mit CCP?

Neue Idee:
1
void  EXT_isr(void)
2
{
3
      timerwert=get_timer0()
4
      anzahl0 = (Counter0 * 65536) + timerwert;
5
      if(INTCONbits.T0IF && timerwert < 30)
6
            anzahl0=anzahl0+65536;
7
      
8
      if (anzahl0 < 100000)
9
      {
10
          output_high(PIN_C0);
11
      }
12
      else
13
      {
14
         output_low(PIN_C0);
15
      }
16
      set_timer0(0);
17
      Counter0 = 0;
18
}
Jetzt wird geprüft, ob ein Timerinterrupt stattgefunden hat, das noch 
nicht bearbeitet wurde. In diesem Fall wird 65536 zu anzahl0 addiert.

zu INTCONbits.T0IF: Wie man bei deinem Compiler einzelne bits abfragt 
musst du wissen, mein Code ist für den C18
Gast #3548941
Lesenswert?

Hallo

die Lösung ist prima, sie trifft genau den Punkt.

Wie ich das Bit abfrage muß ich natürlich noch
rausfinden, aber ich weiß jetzt, was ich machen
muß.

Tausend Danke für die schnelle und hervorragende Hilfe :)
Gast #3549016
Lesenswert?

Hallo Max und Teo

danke für eure Hilfe und Beiträge.

Die Umsetzung wird natürlich etwas Zeit in Anspruch nehmen,
aber ihr habt auch sehr zum Verständnis über den
Interrupt-Ablauf und Handling beigetragen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren