Forum: Mikrocontroller und Digitale Elektronik 8bit-Timer Mega8


von Pat F. (breaker87)


Lesenswert?

Hey Leute!

Ich habe Probleme mit dem 8bit Timer bei meinem ATmega8.
Das Tutorial habe ich mir durchgelesen und ich habe auch andere Quellen 
im Internet durchsucht (inkl. Datenblatt) - trotzdem habe ich es nicht 
geschafft.

Wie starte ich den Timer?
Ich würde das Programm gerne so gestalten, dass alle 0,1ms (oder 0,01 
ms) ein Timeroverflow ausgelöst wird, welches dann eine long Variable 
"zeit" erhöht. Sobald dann ein "Ereignis" an einem definierten Eingang 
auftritt, soll ein "Timestamp" in ein Array gespeichert werden...

Doch zuerst hat die Funktion des Timers vorrang...

Hier mein aktueller Stand:
1
#include <mega8.h>   // include file w. SFR names
2
#include <LCDlib.h>    // include MegaPAC-LCD functions
3
#include <stdio.h>
4
5
#define Key1 PINC.1    // T1 at PC1 (active low)
6
#define Key2 PINC.2    // T2 at PC2 (active low)
7
#define Key3 PINC.3    // T3 at PC3 (active low)
8
9
#define LED1 PORTD.4   // LED 1 at PD4 (active high)
10
#define LED2 PORTD.5   // LED 2 at PD5 (active high)
11
#define LED3 PORTD.6   // LED 3 at PD6 (active high)
12
#define LED4 PORTD.7   // LED 4 at PD7 (active high)
13
14
// Declare your global variables here:
15
unsigned char n;  // global count variable
16
long zeit=0;
17
char text[16]; 
18
19
// Timer 0 overflow interrupt service routine
20
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
21
{
22
   zeit++;
23
} 
24
25
void main(void)
26
{
27
// Declare your local variables here
28
29
30
PORTB=0x00; //  0    0    0    0    0    0    0    0
31
DDRB=0x3F;  //  0    0    1    1    1    1    1    1 
32
PORTC=0x0E; //  0    0    0    0    1    1    1    0
33
DDRC=0x30;  //  0    0    1    1    0    0    0    0 
34
PORTD=0x03; //  0    0    0    0    0    0    1    1
35
DDRD=0xFE;  //  1    1    1    1    1    1    1    0 
36
UBRRH=0x00;  // UBRR = 103 Dez = 0x0067 for 9600 Bd.
37
UBRRL=0x67;
38
UCSRA=0x20;  // 
39
UCSRB=0x08;
40
UCSRC=0x86;
41
42
// Timer/Counter 0 initialization
43
// Clock source: System Clock
44
// Clock value: 16000,000 kHz
45
TCCR0=0x01;  //Prescaler 64 --> 0x01 = Standartwert
46
TCNT0=0x00;  //Vorladen mit 6 
47
48
// Timer(s)/Counter(s) Interrupt(s) initialization
49
TIMSK=0x01;
50
51
// Global enable interrupts
52
#asm("sei")
53
54
while (1)
55
{
56
InitLCD(); // initialize LCD; auto increment cursorposition
57
58
while (1)       // do forever
59
{    
60
  if (!Key1)
61
  {
62
  TCCR0=0x03;
63
  }
64
  if (!Key2)           // if T2 is active (low),
65
   {
66
    zeit = zeit/1000;
67
    sprintf(text,"%i s",zeit);
68
    SetCursLCD(1);   // set cursor to 9.th pos. again
69
    for(n=0;n<16;n++)   // write last 8 chars of welcome msg.
70
       {WrCharLCD(text[n]);}
71
   }
72
   if (!Key3)
73
   {
74
   TCCR0=0x00;
75
   }
76
  }
77
}
78
}// End of while

Ich hoffe ihr könnt mir weiterhelfen...


lg Patrick

PS: Compiler ist CVAVR

von Dennis (Gast)


Lesenswert?

TCCR1B heißt das Register glaub ich. Such mal danach, da steht drin 
welche Bits zu setzen mußt, kommt auf darauf an, ob Du einen Vorteiler 
willst.

von Pat F. (breaker87)


Lesenswert?

Ich habe mir für ein timer-Frequenz von 1000Hz bei 16MHz Clock folgende 
Werte berechnet:
Prescaler -> 64
Timervorgabewert ->6
d.h. alle 1000µs wird ein Interrupt ausgelöst...

lg

von unbeschreiblicher Rahul (Gast)


Lesenswert?

Solche Sachen macht man nicht (mehr) mit einem "manuellen" 
Timer-Nachladen, sondern mit dem CTC-Mode. Der geht bei Mega8 allerdings 
nur bei Timer1 (16Bit) und Timer2 (8Bit).

>zeit = zeit/1000;


wirr...
Long sind doch 32Bit-Integer, oder? (So riesige Zahlen benutze ich 
nie...)
Wenn man eine Zahl z.B. 5 durch 1000 teilt, bekommt man als Ergebnis 0.
Also kann Zeit nie grösser als 1 werden...

16MHz / 64 = 250000 Hz
Das würde also schon dicht an deine 1kHz herankommen.

Zumindest bei AVRgcc sollte zeit als volatile deklariert werden; wie das 
CodeVision ist, kann ich nicht sagen.

>TCNT0=0x00;  //Vorladen mit 6
Da wird nicht das veranlasst, was der Kommentar verspricht...


Nur so am Rande:
das:
PORTB=0x00; //  0    0    0    0    0    0    0    0
DDRB=0x3F;  //  0    0    1    1    1    1    1    1
PORTC=0x0E; //  0    0    0    0    1    1    1    0
DDRC=0x30;  //  0    0    1    1    0    0    0    0
PORTD=0x03; //  0    0    0    0    0    0    1    1
DDRD=0xFE;  //  1    1    1    1    1    1    1    0
UBRRH=0x00;  // UBRR = 103 Dez = 0x0067 for 9600 Bd.
UBRRL=0x67;
Ist einer der sinnfreiesten Kommentare, die ich mir vorstellen kann.

von Pat F. (breaker87)


Lesenswert?

unbeschreiblicher Rahul wrote:
> Solche Sachen macht man nicht (mehr) mit einem "manuellen"
> Timer-Nachladen, sondern mit dem CTC-Mode. Der geht bei Mega8 allerdings
> nur bei Timer1 (16Bit) und Timer2 (8Bit).
>

Ich hab leider keine ahnung wie das sonst funktioniert...

>>zeit = zeit/1000;
>
> wirr...
> Long sind doch 32Bit-Integer, oder? (So riesige Zahlen benutze ich
> nie...)

Ich will über einen Zeitraum von 2 stunden messen und das mit einer 
Genauigkeit von mindestens 1/100s - daher dachte ich an eine long 
variable...

> Wenn man eine Zahl z.B. 5 durch 1000 teilt, bekommt man als Ergebnis 0.
> Also kann Zeit nie grösser als 1 werden...
>
> 16MHz / 64 = 250000 Hz
> Das würde also schon dicht an deine 1kHz herankommen.
>
> Zumindest bei AVRgcc sollte zeit als volatile deklariert werden; wie das
> CodeVision ist, kann ich nicht sagen.
>
>>TCNT0=0x00;  //Vorladen mit 6
> Da wird nicht das veranlasst, was der Kommentar verspricht...
>
>
> Nur so am Rande:
> das:
> PORTB=0x00; //  0    0    0    0    0    0    0    0
> DDRB=0x3F;  //  0    0    1    1    1    1    1    1
> PORTC=0x0E; //  0    0    0    0    1    1    1    0
> DDRC=0x30;  //  0    0    1    1    0    0    0    0
> PORTD=0x03; //  0    0    0    0    0    0    1    1
> DDRD=0xFE;  //  1    1    1    1    1    1    1    0
> UBRRH=0x00;  // UBRR = 103 Dez = 0x0067 for 9600 Bd.
> UBRRL=0x67;
> Ist einer der sinnfreiesten Kommentare, die ich mir vorstellen kann.

Diese Komentare stammen von meinem Lehrer, bei dem wir unseren "MegaPac" 
- also unser Demoboard gebaut haben. Stammt aus einem Beispielsprogramm, 
um nicht andauernd alle In und Outputs einstellen zu müssen...


lg

von unbeschreiblicher Rahul (Gast)


Lesenswert?

>Ich will über einen Zeitraum von 2 stunden messen und das mit einer
>Genauigkeit von mindestens 1/100s - daher dachte ich an eine long
>variable...
Kann schon sein, dass in deiner ISR zeit auch hochgezählt wird.
Sobald Key1 betätigt wurde, ist es mit deiner "Uhr" aber hinfällig.

>zeit = zeit/1000;

>while (1)
>{
>InitLCD(); // initialize LCD; auto increment cursorposition

>while (1)

Was soll das erste while bewirken?
Lass es weg!


>zeit = zeit/1000;
>sprintf(text,"%i s",zeit);

solltest du lieber so machen:

sprintf(text,"%i s",zeit/1000);



Wenn dir die Zeit lieb ist.

von Pat F. (breaker87)


Lesenswert?

das while war ein "Versehen" - habs vergessen zu löschen...


wie kann ich denn den Timer dann zb mit Key1 starten?


lg

von Karl H. (kbuchegg)


Lesenswert?

> wie kann ich denn den Timer dann zb mit Key1 starten?

Ein Timer läuft sobald ein Vorteiler eingestellt ist.
Ist der Vorteiler 0, dann stoppt der Timer.

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.