Forum: Mikrocontroller und Digitale Elektronik OCR1A lässt sich kein zweites mal beschreiben


von ctc (Gast)


Lesenswert?

Hi!
Ich hab folgenden Programmcode:
1
#include <avr/io.h
2
#include <avr/interrupt.h>
3
4
ISR(TIMER1_OVF_vect){
5
 if(PORTD & 0x01){ 
6
   PORTD = PORTD & ~(1<<PD0);
7
   OCR1A = 0xFFFF;                     // hier
8
 } 
9
 else{
10
   PORTD = PORTD | (1<<PD0);
11
   OCR1A = 0xFFFF;                     // hier
12
 }
13
}
14
void main(void){
15
  DDRD = 0xFF;
16
  PORTD = 0x00;
17
  
18
  init_ctc(8, 0xFFFF);
19
  while(1){}
20
}
wie man sieht will ich in meiner Interrupt Routine das Register OCR1A 
neu beschreiben, damit ich das Ausgangssignal stärker variieren kann... 
Sobald ich aber OCR1A mit einem anderem Wert als dem als erstes 
geschriebenen Wert beschreiben will, kommt es mir so vor als ob die 
Routine nicht mehr aufgerufen wird!? An was kann das liegen?

Der obige Code funktioniert aber sobald ich an den markierten stellen 
0xFFFF durch irgendetwas anderes ersetzte geht es nicht mehr...
Hoffe ihr könnt mir helfen!

von Karl H. (kbuchegg)


Lesenswert?

Ersetz mal den Overflow durch einen Compare Match Interrupt


> wie man sieht will ich in meiner Interrupt Routine das Register
> OCR1A neu beschreiben

eigentlich seh ich das nicht. Ich sehe nur, dass du in beiden Fällen 
jeweils 0xFFFF ans OCR1A zuweist.

-> es ist realtiv sinnlos, wenn du Code postest der funktioniert. Du 
musst den Code posten, der NICHT funktioniert. Dort kann man den Fehler 
suchen, warum es nicht geht.

von ctc (Gast)


Lesenswert?

Ok ich mach ich mal...
Folgender Code funktioniert nicht mehr:
1
#include <avr/io.h
2
#include <avr/interrupt.h>
3
4
ISR(TIMER1_OVF_vect){
5
 if(PORTD & 0x01){ 
6
   PORTD = PORTD & ~(1<<PD0);
7
   OCR1A = 0xFFFF;                     
8
 } 
9
 else{
10
   PORTD = PORTD | (1<<PD0);
11
   OCR1A = 0xFFF0;                     // Änderung
12
 }
13
}
14
void main(void){
15
  DDRD = 0xFF;
16
  PORTD = 0x00;
17
  
18
  init_ctc(8, 0xFFFF);
19
  while(1){}
20
}
Die init_ctc() (nicht verändert):
1
void init_ctc(uint16_t prescaler, uint16_t top_value){
2
3
  TCCR1A = 0x00;
4
  // CTC auswählen: Top: OCR1A
5
  TCCR1B = (1<<WGM12);
6
  // Prescaler einstellen
7
  /*
8
  0 0 1 clkI/O/1 (No prescaling)
9
  0 1 0 clkI/O/8 (From prescaler)
10
  0 1 1 clkI/O/64 (From prescaler)
11
  1 0 0 clkI/O/256 (From prescaler)
12
  1 0 1 clkI/O/1024 (From prescaler)*/
13
  switch(prescaler){
14
    case 1: 
15
    TCCR1B = TCCR1B | (1<<CS10);      
16
    break;
17
    case 8: 
18
    TCCR1B = TCCR1B | (1<<CS11);
19
    break;
20
    case 64: 
21
    TCCR1B = TCCR1B | (1<<CS10) | (1<<CS11);
22
    break;
23
    case 256: 
24
    TCCR1B = TCCR1B | (1<<CS12);
25
    break;
26
    case 1024: 
27
    TCCR1B = TCCR1B | (1<<CS10) | (1<<CS12);
28
    break;
29
  }
30
  //Timer/Counter1, Overflow Interrupt Enable
31
  TIMSK = (1<<TOIE1);
32
  // TopValue setzen
33
  OCR1A = top_value;    
34
  // Interrupts einschlten
35
  sei();          
36
}

von Karl H. (kbuchegg)


Lesenswert?

>  //Timer/Counter1, Overflow Interrupt Enable
>  TIMSK = (1<<TOIE1);

Wie gesagt. Probier mal den Compare Match Interrupt. Denn das ist ja 
genau das, was beim CTC Modus passiert:
wenn es einen Compare Match mit dem OCR1A gibt, dann wird der Zähler 
zurückgesetzt.

Und ich bin mir nicht sicher, ob da dann überhaupt noch ein Overflow 
Interrupt generiert wird. Bei 0xFFFF könnte es dann genau deshalb 
funktionieren, weil da der Timer dann sowieso seinen Overflow hat.

von Stone (Gast)


Lesenswert?

>Und ich bin mir nicht sicher, ob da dann überhaupt noch ein Overflow
>Interrupt generiert wird.
Ne, wird nicht. Tritt ja kein Overflow auf.

Musst auf jeden Fall TIMSK und den Interrupt Vektor ändern.


Gruß Matthias

von Sascha W. (sascha-w)


Lesenswert?

wie man im Datenblatt unschwer erkennen kann löst der TOIE in der 
Betriebsart CTC (WGM12=1) bei MAX (0xFFFF) aus, wenn OCR1A < MAX löst 
logischerweise nur noch der OCIE aus.

Sascha

von ctc (Gast)


Lesenswert?

Ja stimmt das wars... Nehm jetzt das Compare Match Interrupt und es 
funktioniert!

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.