mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik timer geht nicht


Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe folgendes Problem. ich möchte, dass mein Mikrocontroller die 
Daten im 50 Hz Takt rausschickt. Dafür habe ich

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0xB8;
i++;
 }

void main(void)
{TCCR0=0x05;

while (1)

  {

       if (i == 1)
      {
      printf("M");
      i=0;
}}}

Leider wird das M aber manchmal mit 50Hz geschickt und dann wieder 
nicht.
ich habe ein externes 3,6864MHz quarz drauf und einen ATmega8L.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist i deklariert? Wenn es nicht volatile ist, könnte das zu 
Problemen führen, da es sowohl in der ISR als auch im Hauptprogramm 
benutzt wird.

Schicke demnächst doch bitte einen vollständigen (lauffähigen) Code.

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
i ist als volatile int deklariert. Hier ist der ganze Code.

#include <mega8.h>
#include <stdio.h>

volatile int i=0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

  TCNT0=0xDC;
   i++;
}


void main(void)
{
PORTB=0x00;
DDRB=0x00;

PORTC=0x00;
DDRC=0x00;

PORTD=0x00;
DDRD=0x02;

TCCR0=0x05;
TCNT0=0x00;

TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
TIMSK=0x01;

UCSRA=0x00;
UCSRB=0x08;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;


ACSR=0x80;
SFIOR=0x00;


#asm("sei")

while (1)
      {if (i==1)
      {

     printf("M");

      i=0;
      }


      };
}

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weiß denn keiner woran es liegen könnte?
Ich bekomme ca. 20 mal das M mit 50Hz dann längere Zeit nichts und dann 
wieder 20 mal das M mit 50 Hz.
Im Code muß es natürlich TCNT0=0xB8 anstelle von TCNT0=0xDC heißen um 50 
Hz zu bekommen.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast ziemlich sicher eine Race-Condition:
In deinem Pgm laufen 2 Dinge 'gleichzeitig' ab.
Der Overflow Interrupt versucht i zu erhöhen, während
in der Schleife das kontinuierlich auf 0 zurückgesetzt
wird.

Wenn der Interrupt nur schnell genug ist, dann erhöht er
dir i auf 2 und damit ist die hauptschleife erst mal
lahmgelegt. Die muss warten, bis der Overflow das i weiter-
gezählt hat
 2, 3, 4, 5, ....., 32767, -32768, -32767, -32765, ... -1, 0, 1
bis der if in der Hauptschleife das nächste mal zuschlägt.

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber warum funktioniert es denn manchmal, dass ich die Daten in 50Hz 
Absatnd bekomme und manchmal nicht. Eigentlich müßte das Overflow 
Interrupt doch dann immer schneller sein als die Schleife.
Auch wenn ich den Timer langsamer mache klappt es nicht.
Wie kann ich das denn vielleicht auch anders lösen?

Autor: unsichtbarer WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Liegt vielleicht daran...
>printf("M");

Mit UDR = 'M';
sollte es wesentlich "schneller" gehen.

Man könnte auch einen Zähler von 33 bis 127 durchlaufen lassen und den 
aktuellen Wert ausgeben lassen; so etwa:

if (i)
{
 UDR = z++;
 if (z==128) z = 33;
}

Ansich müssten die Daten ja schon verschickt worden sein, wenn die 
nächsten ins UDR geschrieben werden.
Sonst müsste man das UDRE-Flag noch abfragen...

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es jetzt printf("M") durch UDR='M' ersetzt und habe das gleiche 
Problem, dass die Daten nicht mit konstanten 50Hz geschcikt werden.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anstatt
if (i == 1)
{
//...
}
einfach
if (i >= 1)
{
//...
}

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Holger wrote:
> Aber warum funktioniert es denn manchmal, dass ich die Daten in 50Hz
> Absatnd bekomme und manchmal nicht. Eigentlich müßte das Overflow
> Interrupt doch dann immer schneller sein als die Schleife.
> Auch wenn ich den Timer langsamer mache klappt es nicht.

Weil der Zeitbedarf für einen Interrupt und der Zeitbedarf
für den print nicht gleich ist. Wenn du in 1.3 Sekunden
Abständen auf deine Uhr siehst, dann siehst du den Sekunden
zeiger zunächst auf der 1, dann auf der 2, dann auf der 3.
Bis jetzt sind 3 * 1.3 Sekunden also 3.9 Sekunden vergangen.
Wenn du das nächste mal auf die Uhr siehst, sind aber schon
5.2 Sekunden vergangen. D.h. du siehst den Sekundenzeiger auf
der 5. Auf der 4 hast du ihn nie gesehen.

> Wie kann ich das denn vielleicht auch anders lösen?

Versteif dich halt nicht darauf, dass i in der Hauptschleife
genau den Wert 1 haben muss. Alles was nicht 0 ist (also
1 oder 2 oder was auch immer), sagt dir, dass der Overflow
erfolgt ist:

       if (i != 0)

und schon sollte es gehen.




Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt in der Hauptschleife if (i != 0) gesetz und immer noch 
das gleiche Problem.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich habe jetzt in der Hauptschleife if (i != 0) gesetz und immer noch
> das gleiche Problem.

Seltsam.
Hab keine Erklärung mehr dafür.

Zeig noch mal das jetztige Programm.

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <mega8.h>


#include <stdio.h>

volatile int i=0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

  TCNT0=0xDC;
   i++;
}


void main(void)
{
PORTB=0x00;
DDRB=0x00;

PORTC=0x00;
DDRC=0x00;

PORTD=0x00;
DDRD=0x02;

TCCR0=0x05;
TCNT0=0x00;

TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
TIMSK=0x01;

UCSRA=0x00;
UCSRB=0x08;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;


ACSR=0x80;
SFIOR=0x00;


#asm("sei")

while (1)
      {if (i !=0)
      {

     UDR = 'M'; //egal auch mit printf("M") nicht

      i=0;
      }


      };
}

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Holger wrote:

> Leider wird das M aber manchmal mit 50Hz geschickt und dann wieder
> nicht.

Woher weißt Du denn überhaupt, daß es nicht klappt ?

Überprüfst Du das mit nem Oszi ?

Mit nem Terminalprogramm (PC) kannst Du es jedenfalls nicht überprüfen, 
da Du dort Zeitscheiben zugeteilt bekommst.


Peter

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja mit dem Oszi.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Triggert Dein Oszi auch richtig ?

Simuliers doch einfach mal (Avrstudio).


Peter

Autor: unsichtbarer WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass dann doch mal einen Pin togglen.
Dann könnte man auch überprüfen, ob deine Timer-ISR richtig geht.

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß zwar nicht was toggeln ist, aber ich habe einen Pin kurz high 
und wieder low geschaltet und habe dabei immer noch das gleiche problem.

Autor: unsichtbarer WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
togglen: einen Pin kurz high und wieder low schalten
Liegt also nicht am USART...

Guckt dir mal den CTC-Mode des Timers an, der produziert dir einen 
wunderschöne Frequenz durch einmaliges Konfigurieren (und vorheriges 
Rumgerechne...).

Autor: Holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie kann  ich mir denn den CTC-Mode des Timers anschauen?
Ich bin kein Experte, sondern eher Anfänger.

Autor: unsichtbarer WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie kann  ich mir denn den CTC-Mode des Timers anschauen?
Im Datenblatt (complete datasheet) ist der neben allen anderen 
beschrieben...

>Ich bin kein Experte, sondern eher Anfänger.
Macht ja nichts...

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.