hilfe für neueinsteiger - timerprogramierung

Gast #1658449
Lesenswert?

Hallo liebe Gemeinde,

bin nun auch dem avr´s verfallen :) (..mache grad nen e-techniker), tue 
mich aber noch ein bissel schwer mit der programierung. c/c++ 
grundkennisse sind vorhanden.

ich versuch mich am stk500 mit nem atmega 8 (4mhz ext. quartz), atmega16 
&8815 wären auch vorhanden.

ich versuche mich gerade am timer. hab dazu ein testprogramm geschrieben 
(ja ich weis sollte besser über interupts geschehen, aber ich muss 
erstmal den timer verstehen bevor ich mit interrupts beschäftige, von 
daher verzeiht mir)

nun mein problem: der counter läuft nicht so wie ich gern möchte. er 
sollte im sekundentakt auf einem lcd hochzählen. läuft aber viel zu 
schnell (so mit gefühlen 1000hz - brauch also eine sekunde für nen 
durchlauf) am lcd.


hier mein prog:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include "lcd-routines.h"
4
 
5
unsigned char  z;
6
int s = 0;
7
short a = 0;
8

9

10
int main()
11
{
12

13
lcd_init(); // LCD init
14

15
TCCR0 = (1<<CS01) | (1<<CS00);  // Prescaler Timer0 auf 1024 setzn
16

17
DDRB  = 0x00;  // Port B als Ausgang setzen
18

19

20
do{
21
  do{
22
    
23
    do{
24
    z = TIFR;  // Timer Counter Register auslesen
25
    z = z & 0x01; // Timer Interupt Flag (TOV0) mit Logisch 1 vergleichen 
26
    }
27

28
    while (z == 0); // Schleife solange wie TOV0 nicht gesetzt (Logisch 0)
29

30
  s=s+1; // "s" um 1 erhöhen 
31
  TIFR = (0<<TOV0); // Timer Interupt Flag (TOV0) zurücksetzen
32
  }
33
  while (s<15); // Schleife solange wie "s" < 15 (4Mhz/256/1024/15 sollte rund 1 Hz sein)
34

35
s=0;  // Schleifenzähler "s" zurücksetzen
36
a=a+1; // Zähler für LCD Ausgabe um 1 erhöhen
37

38
  {
39
  char b[5]; // b definieren
40
    itoa( a, b, 10 ); // übergabe int a >> char b
41
  set_cursor (0,1); // cursor pos setzen
42
  lcd_string( b ); // Anzeige b
43
   }
44
}   
45
while (a<1000); // bei LCD Anzeige 1000 beenden
46

47
return 0;
48
}


ich hab alles schön mit "remarks" meiner gedankengänge gefüllt. helft 
mir bitte meine "irrungen" zu finden.

grüsse swen
#1658458
Lesenswert?

Diese Interrupt Flags werden anders zurückgesetzt

Nicht
  TIFR = (0<<TOV0); // Timer Interupt Flag (TOV0) zurücksetzen

sondern
  TIFR = (1<<TOV0); // Timer Interupt Flag (TOV0) zurücksetzen

(Ja das stimmt. Man schreibt eine 1 an die Position, an der man das Flag 
zurückgesetzt haben will)
Gast #1658475
Lesenswert?

danke!,

das hätt ich wissen müssen, habs beim hier angebotenen tutorial 
gelesen..

-> achja wobei natürlich das "TOV0" nen overflow flag ist und kein 
interupt flag (tut aber programmtechnisch nix zu sache..) mein fehler :(

jetzt läuft wesentlich langsamer aber immer noch so mit 15hz zählrate.

hab ich da ne falsche vorstellung von der teilung des zählers?
Gast #1658511
Lesenswert?

spess53 schrieb:
> Ein 8-Bit-Timer hat bei 4MHz und Vorteiler 1024 eine Overflowtime von
> ca.65ms. Und 1/65ms macht ca. 15Hz.


genau deswegen mache ich ja ne schleife mit 15 counts bevor am lcd 
höchgezählt wird.

[c]
while (s<15); // Schleife solange wie "s" < 15 (4Mhz/256/1024/15 sollte 
rund 1 Hz sein)
/[c]

hab trozdem keine 1Hz.

hab mal probehalber die schleife auf 250 gesetzt. ha sind ungefähr 1hz 
zählrate. mir ist das so wichtig weil ich einen frequenzzähler basteln 
möchte
#1658515
Lesenswert?

Nachmal ins Datenblatt:

Das hier
TCCR0 = (1<<CS01) | (1<<CS00);  // Prescaler Timer0 auf 1024 setzn

ist kein Vorteiler von 1024

(Und tu dir selbst einen Gefallen und sorg für ein sauberes 
Erscheinungsbild deines Codes. Du schiesst dich nur ins eigene Knie, 
wenn du es nicht tust. Einrückungen sollen konsistent sein. AUs 2 Meter 
Entfernnung soll erkennbar sein, welche Codeteile zusammen gehören und 
welche nicht. Viele Leerzeilen hintereinander ziehen den Code nur in die 
Länge, erhöhen aber nicht die Übersicht)
Gast #1658531
Lesenswert?

Karl heinz Buchegger schrieb:
> (Und tu dir selbst einen Gefallen und sorg für ein sauberes
> Erscheinungsbild deines Codes. Du schiesst dich nur ins eigene Knie,
> wenn du es nicht tust. Einrückungen sollen konsistent sein. AUs 2 Meter
> Entfernnung soll erkennbar sein, welche Codeteile zusammen gehören und
> welche nicht. Viele Leerzeilen hintereinander ziehen den Code nur in die
> Länge, erhöhen aber nicht die Übersicht)


jo werd ich ab jetzt machen. asche auf mein haupt
#1658551
Lesenswert?

Du sollst auch den 'natürlichen' Schleifentyp für eine Aufgabe benutzen. 
Wenn du Dinge abzählen willst, dann benutze eine for-Schleife. Dort hast 
du
  * Startwert
  * Endwert (und damit implizit die Anzahl der Wiederholungen)
  * den Wert um den erhöht wird
an einer Stelle beisammen und nicht quer über den ganzen Code verstreut

So könnte das zb aussehen
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include "lcd-routines.h"
4
 
5
uint8_t  NrTimerLoops;
6
uint16_t Counter = 0;
7

8
int main()
9
{
10
  DDRB  = 0x00;  // Port B als Ausgang setzen
11
  lcd_init();    // LCD init
12

13
  TCCR0 = (1<<CS01) | (1<<CS00);  // Prescaler Timer0 auf 64 setzn
14

15
  for( Counter = 0; Counter < 1000; Counter++ ) {
16

17
    // 15 Wiederholungen
18
    // 4Mhz/256/1024/15 -> 1Hz
19
    for( NrTimerLoops = 0; NrTimerLoops < 15; NrTimerLoops++ ) {
20

21
      while( TIFR & (1<<TOV0) )     // auf eine 1 im TOV0 Bit warten
22
        ;                           // -> der Timer ist übergelaufen
23
      TIFR = (1<<TOV0);             // Timer Interupt Flag (TOV0) zurücksetzen
24
    }
25

26
    {
27
      char b[5];                 // b definieren
28
      utoa( Counter, b, 10 );    // übergabe int a >> char b
29
      set_cursor (0,1);          // cursor pos setzen
30
      lcd_string( b );           // Anzeige b
31
    }
32
  }
33

34
  return 0;
35
}
Gast #1658573
Lesenswert?

danke für die mühe karl heinz,

mit der for- schleife ist natürlich viel besser!

wobei wir natürlich

TCCR0 = (1<<CS02) | (1<<CS00);

setzen müssen sonst wird es nichts mit prescaler 1024 ;-).

ich habs gerade mal reingespielt. es hängt bei "178". werd mich dann mal 
dransetzen, muss wersmal ausser haus was erledigen gehen...

bis später

grüsse
swen

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