timer0 zur Zeitmessung verwenden (AVR)

OP #2153334
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
}
Gast #2153372
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
}
Gast #2153380
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!
#2153537
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.
Gast #2153892
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)
Gast #2194920
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.

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