Forum: Mikrocontroller und Digitale Elektronik Timer CTC Mode


von Robert (Gast)


Lesenswert?

Hallo,

ich habe nun 2 Stunden einen Fehler gesucht und ihn endlich gefunden. 
Verstehe aber nicht so recht wieso es nicht funktioniert hatte. Ich will 
mir einen Takt von 500Hz an Pin OC5A ausgeben. Dies im CTC Mode.

//ATmega2560
1
//Dieser Code hat nicht funktioniert:
2
  TCCR5A |= (1<<COM5A0);                  // Portpin an Timer angekoppelt  => fclk                   
3
  TCCR5B |= ((1<<WGM52) | (1<<CS01) | (1<<CS00));        // Timer 5: Clear on Compare / Prescale: 64
4
  
5
  OCR5AH = 0;                        // Timer 5 Compare Value
6
  OCR5AL = 249;
7
  //OCR0AL  =  124;                      
8
  // fOC0B = fosc / ( 2 * Prescale * ( OCR0A + 1 ) )
9
  // fosc = 16 MHz => fOC0B = 1000 Hz ( OCR0A = 124 )
10
  // fosc = 16 MHz => fOC0B =  500 Hz ( OCR0A = 249 )
1
//Dieser schon:
2
  TCCR5A = (1<<COM5A0);                  // Portpin an Timer angekoppelt  => fclk                   
3
  TCCR5B |= ((1<<WGM52) | (1<<CS01) | (1<<CS00));        // Timer 5: Clear on Compare / Prescale: 64
4
  
5
  OCR5AH = 0;                        // Timer 5 Compare Value
6
  OCR5AL = 249;
7
  //OCR0AL  =  124;                      
8
  // fOC0B = fosc / ( 2 * Prescale * ( OCR0A + 1 ) )
9
  // fosc = 16 MHz => fOC0B = 1000 Hz ( OCR0A = 124 )
10
  // fosc = 16 MHz => fOC0B =  500 Hz ( OCR0A = 249 )

TCCR5A habe ich vorher nirgends benutzt. Müsste dann doch eigentlich 
seinen Initialwert von 0x00 haben.

von eProfi (Gast)


Lesenswert?

Gib halt für beide Fälle die Register-Werte aus (z.B. über die 
Serielle).
Ggf. vorher / nachher.

von molteee (Gast)


Lesenswert?

eProfi schrieb:
> Gib halt für beide Fälle die Register-Werte aus (z.B. über die
> Serielle).
> Ggf. vorher / nachher.

Solange wieder kein kompletter, compilierbarer, auf das Problem 
gekürzter Code vorliegt kann man sich das Rat und Raten ersparen.

von Jacko (Gast)


Lesenswert?

Ja und, ich will 440,0 Hz an Pin OBOE ausgeben.

Warum sollten wir jetzt auf die Suche gehen, welches
Datenblatt von welchem µC du wohl nicht richtig gelesen
hast?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Robert schrieb:
>   OCR5AH = 0;                        // Timer 5 Compare Value
>   OCR5AL = 249;

Auch wenn's mit dem Problem nix zu tun hat:  Es gibt keinen Grund, das 
Byte-weise zu setzen.  Machst du mit normalen Variablen ja auch nicht...
1
OCR5A = 249;

von Robert (Gast)


Lesenswert?

Ich verwende einen Arduino Mega...

Dieses Programm geht nicht...
1
/* Interruptsteuerung */
2
3
#define ENAB_GLOBAL_INT     asm("sei")               // Set I-Bit in SREG
4
#define DISAB_GLOBAL_INT    asm("cli")                  // Reset I-Bit in SREG
5
6
/* Pin- und Portdefinitionen */
7
8
/********************************* Schrittmotor 1 *******************************************************************************************/
9
#define SM1_CLK_PIN    DDRL |= (1<<DDL3);PORTL |= (1<<PORTL3)   // Port L, Bit 3 => CLK Schrittmotor (Atmel -> Motor) -> OUTPUT, ON   //
10
/********************************************************************************************************************************************/
11
12
/*************************/
13
/******* Functions *******/
14
/*************************/
15
void Motor_Init (void);
16
17
void Motor_Init (void)
18
{
19
  SM1_CLK_PIN;
20
21
  TCCR5A |= (1<<COM5A0);                 // Portpin an Timer angekoppelt  => fclk                  
22
  TCCR5B |= ((1<<WGM52) | (1<<CS01) | (1<<CS00));       // Timer 5: Clear on Compare / Prescale: 64
23
  
24
                      
25
  OCR5A = 249;                      // Timer 5 Compare Value
26
  //OCR0A  =  124;                      
27
  // fOC0B = fosc / ( 2 * Prescale * ( OCR0A + 1 ) )
28
  // fosc = 16 MHz => fOC0B = 1000 Hz ( OCR0A = 124 )
29
  // fosc = 16 MHz => fOC0B =  500 Hz ( OCR0A = 249 )
30
  
31
32
  
33
  EICRA |=  ((1<<ISC31) | (1<<ISC30));          // INT 3 (Kanal A SM1): positive Flanke 
34
  
35
  //EICRA |=  ((1<<ISC30));               // INT 3 (Kanal A SM1): beide Flanken 
36
  //EICRA &= ~((1<<ISC31));
37
  
38
  EICRB |=  ((1<<ISC50) | (1<<ISC40));          // INT 4 (Kanal A SM2) u. INT 5 (Kanal A SM3): beide Flanken  
39
  EICRB &= ~((1<<ISC51) | (1<<ISC41));          
40
  }
41
  
42
  
43
  
44
void setup (void)
45
{
46
  DISAB_GLOBAL_INT;
47
  
48
  Motor_Init ();
49
}
50
51
void loop (void)
52
{
53
54
}

Dieses schon...
1
/* Interruptsteuerung */
2
3
#define ENAB_GLOBAL_INT     asm("sei")               // Set I-Bit in SREG
4
#define DISAB_GLOBAL_INT    asm("cli")                  // Reset I-Bit in SREG
5
6
/* Pin- und Portdefinitionen */
7
8
/********************************* Schrittmotor 1 *******************************************************************************************/
9
#define SM1_CLK_PIN    DDRL |= (1<<DDL3);PORTL |= (1<<PORTL3)   // Port L, Bit 3 => CLK Schrittmotor (Atmel -> Motor) -> OUTPUT, ON   //
10
/********************************************************************************************************************************************/
11
12
/*************************/
13
/******* Functions *******/
14
/*************************/
15
void Motor_Init (void);
16
17
void Motor_Init (void)
18
{
19
  SM1_CLK_PIN;
20
21
  TCCR5A = (1<<COM5A0);                 // Portpin an Timer angekoppelt  => fclk                  
22
  TCCR5B |= ((1<<WGM52) | (1<<CS01) | (1<<CS00));       // Timer 5: Clear on Compare / Prescale: 64
23
  
24
                      
25
  OCR5A = 249;                      // Timer 5 Compare Value
26
  //OCR0A  =  124;                      
27
  // fOC0B = fosc / ( 2 * Prescale * ( OCR0A + 1 ) )
28
  // fosc = 16 MHz => fOC0B = 1000 Hz ( OCR0A = 124 )
29
  // fosc = 16 MHz => fOC0B =  500 Hz ( OCR0A = 249 )
30
  
31
32
  
33
  EICRA |=  ((1<<ISC31) | (1<<ISC30));          // INT 3 (Kanal A SM1): positive Flanke 
34
  
35
  //EICRA |=  ((1<<ISC30));               // INT 3 (Kanal A SM1): beide Flanken 
36
  //EICRA &= ~((1<<ISC31));
37
  
38
  EICRB |=  ((1<<ISC50) | (1<<ISC40));          // INT 4 (Kanal A SM2) u. INT 5 (Kanal A SM3): beide Flanken  
39
  EICRB &= ~((1<<ISC51) | (1<<ISC41));          
40
  }
41
  
42
  
43
  
44
void setup (void)
45
{
46
  DISAB_GLOBAL_INT;
47
  
48
  Motor_Init ();
49
}
50
51
void loop (void)
52
{
53
54
}

Einziger Unterschied ist das Beschreiben von TCCR5A.

Nach dem Start sollte doch 0x00 in diesem stehen.

von Robert (Gast)


Lesenswert?

Steht aber 0x01 drin. Bzw. dann 0x41.

von spess53 (Gast)


Lesenswert?

Hi

>Nach dem Start sollte doch 0x00 in diesem stehen.

Nach einem Reset steht da 0x00. Das ist ein Unterschied.

MfG Spess

von S. Landolt (Gast)


Lesenswert?

Arduino - aha.
Dann bleibt nur zu wiederholen:

eProfi schrieb:
> Gib halt für beide Fälle die Register-Werte aus (z.B. über die
> Serielle).
> Ggf. vorher / nachher.

von Robert (Gast)


Lesenswert?

Laut Datenblatt: Initial Value 0x00.
Ich verstehe darunter Startwert. Nach einem Reset steh bei mir immer 
noch 0x01 drin.

von S. Landolt (Gast)


Lesenswert?

> Laut Datenblatt: Initial Value 0x00.
Datenblatt des Arduino?

von spess53 (Gast)


Lesenswert?

Hi

>Nach einem Reset steh bei mir immer noch 0x01 drin.

Hast du überhaupt die Möglichkeit den Controller direkt nach dem Reset 
anzuhalten und nach zu sehen?

MfG Spess

von Robert (Gast)


Lesenswert?

Nein..., Datenblatt des Atmel. Steht jedenfalls 0x01 drin und vorher 
mache ich nichts mit diesem Register. Ich frage mich einfach warum WGM50 
gesetzt ist.
Egal, dann ists halt so. Ich werde es mal mit dem STK500 probieren und 
schauen was dort passiert.

von Robert (Gast)


Lesenswert?

Gibt es einen bestimmten Grund warum das hier in diesem Programm auch so 
gemacht wird?
Würde es bei TCCR2A mit |= funktionieren?

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR
1
/* uC: ATMega48PA */
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
//Variablen für die Zeit
6
volatile unsigned char sekunde;
7
volatile unsigned char minute;
8
volatile unsigned char stunde;
9
10
int main(void)
11
{
12
  // Timer 2 konfigurieren
13
  GTCCR |= (1 << TSM) | (1 << PSRASY);  //Timer anhalten, Prescaler Reset
14
  ASSR |= (1 << AS2);                   //Asynchron Mode einschalten
15
  TCCR2A = (1 << WGM21);                //CTC Modus
16
  TCCR2B |= (1 << CS22) | (1 << CS21);  //Prescaler 256
17
  // 32768 / 256 / 1 = 128                Intervall = 1s
18
  OCR2A = 128 - 1;
19
  TIMSK2 |= (1<<OCIE2A);                //Enable Compare Interrupt
20
  GTCCR &= ~(1 << TSM);                 //Timer starten
21
  sei();                                //Enable global Interrupts
22
23
  while(1)
24
  {
25
    /*Hier kann die aktuelle Zeit
26
      ausgeben werden*/
27
  }
28
}
29
30
/*
31
Der Compare Interrupt Handler 
32
wird aufgerufen, wenn 
33
TCNT2 = OCR2A = 128-1 
34
ist (128 Schritte), d.h. genau alle 1s
35
*/
36
ISR (TIMER2_COMPA_vect)
37
{
38
    TCCR2B = TCCR2B;              //Wird weiter unten im Text erklärt!
39
    sekunde++;
40
    if(sekunde == 60)
41
    {
42
      minute++;
43
      sekunde = 0;
44
    }
45
    if(minute == 60)
46
    {
47
      stunde++;
48
      minute = 0;
49
    }
50
    if(stunde == 24)
51
    {
52
      stunde = 0;
53
    }
54
    // Wird weiter unten im Text erklärt!
55
    while(ASSR & ((1<<TCN2UB) | (1<<OCR2AUB) | (1<<OCR2BUB) |
56
                  (1<<TCR2AUB) | (1<<TCR2BUB)));
57
}

von S. Landolt (Gast)


Lesenswert?

> vorher mache ich nichts mit diesem Register
Schon; aber, wie es scheint, der Arduino.

Und ob dieser das TCCR2A anfasst, steht auf einem anderen Blatt.

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.