XMega Compare Timer

Gast #1806233
Lesenswert?
• ▲
▼
Guten Tag

Ich arbeite gerade mit einem ATMEGA64A1 und möchte eine Interrupt 
gesteuerte zeit Verzögerung die durch einen Schalter ausgelöst wird. 
Funktioniert auch mehr oder weniger... zumindest als Zufallsgenerator. 
Die Zeitverzögerung ist nämlich nur etwa jedes 2. Mal korrekt. Die 
Zeitverzögerung sollte einer Periode vom Timer0 entsprechen. Ich habe 
mir das so überlegt:
1
ISR (PORTJ_INT0_vect)
2
{  
3
  if(PORTJ.IN & (1<<6))  //Zustand des Schalters abfragen
4
  {
5
    unsigned short x;        //buffer
6

7
    if(TCC0.CNT==0) x=0x7A10;  //den Buffer auf den aktuellen Zählerstand minus eins stellen
8
    else
9
    {
10
      x=TCC0.CNT;
11
      x--;
12
    }
13

14
    TC_SetCompareC( &TCC0, x );   //Eine Periode von Timer0 einstellen
15

16
    TCC0.INTFLAGS|=0x40;    //Interrupt Flag löschen
17

18
    TC0_EnableCCChannels( &TCC0, TC0_CCCEN_bm );    //Komparator C von Timer 0 aktivieren
19
  
20
    TC0_SetCCCIntLevel( &TCC0, TC_CCCINTLVL_LO_gc );  //Interrupt für den Komparator C erlauben
21
  
22
  }
23
  else PORTK.OUT|=0x01;   //bei ausgeschaltetem Schalter, Output setzen
24
}
25

26

27
ISR (TCC0_CCC_vect)
28
{
29
  PORTK.OUT&=0xFE;
30

31
  TC0_DisableCCChannels( &TCC0, TC0_CCCEN_bm );  //Komparator C von Timer 0 desaktivieren
32
  TC0_SetCCCIntLevel( &TCC0, TC_CCCINTLVL_OFF_gc ); //Interrupt für den Komparator C verbieten
33
}


Die Interrupts scheinen zu funktionieren, PK1 wird schön ein und 
ausgeschaltet, nur ist eben die Zeit nicht immer gleich einer Periode 
vom Timer0. Ich weiss nicht ob ich einen Logik Fehler darin habe oder 
etwas Wichtiges vergessen habe, ich hoffe ihr habt bessere Augen dafür 
als ich.

Vielen dank schon im voraus.
Gast #1806623
Lesenswert?
• ▲
▼
Hallo

Mathiable schrieb:


> ISR (PORTJ_INT0_vect)


Wie hast du deinen Port0 programmiert?

Man muss  den Port konfigurieren, dass er auf  gewisse Ereignisse 
reagiert!

z.B. eine Taster (steigende oder  fallende Flanke

PORTJ.DIR=0x00;
PORTJ.PIN0CTRL=PORT_OPC_PULLUP_gc | PORT_ISC_FALLING_gc;
oder

PORTJ.DIR=0x00;
PORTJ.PIN0CTRL=PORT_OPC_PULLDOWN_gc | PORT_ISC_RISING_gc;

Auszug aus CodeWizardAVR V2.04.8 Evaluation

Das sollte bei einem Schalter (dauernd ein oder aus) auch berücksichtigt 
werden.

Warum frägst du hier: ISR (PORTJ_INT0_vect) nochmals den Schalter ab,
wenn ganz klar der Schalter den Interrupt bereits ausgelöst hat?

Bei einen auglösten Interrupt kann das:

else PORTK.OUT|=0x01;   //bei ausgeschaltetem Schalter, Output setzen

nicht eintreten.

Gruß GG
Gast #1806881
Lesenswert?
• ▲
▼
GG schrieb:
> Man muss  den Port konfigurieren, dass er auf  gewisse Ereignisse
> reagiert!
>
> z.B. eine Taster (steigende oder  fallende Flanke)

Der Interrupt reagiert auf beide Flanken, deshalb die Abfrage. Wenn der 
Schalter eingeschaltet wird, soll es eine Zeitverzögerung geben, wenn 
der Schalter abgeschaltet wird soll es sofort abschalten. Die Schalter 
Abfrage und die Interrupts funktionieren auch, die Konfiguration sollte 
also stimmen.

Trotzdem hier noch die Initialisierung des Timers und der IO:
1
  PORTJ.DIRSET=0x38;
2
  PORTK.DIRSET=0xFF;
3

4

5
// -=Timer Initialisieren=- //
6
  TC_SetPeriod( &TCC0, 0x7A10 );               //Interrupt Periode definieren, annäherungsweise 1s
7
  
8
  TC0_SetOverflowIntLevel( &TCC0, TC_OVFINTLVL_LO_gc );  //Overflow Interrupt auf Low Level erlauben
9

10
  PMIC.CTRL |= PMIC_LOLVLEN_bm;   //low level Interrupt erlauben
11

12
  PORTJ.INTCTRL = 0x01;     //Interrupt Level an PORTJ festlegen
13
  PORTJ.INT0MASK = 0x40;    //Interrupt an PORTJ PIN6 freigeben
14
  PORTJ.PIN0CTRL = 0x00;    //Interrupt auf beide Flanke einstellen
15
  sei();                    //Interrupt einschalten
16

17
TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV1024_gc );    //Prescaler sowie Clock wählen und Timer starten

Kann man den einstieg in die Timer0 Periode überhaupt so machen wie ich 
es wollte (TCC0.CNT - 1) oder gibt es da eine „normalere“ Variante?
Gast #1808090
Lesenswert?
• ▲
▼
ala42 schrieb:
> Wenn der Schalter prellt, wird sich die Logik sicherlich anders
> verhalten als Du das erwartest.

Danke für die Antwort.
Dann müsste der interrupt aber von vorne beginnen und die 
Zeitverzögerung würde sich in die länge ziehen, es wird aber kürzer. Im 
Oszilloskop lässt sich auch kein signifikantes Prellen beobachten, 
handelt sich um max. 200mV während ca. 1us. Aber auch eine delay von 
10us hat nichts verändert.
Sollte es so funktionieren oder wieso antworten so wenige?

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.