Forum: Mikrocontroller und Digitale Elektronik timer0 zur Zeitmessung verwenden (AVR)


von Peter M. (peter0815)


Lesenswert?

Hallo !
ich habe ein Problem:

Ich verwende einen Teensy2.0 auf dem ein Atmega32u4 verbaut ist. Damit 
möchte ich mit dem 8-Bit Timer0 alle 10 Mikrosekunden ein Interrupt 
werfen.

Das Problem ist dass die der Timer nur mit dem TOP-Wert (255), nicht mit 
dem von mir fesgtelegten OCR0A Wert verlgeicht. Zum programmieren 
verwende ich die Arduino IDE.

Danke im Voraus

Hier der Code:
1
#include <avr/interrupt.h>
2
3
ISR(TIMER0_COMPA_vect){
4
5
  digitalWrite(pin4,!digitalRead(pin4));
6
7
}
8
9
void setup(){ 
10
11
  //setting waveform generation mode
12
  TCCR0A |= ( _BV( WGM01 ) ); // page 104 ( Mode 2 (Table 13-8))
13
  
14
  //setting the prescaler to 1/8
15
  TCCR0B &= ~(_BV( CS02 ) | _BV( CS00 )); 
16
  TCCR0B |= (_BV( CS01 )); 
17
  
18
  OCR0A = 20;
19
  
20
  //enable interrupt for a
21
  TIMSK0 |= ( _BV( OCIE0A ) ); 
22
  TCNT0 = 19;  
23
} 
24
25
void loop(){
26
  
27
}

von Helfer (Gast)


Lesenswert?

1
/*
2
   Atmega32u4 (http://atmel.com/dyn/resources/prod_documents/doc7766.pdf)
3
   F_CPU 16 MHz (http://www.pjrc.com/teensy/)
4
*/
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
8
#ifndef F_CPU
9
#define F_CPU 16000000UL
10
#endif
11
12
ISR(TIMER0_COMPA_vect)
13
{
14
  digitalWrite( pin4, !digitalRead(pin4) );
15
}
16
17
void setup(void)
18
{ 
19
  //setting Clear Timer on Compare Match (CTC) Mode
20
  TCCR0A = ( _BV( WGM01 ) ); // page 104 ( Mode 2 (Table 13-8))
21
  
22
  /*
23
     Berechnung des OCR0A Werts
24
     F_CPU = 16000000, Ziel: 10ms
25
     OCR0A+1 = F_CPU / Prescaler / (1000ms/10ms)
26
27
     Prescaler    OCR0A+1   Anm.
28
     =========================================
29
     1            160000     8-Bit Overflow
30
     8             20000     8-Bit Overflow, tauglich bei 16-Bit Timer
31
     64             2500     8-Bit Overflow, tauglich bei 16-Bit Timer
32
     256             625     8-Bit Overflow, tauglich bei 16-Bit Timer
33
     1024            156.25  Kein ", aber nicht exakt 10ms!
34
35
     Zeit zw. ISR = (OCR0A+1) * Prescaler * 1000 / F_CPU  ms
36
37
     Prescaler 1024
38
     OCR0A+1  Zeit zw. ISR   Fehler
39
     ==============================
40
     156       9,984 ms      -0,16%
41
     157      10,048 ms      +0,48%
42
  */
43
  OCR0A = (F_CPU / 1024 / (1000/10)) - 1;
44
45
  //setting the prescaler to 1024
46
  TCCR0B = (_BV( CS02 ) | _BV( CS00 )); 
47
  
48
  //enable interrupt for a
49
  TIMSK0 |= ( _BV( OCIE0A ) ); 
50
} 
51
52
void loop(void)
53
{
54
}

von Helfer (Gast)


Lesenswert?

> Mikrosekunden

Sorry, habe das nicht genau gelesen und ms verwendet. Prescaler 8 und 
OCR0A = 20-1 = 19 passt bei 10 µs.

Deine Interrupts kommen dann bei 10 µs alle 160 Takte. Wie lange 
brauchen die Funktionen digitalRead() und digitalWrite() plus der 
Overhead für das Anspringen und Verlassen der ISR? Das müssen zusammen 
weniger als 160 Takte sein, damit keine IRQs verloren gehen!

von Peter M. (peter0815)


Lesenswert?

Danke für die wirklich schnelle Antwort !

Die Funktionen digitalWrite() und digitalRead() brauchen ca. 40 Zyklen.
Ich habe bei OCR0A auch höhere Werte probiert aber auch da das Problem, 
dass immmer bis TOP gezählt wird.

von Ralf (Gast)


Lesenswert?

In der Interruptroutine einfach den Startwert festlegen (256-20) und 
dann bis TOP zählen lassen?

von Stefan E. (sternst)


Lesenswert?

Peter M. schrieb:
> dass immmer bis TOP gezählt wird.

Wie genau stellst du das fest?

Davon abgesehen:

Peter M. schrieb:
> Die Funktionen digitalWrite() und digitalRead() brauchen ca. 40 Zyklen.

Jeweils? Und wenn das womöglich noch echte und nicht ge-inline-te 
Funktionen sind, dann kommen noch mal ca 50 Takte zusätzlicher Overhead 
in der ISR selber dazu. Und das alles, um (anscheinend) lediglich einen 
Pin zu toggeln.
Umständlicher und aufwändiger geht es wohl kaum.

von Peter M. (peter0815)


Lesenswert?

Das Programm ist deswegen so einfach um den Fehler zu finden. Es ist nur 
ein Auszug aus einem anderen. Ich habe das Signal mit einem Oszilloskop 
ausgemessen und die gesamte Periodendauer ist 255 Mikrosekunden ( Bei 
8-Bit Timer = TOP). Die Funktionen SIND inline.

von spess53 (Gast)


Lesenswert?

HI

Bist du sicher, das du das richtige Programm flashst?

MfG Spess

von Peter M. (peter0815)


Lesenswert?

ja, da bin ich mir ziemlich sicher ;-)

von Helfer (Gast)


Lesenswert?

Der Sourcecode sieht für mich (und wohl auch die anderen Leser) sauber 
aus.

Deshalb ist die Frage nach dem Binärfile nicht abwegig. Fehler bei der 
Definition eines µC in der Toolchain und/oder flashen eines veralteten 
Binärfiles wurden schon beobachtet.

Wenn du nicht weiter kommst: Den Inhalt des µC mal auslesen und 
anhängen, so dass man das in den Simulator laden kann. Dort dann 
Register TCCR0A nach dem setup() auslesen und mit dem Datenblatt 
vergleichen, ob wirklich der CTC Modus gesetzt wird. Der Prescaler 
(TCCR0B) ist ja anscheinend OK (16 MHz, Prescaler8, TOP 255 => 255 µs 
ist richtig)

von Peter M. (peter0815)


Lesenswert?

Simulator ?
Bietet AVR Studio diese Möglichkeit ?
Und wie liest man überhaupt den Inhalt eines µControllers aus ? Sry 
damit hab ich mich noch nie befasst.
Hab auf die Schnelle auch nichts wirklich verständliches finden können.

von Eingehirner (Gast)


Lesenswert?

Das AVR-Studio bietet die Möglichkeit, deinen Quellcode zu simulieren. 
Allerdings weiß ich nicht, ob nur Assembler oder auch C...

Einfach Strg+F7 ("build and run") drücken statt nur F7 ("build"), dann 
wird der Code compiliert und der Simulator gestartet. Mit F11 gehst du 
dann immer einen Befehl weiter. Der Simulator zählt die Takte mit und 
zeigt sie links oben an, genauso wie (bei korrekt eingestellter 
Frequenz) die verstrichene Zeit. Die Inhalte der einzelnen Register, 
Ports etc. kannst du dir auch zu jedem Zeitpunkt anzeigen lassen.

Auslesen kannst du ihn, wenn du dir das Dialogfenster vom AVR-Studio mit 
dem µC anschaust, über diverse Buttons. Da, wo du ihn 
programmierst/schreibst, kannst du ihn auch auslesen und verifizieren 
(d.h., automatisch auslesen und mit deinem Hex-File vergleichen) lassen. 
Dort kommst du hin, wenn du den rechten "IC"-Button im AVR-Studio 
anklickst.

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.