Timer läuft seht ungenau bei hohen Tacktraten

Gast #1396778
Lesenswert?

Hallo,

ich brauche einen 500kHz Tackt um damit ein Display anzusteuern.

Nachdem das ganze nicht funktioniert hat, hab ich das Programm mal 
zerpflückt (restliche Programmteile entfernt) und etwas komisches beim 
Timer festgestellt.


Ich hab nen At90CAN128 mit 16MHz
1
#ifndef __AVR_AT90CAN128__
2
#define __AVR_AT90CAN128__
3
#endif
4

5
#include <avr/interrupt.h>
6
#include <avr/io.h>
7
#include <stdio.h>
8

9
unsigned long test = 0;
10
int test2= 0;
11

12
int main( void )
13
{
14
    sei();
15

16
  DDRB = 0x07;
17
  PORTB = 0x02;
18

19
  //125Hz
20
//  OCR0A = 0x7D; // 0x7D = 124 & Prescaler 1024 => 125Hz  
21
//  TCCR0A =  (1<<CS02) | (1<<CS00) | (1<<WGM01);
22
//  TIMSK0 |= (1<<OCIE0A);
23

24
  //500kHz
25
  OCR0A = 0x1F; // 0x1F = 31 bei Prescaler 1 => 500kHz  
26
  TCCR0A =   (1<<CS00) | (1<<WGM01);  
27
  TIMSK0 |= (1<<OCIE0A); 
28

29
  //500kHz
30
//  OCR0A = 0x03; // 0x03 = 03 bei Prescaler 8 => 500kHz   
31
//  TCCR0A =   (1<<CS01) | (1<<WGM01);
32
//  TIMSK0 |= (1<<OCIE0A); 
33

34
  while(1)
35
  {
36
  }
37

38
}
39

40
ISR(TIMER0_COMP_vect){
41
  
42
  if (test == 500000){
43
    if(test2){
44
      test2 = 0;
45
       PORTB |= (1<<PIN2);      //Led an
46
    }else{
47
      test2 = 1;
48
      PORTB &= ~(1<<PIN2);
49
    }
50
    test = 0;
51
  }
52
  test++;
53

54
}


verwende ich ihn mit 125Hz und lasse test nur bis 125 zählen, dann 
leuchted die LED, für eine Sekunde - so weit so gut.

stelle ich aber wie im Code auf 500kHz dann leuchted sie fast 3 sek.

kann mir das jemand erklären?

ach ja welche der beiden 500kHz varianten würdet ihr bevorzugen (ändert 
nichts an meinem Problem)?

Danke,
Michi
Gast #1396792
Lesenswert?

Dein Interrupt bei 500 kHz soll alle 32 Taktzyklen aufgerufen
werden. Ist auch so eingestellt.

Aber wieviele Taktzyklen braucht die Interruprroutine?

Schreib doch mal die Antwort auf meine Frage und du hast die
Antwort auf deine Frage!

avr
Gast #1396817
Lesenswert?

uff du meinst er braucht länger für die Ausführung von
1
  if (test == 500000){
2
    if(test2){
3
      test2 = 0;
4
       PORTB |= (1<<PIN2);      //Led an
5
    }else{
6
      test2 = 1;
7
      PORTB &= ~(1<<PIN2);
8
    }
9
    test = 0;
10
  }
11
  test++;

länger als 32 taktzyklen...

hmmm, dann wird des echt schwer, da was ordentliches auf die beine zu 
stellen....

wie finde ich denn dann raus, welche operationen wieviele tacktzyklen 
brauchen? (hab leider nicht viel ahnung von Assembler)
#1396885
Lesenswert?

Michi-S schrieb:
> ein display ansteuern, dazu reichen mir auch ca. 65kHz, aber der code
> ist auch länger...

Es wäre sinnvoller, mal einen Link auf das Datenblatt des LCD zu posten.

Ein LCD ohne eigenen Controller anzusteuern, ist schon recht tricky, da 
brauchts Assembler. In der Codesammlung ist was dazu.


Peter
#1396955
Lesenswert?

Die Ansteuerung ist ja echt bescheuert...
Du könntest dir die Arbeit mit einem Trick aber stark vereinfachen:
Den Takt erzeugst du mit einem Timer im CTC Modus.
Die Daten werden synchron zu dem Takt übertragen, aber davon abgesehen 
in dem Stil wie normale UART Daten. Falls du also noch den UART frei 
hast, stell den so ein, dass er den externen Takt verwendet, und sende 
einfach die Daten per UART, das erspart einiges an Rechenleistung.
Gast #1396975
Lesenswert?

Hallo Michi-S,

da hilft nur das Datenblatt (aber das richtig).

Es ist eine normale synchrone serielle Übertragung.

Startbit, 8 Datenbit, Parity, 2xStop (Datenblatt Figur 17.4)

Die Clockeinstellung und Flanke ist auch kein Problem
Table 17.1 und Abschnitt 17.4.4

Dann läuft es alles in Hardware mit UDRx als Daten.

gruß avr

Hoffe, du hast noch eine der beiden USART frei ;)
Gast #1397828
Lesenswert?

FERTIG!!!

@dl8dtl
jetzt wo dus sagst, keine Ahnung warum das da noch drin ist, kommt davon 
wenn man alten Code schnell noch mal hernimmt zum testen ^^

aber -mmcu=at90can128 ist natürlich überall drin.

@benedikt
habs genau so gemacht wie du gesagt hast, hat priema funktioniert! 
MERCI!
Werd aber bei gelegenheit noch mal probieren ob ich den Tackt nicht 
irgendwie schöner hinbekomme (würde des auch mit der Baudrate Ausgabe 
auf XCK funktionieren oder ist dann nur beim senden Tackt da?)

Ich hab das funktionierende Programm mal in den Anhang, falls noch 
jemand auf die Idee kommt sowas zu machen.

Nur schade dass man nen uart braucht, hätte gerne die dinger mit nem 
kleinen atmel (Tiny oder so) als Treiber verwendet. So dass man dem 
Treiber entweder Daten seriell (uart dens nicht mehr gibt) oder per I2C 
schickt und der die Daten dann an die einzelnen Taster verteilt. So hätt 
ich das ganze vom PC und vom uC einfach steuern können.

Was ist denn der kleinste/billigste Atmel mit 2 Uarts?
Angehängte Dateien:
#1398004
Lesenswert?

Michi-S schrieb:

> Werd aber bei gelegenheit noch mal probieren ob ich den Tackt nicht
> irgendwie schöner hinbekomme (würde des auch mit der Baudrate Ausgabe
> auf XCK funktionieren oder ist dann nur beim senden Tackt da?)

Musst du mal ausprobieren. Dem Diagramm im Datenblatt nach könnte es so 
sein, aber eine echte Bestätigung habe ich beim Überfliegen des Textes 
nicht finden können.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren