Forum: Mikrocontroller und Digitale Elektronik Probleme mit timer0


von FreeMX (Gast)


Lesenswert?

Hey Forum,

ich steh gerade vor einem Problem mit mein Timer0, bzw ich hab das 
gefühl erzählt bis 255 satt wie gewollt nur 72 bevor ein Interrupt 
auslöst, Vielleicht kann mal jemand drüber schauen, weil selber find ich 
den fehler nicht.

Handet sich um nen Mega16 16Mhz
1
void timer0_init()
2
{
3
  TCCR0 |= (1<<WGM01)|  (1<<CS01) |  (1<<CS00);    /* CTC Aktiv + Prescaller 1:64        */
4
  TCNT0 = 0;                      /* TCNT Register nicht aktiv          */
5
  OCR0 = 72;                      /* alle 288 us ein interrup */
6
  TIMSK |=(1<<OCIE0);                  /* Owerflow Interrups erlauben*/
7
}
8
9
ISR (TIMER0_COMP_vect)
10
{
11
  timer0++;
12
}

also im Moment sollte der timer0 alle 288us erhöht werden, doch im 
Moment hab ich das gefühl das die Erhöhung bei etwa 1,024ms.

die Berechnung ist ja richtig oder (ORC0*Prescaller)/F_CPU

von Pandur S. (jetztnicht)


Lesenswert?

Bei 16MHz und einem Prescaler von 64 gibt es alle 4us einen Zaehlimpuls.
Und ja, wenn man auf 256 hoch zahlt ergibt das alle 1.024 ms einen 
Interrupt.

Und daraus lernt man, dass etwas mit dem Mode noch nicht stimmt. Lies 
das Kapitel CTC nochmals durch.

Allenfalls :

TIMSK |=(1<<OCIE0);   /* Owerflow Interrups erlauben*/

wird eben doch der Overflow und nicht der CTC interrupt benutzt.
Setz doch mal TCNT0 =72 und mach das im Interrupt selbst
immer wieder.
So, mit dem Overflow, wuerd's auch gehen.

von FreeMX (Gast)


Lesenswert?

ist den der Interrupt mit compare match richtig, den beim Overflow 
Interrupt bekomm ich nur müll raus.

von spess53 (Gast)


Lesenswert?

Hi

>ist den der Interrupt mit compare match richtig,

Ja.

Bist du sicher, das der Controller mit der richtigen Frequenz läuft?

MfG Spess

von FreeMX (Gast)


Lesenswert?

Ja bin ich mir hab noch nen timer1 mit 0.5Hz laufen der läuft richtig.

von Rainer B. (katastrophenheinz)


Lesenswert?

timer0 ist "volatile" deklariert?

von FreeMX (Gast)


Lesenswert?

also hab mir die Anleitung vom mega16 mehrmals durch gelesen aber auf 
den fehler komm ich einfach nicht.

WGM01 muss für CTC gesetzt sein ist

Presacaller 64 = gleich CS00 und 01 ist auch

ORC = 73-1 als Obergrenze ist gesetzt.

When the OCIE0 bit is written to one, and the I-bit in the Status 
Register is set (one), the
Timer/Counter0 Compare Match interrupt is enabled. The corresponding 
interrupt is executed if
a compare match in Timer/Counter0 occurs, that is, when the OCF0 bit is 
set in the Timer/Counter
Interrupt Flag Register – TIFR.

ist auch gemacht.

fehler ist immernoch da ....

von FreeMX (Gast)


Lesenswert?

Ja,

volatile unsigned short timer=0;

von FreeMX (Gast)


Lesenswert?

timer0=0 sollte das heißen

von spess53 (Gast)


Lesenswert?

Hi

>ORC = 73-1 als Obergrenze ist gesetzt.

Nicht der Fehler, aber für 288µs muss OCR0 auf 71 gesetzt werden.

MfG Spess

von Rainer B. (katastrophenheinz)


Lesenswert?

Poste doch mal den gesamten Code.

von Pandur S. (jetztnicht)


Lesenswert?

Es muss uebrigens nicht unbedingt der CTC sein, Overflow geht auch. Ich 
hab meine Systemticks mit dem timer0 Overflow laufen.

von FreeMX (Gast)


Lesenswert?

stimmt hatte mit 2 werten gerechnet.

hab mal die selben Einstellungen für timer2 wie für timer0 genommen 
selbe Problem.

von FreeMX (Gast)


Lesenswert?

hab jetzt auch eben ne UART konfiguiert auch diese funktioniert also 
müsste die Taktfrequenz passen.

von FreeMX (Gast)


Lesenswert?

1
#define F_CPU 16000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
#include <stdlib.h>
7
#include <stdio.h>
8
#include <stdint.h>
9
10
#define Baud    9600UL
11
#define UBBR_VALUE  ((F_CPU/(16*Baud))-1)
12
13
14
char UART_INPUT [255];
15
char UART_OUTPUT [255];
16
volatile unsigned char eingabe,counter,complete=0;  
17
volatile unsigned short timer=0,ctn=1,timer0=0,messung_start=0,messung_ende=0;
18
volatile float entfernung;
19
20
void uart_init()                    /*Inizialiserung von UART*/
21
{
22
  UBRRH = (UBBR_VALUE>>8);              /*Baudrate ins UBBR Register schreiben*/
23
  UBRRL = (UBBR_VALUE);
24
    
25
  UCSRB = (1<<TXEN) | (1<<RXEN)|(1<<RXCIE);      /* RX und TX Aktivieren , RX Interrupt aktiv*/
26
  UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);    /* Sendemodus: Synchron; 8 Bit;1 Stoppbit */
27
}
28
29
void timer0_init()
30
{
31
  TCCR0 |= (1<<WGM01)|  (1<<CS01) |  (1<<CS00);    /* CTC Aktiv + Prescaller 1:64        */
32
                        /* TCNT Register nicht aktiv          */
33
  OCR0 = 71;
34
                      /* alle 288 us ein interrup */
35
  TIMSK |=(1<<OCIE0);                  /* Owerflow Interrups erlauben*/
36
37
void uart_output(char * vektor)              /* Zeichen aus Array lesen und an Uart_senden weiterleiten */
38
{
39
  for (int a=0; a<255;a++)          /* Vektor Array um 1 erhöhen und senden*/
40
  {
41
    if(vektor[a] !=0)
42
    {
43
      uart_senden(vektor[a]);      /*Senden eines zeichen aus Vektor*/
44
    }
45
    else
46
    {
47
      break;      /*verlassen der for schleife*/
48
    }
49
  }
50
  
51
  
52
}          
53
54
char uart_empfang()                    /*abholung neuner daten vom BUS*/
55
{
56
  while(!(UCSRA & (1<<RXC)))
57
  ;
58
  return UDR;
59
}
60
61
void uart_speichern(char *pointer)            /* Speichert Zeichen in einem String*/
62
{
63
  eingabe = uart_empfang();
64
    
65
  if (complete == 0) /*Solange String nicht komplett oder zwischengespeichert*/
66
  {
67
      
68
    if (eingabe == 13)/* 13 = new line*/
69
    {
70
      
71
      pointer[counter] = 0;    /* wenn newline variable von vorne beginnen*/
72
      counter = 0;
73
      complete = 1;
74
                      /*unterbricht die while schleife*/
75
    }
76
      
77
    else
78
    {
79
    
80
      pointer[counter] = eingabe;  /*sonst nächstes zeichen scheiben*/
81
      counter++;
82
      complete = 0;
83
        
84
    }
85
  }
86
}
87
88
ISR(USART_RXC_vect)                    /* Interrupt wenn RX zeichen empfängt*/
89
{
90
  uart_speichern(UART_INPUT);  /* Zeichen in UART_INPUT speichern*/
91
}
92
93
ISR (TIMER0_COMP_vect)
94
{
95
  timer++;
96
}
97
98
99
int main(void)                      /*HAUPTPROGRAMM*/
100
{
101
  uart_init();                    /* Uart_Init ausführen*/
102
  
103
  int0_init();
104
  timer0_init();
105
  sei();                        /* Globale Interrups Aktivieren*/
106
     
107
   while (1)                      
108
    {
109
    if (complete == 1)
110
    {
111
    entfernung = (0.03434 * (messung_ende - messung_start) * 288.000)/2.000;    /* Entfernung in cm        */
112
    
113
    dtostrf(entfernung , 0 , 2 ,UART_OUTPUT);  /*float to array*/  
114
    uart_output(UART_OUTPUT);
115
    uart_output(" cm");
116
    uart_output("\r\n");
117
    utoa (messung_ende-messung_start,UART_OUTPUT,10);
118
    uart_output(UART_OUTPUT);
119
    uart_output("\r\n");
120
    utoa (timer,UART_OUTPUT,10);
121
    uart_output(UART_OUTPUT);
122
    uart_output("\r\n");
123
    
124
    complete = 0;
125
    }
126
      
127
  }
128
}

von FreeMX (Gast)


Lesenswert?

OH Doch wie meinste das einfach als normal mode 1 konfiguieren das 
ganze?

von FreeMX (Gast)


Lesenswert?

So hab es jetzt hinbekommen.

von Holger L. (max5v)


Lesenswert?

Interessehalber, woran lag es,
der Funktion uart_speichern() in der ISR?

von FreeMX (Gast)


Lesenswert?

ne der fehler liegt komplett an der Hardware -.- die Erkennung der 
flanken über INT0 in us Bereich bekommt er nicht hin.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

FreeMX schrieb:
> also im Moment sollte der timer0 alle 288us erhöht werden, doch im
> Moment hab ich das gefühl das die Erhöhung bei etwa 1,024ms.

> ne der fehler liegt komplett an der Hardware -.- die Erkennung der
> flanken über INT0 in us Bereich bekommt er nicht hin.

 Abgesehen davon, dass dies nicht stimmt - was hat das mit deiner Frage
 zu tun ?

von FreeMX (Gast)


Lesenswert?

hab ich jetzt auch gemerkt nen ganzen Tag rum probiert und schuld war 
nen rechen fehler um Faktor 10. hab es jetzt Korrigiert und nun läuft es 
fehler frei.

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.