mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik OC1A steuern im CTC Mode


Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich habe Probleme mit dem CTC-Mode im ATmega16.

In einer Interruptroutine soll der Ausgang OC1A des Timer 1
gesetzt werden. Dann soll der Timer 1 von 0 an hochzählen
und bei Gleichheit mit dem OCR1A Register den Ausgang
OC1A wieder zurücksetzten.

Hier die entsprechenden Teile meiner Lösung, die aber nicht
funktioniert. Was muss ich anders machen?
//Initialisierung von Timer 1
 TCCR1A = (1<<COM1A1); //OC1A bei Gleichheit löschen
 TCCR1B = (1<<WGM12)|(1<<CS12); //CTC-Mode , Vorteiler 256
 SETBIT(TIMSK,OCIE1A);  //Interruptfreigabe nötig?


//Die Startende Interruptroutine
 ISR(TIMER0_OVF_vect)
{
.
 SETBIT(TCCR1A,FOC1A); //OC1A sollte auf 1 gehn
 TCNT1 = 0; //Timer zurücksetzten
}

ISR(TIMER1_COMPA_vect)
{  
nop; //eigentlich nichts zu tun
 
}

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also erstmal fehlt da ein sei()

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ist klar!
Ich hab auch nur die
wirklich relevanten Teile
des Programms geschrieben.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>TCCR1A = (1<<COM1A1); //OC1A bei Gleichheit löschen

TCCR1A = (1<<COM1A0); //OC1A bei Gleichheit Toggeln

Bei jedem Erreichen von OCR toggelt das Pin, und der Timer wird 
zurückgesetzt.

Den Rest kannst du dir sparen.

MfG Spess

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
CTC -> clear timer on compare match...

Zählt hoch bis compare match, fängt dann wieder bei 0 an.
Wenn dann OC1A auf toggeln gestellt ist gehts doch.

Was geht denn genau nicht bei dir?

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>TCCR1A = (1<<COM1A0); //OC1A bei Gleichheit Toggeln

Er soll aber nicht Toggeln.
OC1A soll durch die ISR von T0
alle 20ms gesetzt werden und dann
je nach Wert in OCR1A nach einer
bestimmten Zeit 0,1...1,5ms
wieder aus gehen und aus bleiben.
T1 lass ich einfach weiterzählen.

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was geht denn genau nicht bei dir?

OC1A geht gar nicht an.

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast den Port aber auch als Ausgang definiert? DDRB = (1 << DDB1); 
oder so ähnlich

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Glaube mich daran zu erinnern, dass OCR1A nicht doppelt gepuffert ist im 
non PWP modus?!? Vielleicht verpasst du da ein compare oder so..

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Du hast den Port aber auch als Ausgang definiert?
Ja, und zwar mit diesen Befehlen:

[c]
 SETBIT(DDRD,DDD5); //OC1A Pin zum Ausgang machen
 SETBIT(PORTD,PORTD5);
[/]

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo wird OCR1A gesetzt?

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch Mal aber richtig

>Du hast den Port aber auch als Ausgang definiert?
Ja, und zwar mit diesen Befehlen:
 SETBIT(DDRD,DDD5); //OC1A Pin zum Ausgang machen
 SETBIT(PORTD,PORTD5);

Man sieht, der Ausgang wird auch gesetzt.
Er geht auch kurz an. Aber sobald
COM1A1 gesetzt ist übernimmt der Timer 1

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne die SETBIT Funktion/Makro nicht aber die funktionier?
Geht der Pin denn ohne den Timer auf 5V, ich hatte schonmal nen defekten 
Pin...

Hm ok. Dann hab ich auch kein Plan mehr ^^

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ausserdem: IM CTC Modus zählt der Timer bis zu OCR1A und setzt sich 
selber zurück. Wenn der OC1A pin aktiv ist, kann man den Pin nicht mehr 
über PORT-Zugriffe steuern, d.h. der Pin wird vom Timer gesteuert. Wenn 
Du ihn einmal setzten willst, wird der Pin gesetzt und bleibt dann high, 
egal was du sonst noch machst. Ausser du initaialisiert den Timer samt 
Pin neu.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR1A = (1<<COM1A1); //OC1A bei Gleichheit löschen


Diese Zeile macht dir das

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erst mal Danke für die Tipps.
Hier noch mein ganzes Testprogramm.
In Abhängigkeit von einer Taste
sollte OC1A im Rhythmus von 2Sek
eine halbe oder eine Sek an sein.
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL //Taktfequenz in Hz. Wichtig für alle 
                        //zeitabhängigen Funktionen und ISRs
#include <util/delay.h>

#define nop asm volatile ("nop")  //nop für ganz kurze Pausen

//Makros für die Bitverarbeitung
#define SETBIT(adr, bit) (adr |=  (1<<bit))
#define CLEARBIT(adr, bit) (adr &= ~(1<<bit))
#define TOOGELBIT(adr, bit) (adr ^=  (1<<bit))
#define CHECKBIT(adr, bit) (adr  &  (1<<bit))


//Anschlussklemmen der beiden LED und der Glühlampe
#define led_r PORTC5    //LED rechts
#define led_l PORTD7    //LED links und Glühlampe
#define port_r PORTC
#define port_l PORTD


int main(void)
{
 SETBIT(DDRC,led_r);   //LED Pins zu Ausgängen machen
 SETBIT(DDRD,led_l);
 CLEARBIT(port_r,led_r);//LED ausschalten
 CLEARBIT(port_l,led_l);

 SETBIT(DDRD,DDD5); //OC1A Pin zum Ausgang machen
 SETBIT(PORTD,PORTD5);//bleibt eine halbe Sek an

 _delay_ms(500);      //0,5s Pause

 //Timer 0 einrichten.
 //ISR wird jede ms aufgerufen
 TCCR0 = 1; //Prescaler auf 0
 SETBIT(TIMSK, TOIE0);
 TCNT0 = 0;

 //Timer 1 vorbereiten CTC-Mode mit OCR1A Register. Bei
 //Gleichheit von Zähler und OCR1A wird der Pin OC1A gelöscht

 TCCR1A = (1<<COM1A1);
 TCCR1B = (1<<WGM12)|(1<<CS12);
 SETBIT(TIMSK,OCIE1A);

 sei();

 while(1)
 { 

//Eine Taste wird abgefragt und OCR1A belegt.
//eigentlich müsste OCR1 eine ein halbe
//oder eine Sekund an sein.
  if(CHECKBIT(PIND,PIND2)) OCR1A = 15625;
  else OCR1A = 31250;
 }
} //Ende main


//##### T0 Überlauf ISR  ##################
ISR(TIMER0_OVF_vect)
{
 static unsigned int n = 62500;
 
 if(n--) return; 

 n = 62500; 
 
 SETBIT(TCCR1A,FOC1A);
 TCNT1 = 0;

 TOOGELBIT(port_r,led_r);  //OC1A Pin umschaltenschalten
                           //2 Sek. an, 2 Sek. aus
                           //Die LED blinkt richtig
}

//##### T1 Compare Match ISR  ##################
ISR(TIMER1_COMPA_vect)
{  
nop;
}

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Äh,
ISR(TIMER0_OVF_vect)
{
 static unsigned int n = 62500;
 
 if(n--) return; 

 n = 62500; 

irre ich mich oder wird da jetzt bei jedem Aufruf der ISR n immer neu 
mit 62500 initialisiert, dann einen runter gezählt und auf 0 geprüft, 
nur um dann wieder auf 62500 gesetzt zu werden?

/Edit

nein ich irre mich :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.