OCR1A lässt sich kein zweites mal beschreiben

Gast #2678632
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!
#2678633
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.
Gast #2678641
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
}
#2678649
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.
Gast #2678656
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

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