Forum: Mikrocontroller und Digitale Elektronik ATmega32 Timer1 zählt immer bis zum Ende


von Frederik K. (n0ll4k)


Lesenswert?

Hallo,

also erstmal, ich programmieren noch nicht sehr lange bzw. intensiv mit 
Mikrocontrollern.

Mein Problem ist das mein Timer1 immer bis zum Ende zählt.

Ich habe mich an einer Tastenentprellung mit Interrupt versucht aber es 
hat irgendwie nur so halb geklappt. Also bin ich mal ein wenig auf die 
Fehlersuche gegangen und habe einfach mal beim Compare eine LED 
getoogelt.

Nachdem ich dann spaßeshalber mal die OCR1AH und OCR1AL rausgenommen 
habe um zu sehen ob das ganze dann langsamer wird hat sich keine 
Veränderung beim blinken gezeigt.

Hat jemand eine Idee woran das liegt?

uC ist wie gesagt ein ATmega32 mit 16MHz externem Quarz

Hier mal noch der Quellcode
1
#include <avr/io.h>
2
#ifndef F_CPU
3
#define F_CPU 16000000UL
4
#endif
5
#include <avr/interrupt.h>
6
#include <stdint.h>
7
 
8
// Schwellwerte
9
// Entprellung: 
10
#define CNTDEBOUNCE 1
11
// "lange gedrueckt:"
12
#define CNTREPEAT 100
13
 
14
// hier z.B. Taste an Pin2 PortA "active low" = 0 wenn gedrueckt
15
#define KEY_DDR DDRB
16
#define KEY_PORT PORTB
17
#define KEY_PIN PINB
18
#define KEY1 PB1
19
20
#define LED_DDR         DDRC
21
#define LED_PORT        PORTC
22
#define LED_PIN      PINC
23
#define LED0            PC0
24
#define LED1      PC1
25
#define LED2      PC2
26
#define LED3      PC3
27
#define LED4      PC4
28
#define LED5      PC5
29
#define LED6      PC6
30
#define LED7      PC7
31
 
32
// beachte: volatile! 
33
volatile uint8_t gKeyCounter;
34
 
35
// Timer-Compare Interrupt ISR, wird z.B. alle 10ms ausgefuehrt
36
ISR(TIMER1_COMPA_vect)
37
{
38
   // hier wird gKeyCounter veraendert. Die übrigen
39
   // Programmteile müssen diese Aenderung "sehen":
40
   // volatile -> aktuellen Wert immer in den Speicher schreiben
41
   /*if ( !(KEY_PIN & (1<<KEY1)) ) {
42
      if (gKeyCounter < CNTREPEAT) gKeyCounter++;
43
   }
44
   else {
45
      gKeyCounter = 0;
46
   }*/
47
LED_PORT ^= ( 1 << LED7 );
48
}
49
 
50
 
51
int main(void)
52
{
53
54
55
  //Initialisierung der Ports
56
  KEY_DDR = 0;
57
  KEY_PORT = 0x0F;
58
  LED_DDR = 0xFF;
59
  LED_PORT ^= ( 1 << LED2 );
60
61
  //Initialisierung des Timers
62
  OCR1AH = 0xB1;
63
  OCR1AL = 0xE0;
64
  TCCR1A = 0x00;
65
  TCCR1B = 0x02;
66
  
67
  TIMSK = 0x10;
68
69
  sei();
70
  while(1)
71
  {
72
       // hier wird auf gKeyCounter zugegriffen. Dazu muss der in der
73
       // ISR geschriebene Wert bekannt sein:
74
       // volatile -> aktuellen Wert immer aus dem Speicher lesen
75
       /*if ( gKeyCounter > CNTDEBOUNCE ) { // Taste mind. 10*10 ms "prellfrei"
76
           if (gKeyCounter == CNTREPEAT) {
77
              LED_PORT ^= ( 1 << LED7 );
78
           }
79
           else { 
80
              LED_PORT ^= ( 1 << LED0 );
81
           }
82
       }*/
83
84
  }
85
}

von hans (Gast)


Lesenswert?

Dein Timer läuft immer von 0-ffff, d.h. alle 65536 Takte
kommt ein Interrupt.

 TCCR1B = 0x00; //stop
 TCNT1H = 0xB1; //setup
 TCNT1L = 0xE0;
 OCR1AH = 0x4E;
 OCR1AL = 0x20;
 ICR1H  = 0x4E;
 ICR1L  = 0x20;
 TCCR1A = 0x00;
 TCCR1B = 0x02; //start Timer

Damit müßte der Interrupt alle 10 ms kommen, Wert in OCRA.
Timer wird jetzt automatisch zurückgesetzt.

gruß hans

von Frederik K. (n0ll4k)


Lesenswert?

Hallo,

danke erstmal aber die LED blinkt in der selben Frequenz.

von Peter D. (peda)


Lesenswert?

Frederik Krämer wrote:

>
1
>   //Initialisierung des Timers
2
>   OCR1AH = 0xB1;
3
>   OCR1AL = 0xE0;
4
>   TCCR1A = 0x00;
5
>   TCCR1B = 0x02;
6
> 
7
>   TIMSK = 0x10;
8
>

Du programmierst in C, also nimm die Timerregister als 16Bit und laß den 
Compiler die richtige Zugriffsreihenfolge machen (ich weiß nicht, ob 
Deine stimmt).

Und warum kryptische Hexwerte, man kann in C auch Dezimalzahlen 
verwenden, damits lesbarer wird.
Noch besser, man läßt den Compiler die richtigen Werte aus der 
Quarzfrequenz automatisch berechnen.

Und warum nimmst Du nicht die vordefinierten Bitnamen für die 
Konfigurationsregister. Hast Du Angst, daß sonst ein anderer Deinen Code 
zu leicht verstehen kann?


Peter

von Frederik K. (n0ll4k)


Lesenswert?

Moin,

das ich die 16Bit Register auch direkt setzen kann wusste ich zum 
Beispiel gar nicht. Bisher kannte ich es nur so das ich alles einzeln 
angeben muss.

Die Umrechnung passt aber soweit.

Wie sage ich dem Kompiler denn das er die Zugriffsreihenfolge 
automatisch machen soll oder wird das gemacht, wenn ich die Register 
direkt mit 16Bit beschreibe?

Und wie funktioniert das denn mit der automatischen Berechnung über die 
Quarzfrequenz?

Ich nehme nicht die vordefinierten Namen, da das Programm nachher auf 
einen anderen ATmega auch laufen soll und ich es so einfacher finde das 
ganze zu protieren bevor ich überall wieder die Namen ändern muss.

Frederik

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Frederik Krämer wrote:
> Ich nehme nicht die vordefinierten Namen, da das Programm nachher auf
> einen anderen ATmega auch laufen soll und ich es so einfacher finde das
> ganze zu protieren bevor ich überall wieder die Namen ändern muss.
DU findest es also einfache überall die Zahlen neu zu berechnen? Die 
Namen sind bei (vielen) GLeich oder ähnlich die Bitpostionen NICHT!

von Frederik K. (n0ll4k)


Lesenswert?

Ist natürlich ein Argument, aber da ist der Fehler auch nicht zu suchen 
oder?

von Frederik K. (n0ll4k)


Lesenswert?

Mhh das Thema hat sich erledigt, ich hatte irgendwie verpennt CTC 
anzumachen, nun funktioniert es soweit.

Trotzdem danke.

von Johannes M. (johnny-m)


Lesenswert?

Frederik Krämer wrote:
> Wie sage ich dem Kompiler denn das er die Zugriffsreihenfolge
> automatisch machen soll oder wird das gemacht, wenn ich die Register
> direkt mit 16Bit beschreibe?
Genau! Wenn Du die 16-Bit-Register benutzt, dann macht der Compiler das 
alles automatisch, ohne dass Du Dich da drum kümmern musst. Dafür isses 
da.

> Ich nehme nicht die vordefinierten Namen, da das Programm nachher auf
> einen anderen ATmega auch laufen soll und ich es so einfacher finde das
> ganze zu protieren bevor ich überall wieder die Namen ändern muss.
Das kann man über Makros erschlagen. Und übrigens: Wenn bei dem "anderen 
ATMega" die Bits anders heißen, dann ist die Wahrscheinlichkeit sehr 
groß, dass auch die Register selbst andere Namen haben. Und dann musste 
sowieso ändern. Das Argument der Portabilität ist in diesem Falle also 
Mumpitz.

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.