Forum: Mikrocontroller und Digitale Elektronik AVR Atmega32U4 Timer-Konstruktion unzureichend


von Martin S. (maryn)


Lesenswert?

Hallo liebe MCU-Forengemeinde!

Ich bin MCU-Anfänger und versuche jetzt schon seit längerem, eine 
Timer-Konstruktion zum Laufen zu bekommen.
Ich verwende einen Atmega32U4 mit externem 16MHz-Quarz und einer LED am 
Pin PB5.
Zum Programmieren verwende ich Atmel Studio 7.0 und einen 
AVR-Dragon(ISP-Schnittstelle).

Ich brauche den Timer für ein anderes Projekt und möchte ihn eigentlich 
nur mit der LED an einem ganz einfachen Blinker testen. Trotz 
wiederholter Fehlersuche/Überprüfung aller Programmteile funktioniert 
mein Konzept aber nicht. An der LED liegts nicht, da der Blinker unter 
Verwendung der _delay_ms Funktion richtig arbeitet.
Bei Verwendung des Timers(ohne delay-Funktion) tut sich an der LED aber 
rein gar nichts. Ich kann nur vermuten, dass ich irgendwas noch nicht 
richtig verstanden habe.

Ich verwende eine Variable, welche per Vergleichsregister hochgezählt 
werden soll. Hat die Variable den Wert 1000 erreicht, soll die LED 
getriggert werden. Hier spricht der Code aber eigentlich(hoffentlich!) 
für sich. Vielleicht stoßt ihr auch in meinen Code-Kommentaren auf den 
Fehler.

Ich bitte euch, mal ein wachsames Augenpaar über meinen Code wandern zu 
lassen. Denn irgendwo muss ich einen ganz doofen Fehler gemacht haben, 
den ich nicht sehe.

Ich hoffe ich habe alle notwendigen Informationen zusammengestellt.

Viele Grüße,
Martin


1
/* Definition Taktfrequenz */
2
#ifndef F_CPU
3
#define F_CPU 16000000UL
4
#endif
5
6
/* Einbinden von Headerdateien */
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include <avr/sleep.h>
10
#include <stdio.h>
11
#include <stdint.h>
12
13
/* Definitionen */
14
#define TOGGLE_LED (PORTB ^= (1 << PORTB5))      /* LED An/Aus per XOR-Operator */
15
16
/* Variablendeklaration */
17
volatile uint16_t timer_03_ms = 0 ;          /* 16-bit Variable, um bis 1000 (1 Sekunde) zählen zu können */
18
19
/* Deklaration der verwendeten Funktionen */
20
void init_timer_03(void) ;
21
void start_timer_03(void) ;
22
23
/*
24
INTERRUPTVEKTOREN:
25
Configure Interrupt Vector Timer 3 - Compare A
26
Flag OCF3A des TIFR3-Registers wird gesetzt, wenn OCR3A=16000 erreicht wird.
27
Immer dann soll der Timer hochgezählt werden.
28
Durch den Takt von 16MHz geschieht dies pro Sekunde 1000 Mal.
29
Man erhält Millisekunden-Auflösung.
30
*/
31
ISR(TIMER3_COMPA_vect)
32
{
33
  
34
  timer_03_ms = timer_03_ms + 1 ;            /* Timer um eine Millisekunde erhöhen */
35
  
36
  if (timer_03_ms == 1000)              /* Nach 1 Sekunde */
37
  {
38
    TOGGLE_LED ;                  /* LED An/Aus per XOR-Operator */
39
    timer_03_ms = 0 ;                /* Timer zurücksetzen */
40
  }
41
  
42
}
43
44
/* HAUPTFUNKTION */
45
int main(void)
46
{
47
  
48
  /* Hier soll Pin PB5 als Ausgang deklariert werden */
49
  DDRB |= (1 << DDB5) ;
50
  
51
  /*
52
  Initialisierung des Timers:
53
  */
54
  init_timer_03() ;
55
  start_timer_03() ;
56
  
57
  /*
58
  Enable Interrupts globally
59
  */
60
  sei() ;
61
  
62
    while(1)
63
    {
64
    
65
    SMCR |= (1 << SE) ;          /* Enable Sleep Mode */
66
    set_sleep_mode(SLEEP_MODE_IDLE) ;  /* Select Sleep Mode: Idle */
67
    sleep_mode() ;            /* Enter Sleep Mode */
68
    
69
    }
70
  
71
}
72
73
void init_timer_03(void)
74
{
75
76
  // Timer/Counter 3 Control Register A:
77
  // Select Normal Port Operation(i.e. Counter Mode), Output Compare Pins(COM1Xn) disconnected, Waveform Generation Mode = Normal Mode
78
  TCCR3A |= ( (0 << COM3A1) | (0 << COM3A0) | (0 << COM3B1) | (0 << COM3B0) | (0 << COM3C1) | (0 << COM3C0) | (0 << WGM31) | (0 << WGM30) ) ;
79
80
  // Timer/Counter 1 Control Register B:
81
  // Select CTC Mode, Clock is still deactivated -> Counter isn't started yet!
82
  TCCR3B |= ( (0 << ICNC3) | (0 << ICES3) | (0 << 5) | (0 << WGM33) | (1 << WGM32) | (0 << CS32) | (0 << CS31) | (0 << CS30) ) ;
83
84
  // Timer/Counter 1 Control Register C:
85
  // All non-mentioned bits in this register are unused by default
86
  // FOC3B and FOC3C don't exist in the register according to datasheet
87
  TCCR3C |= (0 << FOC3A) ;
88
  
89
  // Interrupt Mask Register TIMSK3
90
  // Enable Output Compare Match A Interrupt 
91
  TIMSK3 |= ( (0 << ICIE3) | (0 << OCIE3C) | (0 << OCIE3B) | (1 << OCIE3A) | (0 << TOIE3) ) ;
92
  
93
  OCR3A = 0b0011111010000000 ;  /* Setze das 16-bit Timer-Vergleichs-Register OCR3A auf 16000 */
94
  
95
  return;
96
97
}
98
99
void start_timer_03(void)
100
{
101
  
102
  TCNT3 = 0 ;
103
  
104
  // Timer/Counter 3 COntrol Register B:
105
  // Select External clock(16 MHz Quarz-Oscillator), Clock on Rising Edge
106
  // Starting of clock should also start the timer(TCNT3)
107
  TCCR3B |= ( (1 << CS32) | (1 << CS31) | (1 << CS30) ) ;
108
  
109
  return ;  
110
  
111
}

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Martin S. schrieb:
> TCCR3B |= ( (1 << CS32) | (1 << CS31) | (1 << CS30) ) ;

 Und wo soll der External Clock herkommen ?

von Martin S. (maryn)


Lesenswert?

Vielen Dank für den Hinweis!

Ich bin doch tatsächlich davon ausgegangen, dass mein externer Quarz 
auch der externe Takt am Tn (T1) Pin ist. Durch den Hinweis und ein 
kurzes Nachschauen hat sich das natürlich als falsch herausgestellt.

So kann man sich irren und ich hab schon an mir gezweifelt.
Mein Problem ist damit bereits gelöst, Besten Dank nochmal!

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.