Forum: Compiler & IDEs Timer Vergleichsregister Problem


von Niklas (Gast)


Lesenswert?

Ich möchte für mein STK500 mit ATmega128 ein Programm schreiben das die 
Led´s im Sekundentakt aufblinken lassen soll, sprich:

0s led´s aus
0,5s led´s an
1s led´s aus
1,5s led´s an
usw.

Dafür hab ich mir unter anderem die GCC Tutorials durchgelesen ( das 
Allgemeine, das für Timer und das für die "genaue Sekunde")

und dabei ist folgender Code rausgekommen:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <avr/interrupt.h>
5
6
7
//##########################################
8
//          Funktionen                   ###
9
//##########################################
10
11
//########TIMER0INT#########################
12
13
  
14
void timer0 (void)
15
{
16
  
17
  TCNT1 = 0x0000;  //Startwert 0 setzen
18
  OCR1A = 31249;  //Vergleichsregister auf 31249
19
  TIMSK = (1<<OCIE1A); //Enable Output Compare Interrupt
20
  sei();                //Enable Global Interrupt 
21
22
  TCCR1A = 0x00;       
23
  TCCR1B = (1<<CS12);   // Prescaler 256
24
}
25
26
27
//##########################################
28
//          Variablen                    ###
29
//##########################################
30
31
unsigned char x=0;
32
33
34
//#####MAIN#################################
35
36
main()
37
{
38
  timer0();
39
  DDRB = 0xFF;
40
  while(1)
41
  {  
42
    if(x == 1)
43
    PORTB = 0xFF;
44
    else
45
    PORTB = 0x00;    
46
  }
47
}
48
    
49
//##########################################
50
//          Interrupts                   ###
51
//##########################################
52
53
//####COMPAREA##############################
54
55
ISR(TIMER1_COMPA_vect)
56
{
57
  if(x == 0)
58
  x = 1;
59
  else
60
  x = 0;
61
}

er funktioniert soweit auch, das die Led´s alle 2 sekunden blinken
(0 = LED´s aus, 1 = LED´s an, 2 = LED´s aus usw.)

ich hab die Rechnung aus dem "Die genaue Sekunde" Tutorial genommen und 
bin damit auf diesen Wert (31249 bei 8Mhz ) gekommen.
Leider verstehe ich die Rechnung nicht ganz und weiß  nicht was ich 
ändern muss um das Intervall zu halbieren.
Würde mich freuen wenn ihr mir helfen könntet.

Mfg Niklas

von Gast (Gast)


Lesenswert?

Na, da musst Du doch nur OCR1A = 31249 durch OCR1A = 15624 ersetzen. 
Dann blinken die LEDs doppelt so schnell.

von Gast (Gast)


Lesenswert?

Die Rechnung ist ein Klacks: Der Timer wird von der Hardware mit 8 
MHz/256 hochgezählt (/256 weil der Prescaler auf 256 konfiguriert ist), 
d. h. mit 31250 Hz. Ergo ist nach genau 31250-maligem Hochzählen exakt 
eine Sekunde vorbei, d. h. der ins OCR-Register zu schreibende Wert ist 
31250-1. Schreibst Du statt 31250-1 nur 3125-1 rein, wird die Chose 
logischerweise zehnmal so schnell usw. That's all :-)

(Die "-1" hat ihren Grund in der Hardware der Controller. Siehe 
Datenblatt.)

von Niklas (Gast)


Lesenswert?

>>Na, da musst Du doch nur OCR1A = 31249 durch OCR1A = 15624 ersetzen.
>>Dann blinken die LEDs doppelt so schnell.

Ok dann hab ich die Rechnung doch verstanden^^ das hab ich nämlich auch 
gemacht aber es hat nicht funktioniert und daher dachte ich ich hab was 
bei der Rechnung falsch gemacht.

Die LED´s blinken sogar im 2 sekunden takt wenn ich die Zeile weg lasse 
:S

von avr (Gast)


Lesenswert?

TCCR1B = (1<<CS12)|(1<<WGM12);

avr

von Gast (Gast)


Lesenswert?

>das hab ich nämlich auch gemacht aber es hat nicht funktioniert

Kein Wunder: Wie ich jetzt auch sehe, betreibst Du den Timer ja gar 
nicht im CTC-Modus. Dann läuft er immer ganz durch bis zum Overflow, 
also von 0 bis 65535, und Du bekommst immer einen 65536 / (8 MHz/256) = 
2.097152-Sekundentakt.

Also: CTC-Modus einschalten! Dann wird der Timer von der Hardware beim 
Erreichen des OCR-Werts automatisch auf Null gesetzt, und das willst Du 
ja.

von Mark .. (mork)


Lesenswert?

Wenn Variablen sowohl in der ISR als auch im Hauptprogramm verwendet 
werden, wie hier das x, dann sollte man diese Variable mit dem Modifier 
'volatile' versehen, also
1
volatile unsigned char x;
 'volatile' sagt dem Compiler, dass die Variable bei jedem Zugriff aus 
dem RAM gelesen werden soll. Ansonsten könnte es bei eingeschalteter 
Optimierung vorkommen, dass die Variable vom Hauptrogramm in einem 
Register gehalten wird und das Hauptprogramm von der Änderung in der ISR 
nichts mitbekommt.

MfG Mark

von Niklas (Gast)


Lesenswert?

Ah ok, jetzt funktionierts wunderbar. Vielen Dank.

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.