ATmega1281 - Timer 3 (4,5) - CTC-Mode 4 oder 12 - 2 Probleme / Fehler

OP #857067
Lesenswert?
• ▲
▼
Hallo.

Ich weiß nicht woran es liegt, weil sich für mich an zu vielen Stellen 
zu viele Fragen aufwerfen, aber vielleicht kann jemand mit mehr Ahnung 
ja eher etwas damit anfangen.

_Ziel:_ 16Bit Timer 3 (4 oder 5) mittels CTC Mode 4 (oder 12) als 
Interrupt mit modifizierter Auflösung nutzen.

_Idee:_ Da die Timer/Counter 4 und 5 keine Ausgangspins haben, würden 
sie sich für interne Interrupts mit selbstgemachter Auflösung eignen 
(Overflow Interrupt).

_Problem:_ Zitat Datenblatt ATmega1281, S.136: "Timer/Counter4 and 
Timer/Counter5 only have full functionality in the ATmega640/1280/2560. 
Input capture and output compare are not available in the 
ATmega1281/2561..."
Mir ist durchaus bewusst, dass ich beim 1281'er für T/C4&5 für Mode 12 
nichts erwarten darf, weils ja im Datenblat steht, aber schließt das 
Zitat den Modus 4 (CTC mit OCRnA als TOP) für T/C 4&5 auch aus?

_Die Probleme betrifft in der Form aber vor allem AUCH Timer 3, und da 
fängts für mich an._

/Ich benutzte Timer0 im Fast-PWM Modus und Pin 17 (PB7) als Ausgang für 
die Anzeige über eine 2 farbige LED (OCR0A=0 -> grün, OCR0A=255 -> rot). 
Wenn ich OCR0A mit diesen Werten beschreibe leuchtet es auch 
entsprechend. Der Ausgang wird zusätzlich mit Oszi beobachtet.. ich kann 
also sehen wie die PWM aussieht.

Die PowerReductionRegsiter-Bits für die Timer sind alle auf 0 -> Timer 
also aktiv./

Problem 1: Modus 4 (CTC mit OCR3A) läuft nur mit "OCR3A = 0xFFFF", 
sämtliche anderen Werte werden ignoriert.. das dürfte schon mal nicht 
passieren.
1
#include <inttypes.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4

5
int main (void)
6
{
7
  PORTB |= (0<<PB7); // hier läuft der LED-PWM drauf
8
  DDRB |= (1<<DDB7);
9
  // Timer0 (8Bit): FastPWM-Mode(3), TOP = 0xFF, OCR0A als CompareMatch für PWM, Prescaler 1
10
  TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(1<<WGM00);
11
  TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00);
12

13
  sei(); // Interrupts global ein
14
  PRR1 |= (0<<PRTIM3); // Timer Modul ON
15
  TIMSK3 |= (1<<TOIE3); // Overflow Interrupt ein
16
  TCCR3B |= (0<<WGM33)|(1<<WGM32)|(1<<CS31); // Mode 4, Prescaler 1/8
17

18
  OCR3A = 0xFFFF; // OutputCompareRegister Vergleichswert setzen, andere Werte zB. 0xFFFE gehen nicht!
19

20
  TCNT3 = 0x0000; // Timer/Counter4 Zählregister Reset
21
  OCR0A = 10; // Alive-Signal: grün
22
  while (1) // Loop forever
23
  { }
24
    return (0);
25
} 
26

27
ISR (TIMER3_OVF_vect)
28
{
29
OCR0A = 245; // Alive-Signal: rot
30
}

Ich hab auch schon versucht OCR3A jeweils nur 8 Bit weise zu schreiben..
Erst OCR3AH mit 0xFF und dann OCR3AL mit 0xFF -> funktioniert, der 
Interrupt kommt.
Nimmt man stattdessen andere Werte geht es nicht mehr, der Interrupt 
bleibt aus.
Das gleiche gilt für Timer 4 und 5.


Problem 2: Modus 12 (CTC mit ICR) ISR-Funktion läuft nur mit 
"_VECTOR(41)" anstatt "TIMER4_CAPT_vect".. wäre mit dem Zitat erklärbar. 
Insofern überfahre ich sicher mit meinem _VECTOR(41) irgendwelche 
Einstellungen in den Makros. Allerdings wär das nur die Notlösung, weil 
ja Overflow-Interrupt nicht geht.. nur deshab führe ichs überhaupt auf.
1
#include <inttypes.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4

5
int main (void)
6
{
7
  PORTB |= (0<<PB7); // hier läuft der LED-PWM drauf
8
  DDRB |= (1<<DDB7);
9
  // Timer0 (8Bit): FastPWM-Mode(3), TOP = 0xFF, OCR0A als CompareMatch für PWM, Prescaler 1
10
  TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(1<<WGM00);
11
  TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00);
12

13
  sei(); // Interrupts global ein
14
  PRR1 |= (0<<PRTIM4); // Timer Modul ON
15
  TIMSK4 |= (1<<ICIE4); // InputCapture Interrupt ON
16
  TCCR4B |= (1<<WGM43)|(1<<WGM42)|(1<<CS41); // Mode 12, Prescaler 1/8
17
  ICR4H = 0xAF; // InputCaptureRegister Vergleichswert setzen
18
  ICR4L = 0x00; 
19
  TCNT4 = 0x0000; // Timer/Counter4 Zählregister Reset
20
  OCR0A = 10; // Alive-Signal: grün
21
  while (1) // Loop forever
22
  { }
23
    return (0);
24
} 
25

26
ISR (_VECTOR(41)) // wenn da "TIMER4_CAPT_vect" drin steht, gehts nicht..
27
{
28
OCR0A = 245; // Alive-Signal: rot
29
}

Mit anderen Worten, schön das es mit _VECTOR(41) geht, aber darauf 
verlassen sollte ich mich nicht, oder?
Mit Timer 3 funktioniert Mode 12 (CTC mit ICR) ohne diesen Trick, also 
direkt mit "TIMER3_CAPT_vect".

Danke für eure Hilfe
Joan

[Edit, Overflow statt Output Compare solls ja sein]
OP #857231
Lesenswert?
• ▲
▼
Mittlerweile bin ich drauf gekommen, dass man anstatt des 'Timer x 
Overflow Interrupts' den 'Timer x Output Compare A Interrupt' nehmen 
kann/muss/soll, wenn man nen Interrupt bei TCNTn == OCRnA haben will..

Laut Datenblatt sind die Timer 4&5 Compare A/B/C Vektoren für den 
1281'er auch nicht gesperrt, das betrifft nur die ICP-Vektoren (Seite 
106 im Datenblatt). Insgesamt kommts mir wegen dem ganz am Anfang 
geposteten Zitat, wegen der Output Compare Units, zwar immer noch 
"spanisch" vor aber nu läufts..
1
#include <inttypes.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4

5
int main (void)
6
{
7
  PORTB |= (0<<PB7);
8
  DDRB |= (1<<DDB7);
9
//PORTB |= (1<<PB7); // Alive-Signal: HIGH
10
  // Timer0 (8Bit): FastPWM-Mode(3), TOP = 0xFF, OCR0A als CompareMatch für PWM, Prescaler 1
11
  TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(1<<WGM00);
12
  TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00);
13

14
  // Timer5: CTC-Mode(4), TOP = OCR5A, Prescaler 1/8 (1µs per cycle), nix externes, OCM-Interrupt (über WGM..)
15
  TCCR5A = (0<<COM5A1)|(0<<COM5A0)|(0<<COM5B1)|(0<<COM5B0)|(0<<COM5C1)|(0<<COM5C0)|(0<<WGM51)|(0<<WGM50);
16
  TCCR5B = (0<<ICNC5)|(0<<ICES5)|(0<<WGM53)|(1<<WGM52)|(0<<CS52)|(1<<CS51)|(0<<CS50);
17
  TCCR5C = (0<<FOC5A)|(0<<FOC5B)||(0<<FOC5C);
18
  PRR1 = (0<<PRTIM5);
19
  OCR5A = 0x07d0; // Timer 5 mit 2000µs OCM_A-Interrupt starten
20
  TCNT5 = 0x0000; // Timer/Counter5 Zählregister reset
21
  TIFR5 = (1<<OCF5A); // Timer 5 Output Compare A Flag löschen
22
  TIMSK5 = (1<<OCIE5A); // Timer 5 Output Compare A Interrupt aktivieren
23

24
  sei(); // Interrupts global ein
25

26
  OCR0A = 10; // Alive-Signal: grün
27

28
  while (1) // Loop forever
29
  { }
30
    return (0);
31
} 
32

33
ISR (TIMER5_COMPA_vect)
34
{
35
//PORTB &= ~(1<<PB7); // Alive-Signal: LOW
36
OCR0A = 245; // Alive-Signal: rot
37
}

Grüsse

PS: Falls jemand noch ne Meinung dazu hat, ich würd sie gerne lesen ;-)

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