www.mikrocontroller.net

Forum: Compiler & IDEs Timer Vergleichsregister Problem


Autor: Niklas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:

#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr/interrupt.h>


//##########################################
//          Funktionen                   ###
//##########################################

//########TIMER0INT#########################

  
void timer0 (void)
{
  
  TCNT1 = 0x0000;  //Startwert 0 setzen
  OCR1A = 31249;  //Vergleichsregister auf 31249
  TIMSK = (1<<OCIE1A); //Enable Output Compare Interrupt
  sei();                //Enable Global Interrupt 

  TCCR1A = 0x00;       
  TCCR1B = (1<<CS12);   // Prescaler 256
}


//##########################################
//          Variablen                    ###
//##########################################

unsigned char x=0;


//#####MAIN#################################

main()
{
  timer0();
  DDRB = 0xFF;
  while(1)
  {  
    if(x == 1)
    PORTB = 0xFF;
    else
    PORTB = 0x00;    
  }
}
    
//##########################################
//          Interrupts                   ###
//##########################################

//####COMPAREA##############################

ISR(TIMER1_COMPA_vect)
{
  if(x == 0)
  x = 1;
  else
  x = 0;
}


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

Autor: Gast (Gast)
Datum:

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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: Niklas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR1B = (1<<CS12)|(1<<WGM12);

avr

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht 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
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

Autor: Niklas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ok, jetzt funktionierts wunderbar. Vielen Dank.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.