Forum: Mikrocontroller und Digitale Elektronik Atmega1284p Timer Counter Problem


von Sebastian W. (code)


Lesenswert?

Hallo zusammen,

ich versuche verzweifelt einen Counter am Atmega1284p einzustellen.
Ich möchte einen Counter einstellen, welcher ca. alle 1us in 
TIMER0_OVF_vect springt und eine Variable "counter" hochzählt. Das 
funktioniert auch soweit. Nun möchte ich im Hauptprogramm eine Abfrage, 
welche den Timer deaktiviert, sobald die Variable "counter" > X ist.

Das Deaktivieren funktioniert aber nicht.
Der Timer bleibt ständig an.

do{
    N++;
} while( counter < T );

Die while Bedingung greift nicht. Es funktioniert aber komischerweise, 
wenn ich in die do Schleife ein _delay_us(100); einbaue.

Ich hoffe mir kann jemand von euch weiterhelfen!

Hier der Code:

#ifndef F_CPU
#define F_CPU 16000000UL                          // Controller CPU 
Frequenz
#endif

#include <avr/io.h>
#include <math.h>
#include <util/delay.h>
#include <string.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/interrupt.h>

extern void uart_init(uint32_t UBRR_VAL);                  //UART 
Initialisierung
extern void uart_puts (char *s);                      //UART String 
senden
extern void uart_gets( char* Input );                    //UART String 
empfangen
extern void uart_putc( char c );                      //UART Char senden

unsigned long counter;
unsigned long T;          //Zeitintervall in us
unsigned long N;          //Anzahl der Impulse
char Ergebnis[10] = "";
static int32_t UBRR_VAL;

int main(void){
  UBRR_VAL =25;
  uart_init(UBRR_VAL);

  T = 1000;
  TCCR0B |= (1<<CS01);  //Prescaler 8
  TCNT0 = 254;        //Counter vorladen

  N = 0;
  counter = 0;
  uart_puts("start");
  TIMSK0|=(1<<TOIE0);      //Enable Counter
  sei();            //Enable Interupts


  do{
    N++;                                 //Taktzähler um 1 erhöhen
  } while( counter < T );


  cli();
  TIMSK0|=(0<<TOIE0);      //Disable Counter
  uart_puts("ende");
  counter = 0;  //Counter zurücksetzen

  itoa(N, Ergebnis, 10);
  strcat (Ergebnis, ";");
  uart_puts(Ergebnis);



}

ISR(TIMER0_OVF_vect) {
  counter++;
  TCNT0 = 254;
}

von Hubert G. (hubertg)


Lesenswert?

Wie viele Takte macht die CPU in 1µsec.
Reicht das aus für die ISR und Code?

von S. Landolt (Gast)


Lesenswert?

Ad hoc:
> TIMSK0|=(0<<TOIE0);      //Disable Counter
Das ist sicher falsch, 'oder' mit 0 bewirkt nichts.

von spess53 (Gast)


Lesenswert?

^Hi

>TIMSK0|=(0<<TOIE0);      //Disable Counter

Damit wird nichts disabled -> 1 or 0 = 1

MfG Spess

von Sebastian W. (code)


Lesenswert?

Es funktioniert auch nicht, wenn ich den Prescaler auf 256 stelle und 
TCNT0 von 0-255 zählen lasse.

Der Controller ist extern mit 16 MHz getaktet.
Wenigstens bei Prescaler 256 sollten eigentlich genügend Takte übrig 
bleiben.

von Sebastian W. (code)


Lesenswert?

Ok wie deaktiviere ich den Timer dann richtig?
cli sollte aber schonmal den sprung in TIMER0_OVF_vect beenden, oder?

von spess53 (Gast)


Lesenswert?

^Hi

>Ok wie deaktiviere ich den Timer dann richtig?

CS02:00 auf 0

MfG Spess

von Sebastian W. (code)


Lesenswert?

Ok, danke.
Ändert aber nichts daran, dass die Do Schleife nicht beendet wird.

von Stefan E. (sternst)


Lesenswert?

Sebastian W. schrieb:
> Ändert aber nichts daran, dass die Do Schleife nicht beendet wird.

Weil ein "volatile" fehlt.

von Sebastian W. (code)


Lesenswert?

Stefan E. schrieb:
> Sebastian W. schrieb:
>> Ändert aber nichts daran, dass die Do Schleife nicht beendet wird.
>
> Weil ein "volatile" fehlt.

Tatsächlich! Jetzt funktioniert es.
Da wär ich ja im Leben nicht drauf gekommen.

Vielen vielen Dank!!

von BirgerT (Gast)


Lesenswert?

Hi,
Deine counter Variable solltest Su als
volatile uint32_t counter = 0; deklarieren

und schau doch mal, was es heisst, wenn kein Prescaler Bit gesetzt 
ist..;-)

TCR0B = Prescaler; // Timer starten
TCR0B = 0;         // Timmer off

von Sebastian W. (code)


Lesenswert?

BirgerT schrieb:
> Hi,
> Deine counter Variable solltest Su als
> volatile uint32_t counter = 0; deklarieren
>
> und schau doch mal, was es heisst, wenn kein Prescaler Bit gesetzt
> ist..;-)
>
> TCR0B = Prescaler; // Timer starten
> TCR0B = 0;         // Timmer off

Ja das mit dem Timer disable war ein dummer kleiner Fehler.
Das mit dem volatile hab ich absolut noch nicht gewusst.

Vielen Dank!

von Klaus (Gast)


Lesenswert?

Sebastian W. schrieb:
> Stefan E. schrieb:
>> Sebastian W. schrieb:
>>> Ändert aber nichts daran, dass die Do Schleife nicht beendet wird.
>>
>> Weil ein "volatile" fehlt.
>
> Tatsächlich! Jetzt funktioniert es.
> Da wär ich ja im Leben nicht drauf gekommen.

Oh. Du bist Nicht-Leser? Das kann ein Vorteil sein - oder ein Nachteil.

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.