mikrocontroller.net

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


Autor: Frederik Krämer (n0ll4k)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/interrupt.h>
#include <stdint.h>
 
// Schwellwerte
// Entprellung: 
#define CNTDEBOUNCE 1
// "lange gedrueckt:"
#define CNTREPEAT 100
 
// hier z.B. Taste an Pin2 PortA "active low" = 0 wenn gedrueckt
#define KEY_DDR DDRB
#define KEY_PORT PORTB
#define KEY_PIN PINB
#define KEY1 PB1

#define LED_DDR         DDRC
#define LED_PORT        PORTC
#define LED_PIN      PINC
#define LED0            PC0
#define LED1      PC1
#define LED2      PC2
#define LED3      PC3
#define LED4      PC4
#define LED5      PC5
#define LED6      PC6
#define LED7      PC7
 
// beachte: volatile! 
volatile uint8_t gKeyCounter;
 
// Timer-Compare Interrupt ISR, wird z.B. alle 10ms ausgefuehrt
ISR(TIMER1_COMPA_vect)
{
   // hier wird gKeyCounter veraendert. Die übrigen
   // Programmteile müssen diese Aenderung "sehen":
   // volatile -> aktuellen Wert immer in den Speicher schreiben
   /*if ( !(KEY_PIN & (1<<KEY1)) ) {
      if (gKeyCounter < CNTREPEAT) gKeyCounter++;
   }
   else {
      gKeyCounter = 0;
   }*/
LED_PORT ^= ( 1 << LED7 );
}
 
 
int main(void)
{


  //Initialisierung der Ports
  KEY_DDR = 0;
  KEY_PORT = 0x0F;
  LED_DDR = 0xFF;
  LED_PORT ^= ( 1 << LED2 );

  //Initialisierung des Timers
  OCR1AH = 0xB1;
  OCR1AL = 0xE0;
  TCCR1A = 0x00;
  TCCR1B = 0x02;
  
  TIMSK = 0x10;

  sei();
  while(1)
  {
       // hier wird auf gKeyCounter zugegriffen. Dazu muss der in der
       // ISR geschriebene Wert bekannt sein:
       // volatile -> aktuellen Wert immer aus dem Speicher lesen
       /*if ( gKeyCounter > CNTDEBOUNCE ) { // Taste mind. 10*10 ms "prellfrei"
           if (gKeyCounter == CNTREPEAT) {
              LED_PORT ^= ( 1 << LED7 );
           }
           else { 
              LED_PORT ^= ( 1 << LED0 );
           }
       }*/

  }
}

Autor: hans (Gast)
Datum:

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

Autor: Frederik Krämer (n0ll4k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke erstmal aber die LED blinkt in der selben Frequenz.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frederik Krämer wrote:

>
>   //Initialisierung des Timers
>   OCR1AH = 0xB1;
>   OCR1AL = 0xE0;
>   TCCR1A = 0x00;
>   TCCR1B = 0x02;
> 
>   TIMSK = 0x10;
> 

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

Autor: Frederik Krämer (n0ll4k)
Datum:

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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

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

Autor: Frederik Krämer (n0ll4k)
Datum:

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

Autor: Frederik Krämer (n0ll4k)
Datum:

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

Trotzdem danke.

Autor: Johannes M. (johnny-m)
Datum:

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

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.