Forum: Mikrocontroller und Digitale Elektronik ATmega1281 - Timer 3 (4,5) - CTC-Mode 4 oder 12 - 2 Probleme / Fehler


von Joan P. (joan)


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]

von Joan P. (joan)


Lesenswert?

Nebenbei.. wieso geht die Text-Formatierung nicht, wie hier angegeben:
http://www.mikrocontroller.net/articles/Formatierung_im_Forum?

von Joan P. (joan)


Lesenswert?

Ich nochmal..

Streicht Problem 2.. das ist halt so.

Aber Problem #1 macht mich fertig..
Wenn da jemand was zu sagen könnte, wärs nett.

Danke

von Joan P. (joan)


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 ;-)

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.