Forum: Mikrocontroller und Digitale Elektronik CTC-Modus, Frage zum GCC-Tutorial


von Anfänger (Gast)


Lesenswert?

Im GCC-Tutorial für AVR´s steht bei "Die Timer und Zähler" beim 
CTC-Modus:

"... und einer der OCnx-Pins so gesetzt werden, dass er bei Auftreten 
des Compare Match getoggelt wird (über die COM-Bits). ... "

Ich verstehe leider grad nicht, was damit gemeint ist bwz. was ich 
setzen soll/muss?

Atmega88 und 16-Bit-Timer möchte ich verwenden.

Falls mir da jemand helfen kann, würd ich mich drüber freuen.

von xfr (Gast)


Lesenswert?

Das steht im Datenblatt:
http://www.atmel.com/Images/doc2545.pdf

Dich interessiert der 16 Bit Timer, also musst Du in Kapitel 16 
nachschauen. Am Ende des Kapitels befindet sich die "Register 
description". Die Bits, die Du suchst, sind im Register TCCR1x.

von Anfänger (Gast)


Lesenswert?

ok, danke fr die Antwort. Ich bin mir nicht so sicher gewesen. Ich 
dachte erst, mit "toggeln" (umschalten) ist gemeint, dass ich vielleicht 
draußen zwischen zwei Pins eine Kontaktbrücke herstellen muss.

von Christian F. (cmf) Benutzerseite


Lesenswert?

Anfänger schrieb:
> "... und einer der OCnx-Pins so gesetzt werden, dass er bei Auftreten
> des Compare Match getoggelt wird (über die COM-Bits). ... "
Das heißt, dass man im Register TCCR1A die Bits COM1A0 und COM1A1 so 
setzen kann, dass bei jedem Compare Match Interrupt der Pin OC1A 
getoggelt wird. (Beim Atmega88 könnten sie leicht anders heißen)

von STK500-Besitzer (Gast)


Lesenswert?

Anfänger schrieb:
> Ich verstehe leider grad nicht, was damit gemeint ist bwz. was ich
> setzen soll/muss?

Die OC-Register sind im Prinzip Weckzeiten: Wenn der Timer den gleichen 
Wert hat, wie das OC-Register, dann gibt es einen "Alarm" in Form 
gesetzter Flags. Unter Umständen wird dann auch eine ISR aufgerufen.

Togglen bedeutet, dass ein Ausgang umgeschaltet wird.
Jedes Mal, wenn ein Ereignis eintritt, wird der Ausgangszustand geändert 
(Da binär, immer nur zwischen "an" und "aus").

Wenn also ein OC-Ereignis eintritt, wird der Ausgang in den anderen 
Zustand geschaltet - jedes Mal.

von Anfänger (Gast)


Lesenswert?

In C gibt es im Gegensatz zu Assembler manchmal:

OCR1A

und

OCR1AH
OCR1AL

Meine Frage - OCR1A(L/H) brauch ich doch nur dierekt in Assembler, da 
ich dort immer nur in 8bit-Schritten mit Registern zuweisen kann?

In C kann ich dann einfach mit ORC1A einen 16bit-Wert zuweisen? ORC1A 
gibt es dann auch nur unter C, oder?

von STK501-Besitzer (Gast)


Lesenswert?

nee, das ist falsch.

von Karl H. (kbuchegg)


Lesenswert?

Anfänger schrieb:

> In C kann ich dann einfach mit ORC1A einen 16bit-Wert zuweisen?

Ja das geht.

Bei vielen 16-Bit Registern funktioniert das auch.
Aber: Es gibt auch Ausnahmen. Zb. DAC Register.

Aber die ganzen Timer-Register kannst du so als 16-Bit Pseudoregister 
auffassen, bei denen sich der Compiler um die richtige Reihenfolge der 
Zuweisungen kümmert.

von STK501-Besitzer (Gast)


Lesenswert?

Hab noch ne Frage:

Datenblatt Atmega88:
0x00B rjmp TIM1_COMPA ; Timer1 Compare A Handler
0x00C rjmp TIM1_COMPB ; Timer1 Compare B Handler

bedeutet dass, dass ich beim Atmega88 im Timer1 das, wie es im 
GCC-Tutorial beschrieben ist - mit zwei Compare-Interrupts machen, 
einen, der dann zb alle 100ms auslöst und der andere dann alle 10ms, je 
nach eingestelltem OCR1(A/B)-Wert?

von STK501-Besitzer (Gast)


Lesenswert?

Dass ist mal mein Programmierversuch, meint ihr, dass ist so ok?

Irgendwas soll einmal jede Minute gemacht werden. Dies steht dann in der 
IF-Abfrage in der Dauerschleife in der main-Funktion.
1
#ifndef F_CPU
2
#define F_CPU 1000000UL    // Prozessorgeschwindigkeit
3
#endif
4
5
// Prescaler (bei 16MHz F_CPU und 100Hz F_OC) = 256 (dann runder Wert!!!)
6
// Prescaler (bei  1Mhz F_CPU und 100Hz F-OC) =   8 (dann runder Wert!!!)
7
#define PRESCALER 8UL
8
#define F_OC 100UL // 100Hz (alle 10ms)
9
#define OCR1A_berechnet (F_CPU/(PRESCALER*F_OC))-1;
10
11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
#include <util/atomic.h>
14
15
volatile uint8_t zaehler = 0;
16
17
// eígenes Flag
18
volatile uint8_t eigen_flag = 0x00;
19
#define ZAEHLERFLAG 1
20
#define ZAEHLERFLAG_BIT (1<<ZAEHLERFLAG)
21
22
ISR (TIMER1_COMPA_vect)
23
{
24
  zaehler++;
25
  
26
  if (zaehler == 100) {
27
    eigen_flag |= ZAEHLERFLAG_BIT;
28
    zaehler = 0;
29
  }  
30
  
31
} // Ende ISR (TIMER1_COMPA_vect)
32
33
int main(void)
34
{
35
  // Timer1 konfigurieren
36
  TCCR1B |= (1<<CS11) | (1<<CS10);  //Prescaler 8: CS12=0 CS11=1 CS10=1   Prescaler 256: CS12=1 CS11=0 CS10=0
37
  TCCR1B &= ~(1<<CS12);
38
  OCR1A = OCR1A_berechnet;
39
  TIMSK1 = (1<<OCIE1A);  // Compare-Interrupt zulassen 
40
  
41
  // Interrupts einschalten
42
  sei ();
43
  
44
  while(1) {
45
    if (eigen_flag & ZAEHLERFLAG_BIT) {
46
      ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
47
        eigen_flag &= ~ZAEHLERFLAG_BIT;
48
        }
49
      
50
      // Tu was jede Minute        
51
    }        
52
   
53
    }
54
} // Ende main()

von STK501-Besitzer (Gast)


Lesenswert?

sorry, es soll nicht jede Minute was gemacht werden, sondern jede 
Sekunde (100*10msec) = 1sec.

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.