Timer Vergleichsregister Problem

Gast #1461601
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
Gast
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.)
Gast
>>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
Gast
>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.
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.