Forum: Mikrocontroller und Digitale Elektronik CTC Modus - Output Compare Register


von Max P. (chipster)


Lesenswert?

Hallo Leute,

ich spiele mich gerade ein wenig mit dem CTC-Modus des ATMega16. Dieser 
Chip hat 3 Timer: T0-8bit, T1-16bit & T2-8bit. Dabei ist mir nach 
einigen Programmabstürzen und Fehlersuche erst aufgefallen, dass die 
jeweiligen Overflow-Zählregister TCNT0-2 als unsigned 8bit/16bit 
definiert sind, jedoch die CTC Register OCR0-2 als signed 8bit/16bit.
Auszug aus dem Datenblatt:


TCNT2 – Timer/Counter Register
The Timer/Counter Register gives direct access, both for read and write 
operations, to the Timer/Counter unit 8-bit counter.
OCR2 – Output Compare Register
The Output Compare Register contains an 8-bit value that is continuously 
compared with the counter value (TCNT2).



Dazu meine 1.Frage:
Gibt es einen Weg diese Overflow Zähler auch als unsigned Variablen zu 
verwenden? Irgendwie finde ich es ansonsten ein wenig verwirrend, wenn 
ich für ein Interrupt aus einem 8bit Timer einen kleineren Wert als 
255(Overflow - TCNT) bräuchte, den Werte bereich zwischen 127 und 255 
aber mit dem OCR-Zähler aber nicht abdecken kann. Oder habe ich da einen 
Denkfehler?


Meine 2.Frage betrifft den Timer1(16bit) CTC-Modus:
Laut Datenblatt gibt es 2 Zählregister für den CTC-Modus, nämlich OCR1A 
und OCR1B. Also war meine 1. Vermutung, dass es mit Timer1 möglich ist 2 
unterschieldiche CTC-Aufrufe zu generieren. Auch in den Interface-Files 
werden die entsprechenden Vektoren definiert 
(TIMER1_COMPA_vect/TIMER1_COMPB_vect) um ein Interrupt aufzurufen, wenn 
die entsprechnende Flag gesetzt wird. Jedoch findet sich im Datenblatt 
keine Einstellungsmöglichkeit in den Registern TCCR1A und TCCR1B, den 
TCNT1 Wert mit dem OCR1B Wert zu vergleichen und somit einen CTC-Modus 
mit OCR1B zu realisieren (im Datenblatt Table 16-5). Und auch von der 
Überlegung her wäre es komisch 2 CTC-Events über nur einen Hauptzählwert 
(TCNT1) zu generieren, da dieser, wenn ich es richtig verstanden habe, 
nach einem erfolgreichen CTC-Match wieder auf 0 gesetzt wird. Kann mir 
jemand erklären was es mit diesem OCR1B Wert auf sich hat und für was 
dieser verwendet werden könnte bzw. ob es vielleicht doch möglich ist 
aus einem Timer gleichzeitig 2 CTC-Events zu erzeugen?


Danke und LG

von Oliver S. (oliverso)


Lesenswert?

Max P. schrieb:
> Dazu meine 1.Frage:
> ...
> Denkfehler?

Ja. Im gesamte  Timer-Kapitel im Datenblatt kommt der Begriff „signed“ 
nicht ein einziges Mal vor.

> Meine 2.Frage betrifft den Timer1(16bit) CTC-Modus:
> Laut Datenblatt gibt es 2 Zählregister für den CTC-Modus, nämlich OCR1A
> und OCR1B.
> ...
> ob es vielleicht doch möglich ist
> aus einem Timer gleichzeitig 2 CTC-Events zu erzeugen?

Datenblatt (oder das passende Tutorial deiner Wahl) nochmal lesen, was 
genau der CTC-Modus ist, und wie er funktioniert, und die dazu Tabelle 
mit den Betriebsarten (alle 16).
Dann beantwortet sich die Frage von alleine.

Oliver

von Dieter R. (drei)


Lesenswert?

Max P. schrieb:

> Laut Datenblatt gibt es 2 Zählregister für den CTC-Modus, nämlich OCR1A
> und OCR1B.

Ich vermute, bei dir liegt ein grundlegendes Missverständnis der 
Register-Funktionen vor. Dies sind keine Zählregister, sondern (siehe 
Datenblatt):

Output Compare Registers

Das Zählregister (ein einziges) ist TCNT1.

Vorschlag: versuche, mit Atmel Start die Register für die von dir 
gewünschte Funktion zu initialisieren. Da hast du ein (mehr oder weniger 
sinnvoll angeordnetes) Formular, das (hoffentlich) die Funktion der 
Register etwas klarer macht. Das liefert dir auch 
Dummy-Interruptroutinen, die du selbst weiter füllen kannst.

von Peter D. (peda)


Lesenswert?

Max P. schrieb:
> Jedoch findet sich im Datenblatt
> keine Einstellungsmöglichkeit in den Registern TCCR1A und TCCR1B, den
> TCNT1 Wert mit dem OCR1B Wert zu vergleichen und somit einen CTC-Modus
> mit OCR1B zu realisieren (im Datenblatt Table 16-5).

Braucht es nicht, die beiden Vergleiche und Flags setzen finden immer 
statt.
Ein Clear ist natürlich nur mit einem Compareregister sinnvoll, sonst 
würde ja das größere nie erreicht.

von Max P. (chipster)


Lesenswert?

Oliver S. schrieb:
> Max P. schrieb:
>> Dazu meine 1.Frage:
>> ...
>> Denkfehler?
>
> Ja. Im gesamte  Timer-Kapitel im Datenblatt kommt der Begriff „signed“
> nicht ein einziges Mal vor.

In der Software verhält sich der OCRx-Wert allerdings wie ein signed 
8bit Wert, d.h. wenn ich versuche 127 zuzuweisen funktioniert alles, mit 
z.B. 128 steht im OCRx auf einmal ein negativer Wert. Hatte gestern 
keine Zeit mehr das nocheinmal zu testen.

>> Meine 2.Frage betrifft den Timer1(16bit) CTC-Modus:
>> Laut Datenblatt gibt es 2 Zählregister für den CTC-Modus, nämlich OCR1A
>> und OCR1B.
>> ...
>> ob es vielleicht doch möglich ist
>> aus einem Timer gleichzeitig 2 CTC-Events zu erzeugen?
>
> Datenblatt (oder das passende Tutorial deiner Wahl) nochmal lesen, was
> genau der CTC-Modus ist, und wie er funktioniert, und die dazu Tabelle
> mit den Betriebsarten (alle 16).
> Dann beantwortet sich die Frage von alleine.

Ok, werde ich mir nochmal durchlesen.

> Oliver

von Max P. (chipster)


Lesenswert?

Dieter R. schrieb:
> Max P. schrieb:
>
>> Laut Datenblatt gibt es 2 Zählregister für den CTC-Modus, nämlich OCR1A
>> und OCR1B.
>
> Ich vermute, bei dir liegt ein grundlegendes Missverständnis der
> Register-Funktionen vor. Dies sind keine Zählregister, sondern (siehe
> Datenblatt):
>
> Output Compare Registers
>
> Das Zählregister (ein einziges) ist TCNT1.
>
> Vorschlag: versuche, mit Atmel Start die Register für die von dir
> gewünschte Funktion zu initialisieren. Da hast du ein (mehr oder weniger
> sinnvoll angeordnetes) Formular, das (hoffentlich) die Funktion der
> Register etwas klarer macht. Das liefert dir auch
> Dummy-Interruptroutinen, die du selbst weiter füllen kannst.

Ah, sorry. Das hab ich komplett falsch beschrieben. Da bin ich mit den, 
für mich neuen, Bezeichnungen durcheinander gekommen. Danke für den Tipp 
mit Atmel Start, das kannte ich noch gar nicht. Werde ich mir ansehen.

LG

von Chris D. (myfairtux) (Moderator) Benutzerseite


Lesenswert?

Max P. schrieb:
> In der Software verhält sich der OCRx-Wert allerdings wie ein signed
> 8bit Wert, d.h. wenn ich versuche 127 zuzuweisen funktioniert alles, mit
> z.B. 128 steht im OCRx auf einmal ein negativer Wert. Hatte gestern
> keine Zeit mehr das nocheinmal zu testen.

Da stimmt irgendetwas nicht.

In was programmierst Du? Zeig mal Deinen Quellcode.

Die Register beim ATMega16 werden definitiv nicht als signed 
angesprochen.

Ehrlich gesagt kenne ich überhaupt keinen Mikrocontroller, bei dem 
Signed-Werte für Register verwendet werden (außer vielleicht 
Fliesskomma-Einheiten).

von Max P. (chipster)


Lesenswert?

Peter D. schrieb:
> Max P. schrieb:
>> Jedoch findet sich im Datenblatt
>> keine Einstellungsmöglichkeit in den Registern TCCR1A und TCCR1B, den
>> TCNT1 Wert mit dem OCR1B Wert zu vergleichen und somit einen CTC-Modus
>> mit OCR1B zu realisieren (im Datenblatt Table 16-5).
>
> Braucht es nicht, die beiden Vergleiche und Flags setzen finden immer
> statt.
> Ein Clear ist natürlich nur mit einem Compareregister sinnvoll, sonst
> würde ja das größere nie erreicht.

Dieser Timer fuchst mich noch ein wenig, aber danke für die Erklärung! 
Langsam wirds^^

von Mega256Helper (Gast)


Lesenswert?

Chris D. schrieb:
> Die Register beim ATMega16 werden definitiv nicht als signed
> angesprochen.

Er wird sich halt eine signed Variable anzeigen lassen die
den Register-Wert beinhaltet.

von Max P. (chipster)


Lesenswert?

Chris D. schrieb:
> Max P. schrieb:
>> In der Software verhält sich der OCRx-Wert allerdings wie ein signed
>> 8bit Wert, d.h. wenn ich versuche 127 zuzuweisen funktioniert alles, mit
>> z.B. 128 steht im OCRx auf einmal ein negativer Wert. Hatte gestern
>> keine Zeit mehr das nocheinmal zu testen.
>
> Da stimmt irgendetwas nicht.
>
> In was programmierst Du? Zeig mal Deinen Quellcode.
>
> Die Register beim ATMega16 werden definitiv nicht als signed
> angesprochen.
>
> Ehrlich gesagt kenne ich überhaupt keinen Mikrocontroller, bei dem
> Signed-Werte für Register verwendet werden (außer vielleicht
> Fliesskomma-Einheiten).

Aktuell verwende ich Atmel Studio/C++.
Werde ich machen, komme aber vor heute Nacht nicht zu meinem PC.

LG

von Oliver S. (oliverso)


Lesenswert?

Max P. schrieb:
> In der Software verhält sich der OCRx-Wert allerdings wie ein signed
> 8bit Wert, d.h. wenn ich versuche 127 zuzuweisen funktioniert alles, mit
> z.B. 128 steht im OCRx auf einmal ein negativer Wert. Hatte gestern
> keine Zeit mehr das nocheinmal zu testen.

In welcher Software?

Oliver

von Peter D. (peda)


Lesenswert?

Max P. schrieb:
> jedoch die CTC Register OCR0-2 als signed 8bit/16bit.

Nö.
Alle IO-Register sind unsigned, siehe sfr_defs.h:
1
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
2
#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))
3
#define _MMIO_DWORD(mem_addr) (*(volatile uint32_t *)(mem_addr))

von Max P. (chipster)


Angehängte Dateien:

Lesenswert?

Chris D. schrieb:
> In was programmierst Du? Zeig mal Deinen Quellcode.

Oliver S. schrieb:
> In welcher Software?

Atmel Studio/C++


main.c

[c]
#include "Interface/Globals.h"

#define DEBUG_Mode

#ifdef DEBUG_Mode
#pragma message("!!!Debug-Modus aktiviert!!! Fuer Mikrocontroller-Built 
deaktivieren!")
#endif

uint16_t ADC_Messergebnis = 0;

bool flag_ADC_Messung_gestartet = false;
bool flag_Taster_Abfrage_Aktiv = false;

byte tmp_Buffer_Taster_val = 0;

double  x_double = 0;
uint8_t x_uint = 0;
int8_t x_int = 0;

int main(void)
{
  x_double = OCR2_VALUE;
  x_uint = OCR2_VALUE;
  x_int = OCR2_VALUE;
  OCR2 = OCR2_VALUE;

  tmp_Buffer_Taster_val = 1;

  return 0;
}
[c]

globals.h

[c]
#include <avr/io.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/interrupt.h>

#include "../Interface/timing.h"


#define F_CPU 14000000UL  //6553600UL

#define T_LED_TICK      10L      //Zeit in "us" pro ISR-Aufruf
#define USEC_IN_1SEC    1000000L  //"us" in einer Sekunde
#define CPU_Prescaler_T0  1L
#define OCR2_VALUE  ((F_CPU * T_LED_TICK) / (USEC_IN_1SEC * 
CPU_Prescaler_T0) - 1)

#if OCR2_VALUE < 0
#warning "OCR2_value" kleiner als 0
#endif
#if OCR2_VALUE > 255
#warning "OCR2_value" groesser als 255
#endif


#include <util/delay.h>

typedef uint8_t byte;
[c]


Habe den Fehler gefunden. Auf der Watchliste wird der OCRx-Wert als 
"int" ausgegeben, und statt z.B. 139 steht dann -117 da drinnen. Mit der 
Hex-Ausgabe stimmt der Wert. facepalm Siehe Bilder im Anhang.

Peter D. schrieb:
> Nö.
> Alle IO-Register sind unsigned, siehe sfr_defs.h:

Mega256Helper schrieb:
> Er wird sich halt eine signed Variable anzeigen lassen die
> den Register-Wert beinhaltet.

Fast, habe die Typen-Definition im Ausgabefenster übersehen, aber danke 
für den Hinweis!

: Bearbeitet durch User
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.