Timer0 und TIMSK0

Hallo Zusammen,

das ist hier mein erster Beitrag und hoffe, dass Ihr mir dabei helfen könnt.

Ich versuche die Timer in Atmel320p zu verstehen. Ich habe ein Code geschrieben welche am pin D12 an Arduino nano ein Signal generiert. Das overflow Interrupt von Timer0 wird abgefangen und pin D12 getoggelt. Wie erwartet, ohne prescaling und TIMSK0 |= (1<<TOIE0) kriege ich am pin ein Signal mit f = 16MHz/256/2 = 31,2 kHz.

Ich habe spielerisch den Register mit TIMSK0 |= (1<<TOIE0) | (1 << OCIE0A) initialisiert. Jetzt bekomme ich ein Frequenz von 25 kHz. Warum sinkt die Frequenz wenn ich das Compare A Interrupt dazu schalte?

Ich würde mich auf jede Erklärung sehr freuen.

#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER0_OVF_vect) {
	
	PORTB ^= (1 << DDB4); // toggle pin
	
	TIFR0 |= 1; // reset  flag
}

int main(void)
{
	TCNT0 = 0;
	TIMSK0 |= (1<<TOIE0); // ca. 31.2 kHz an pin D12
	//TIMSK0 |= (1<<TOIE0) |(1 << OCIE0A) ; // ??? 25.0 kHz an pin D12 ???
	TCCR0B |= (1 << CS00); // no scaler 
	DDRB = (1 << DDB4); // arduino pin 11 -> output
	sei();
    while(1)
    {
	}
}

Wenn du den Interrupt aktivierst solltest du auch eine ISR erstellen. Sonst kann es sein dass der Controller einfach ins Nirvana springt weil in dem Interruptvektor eine 0 steht

#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER0_OVF_vect)
{
  PINB = (1 << DDB4); // toggle pin
}

ISR(TIMER0_COMPA_vect)
{
}

int main(void)
{
  TCNT0 = 0;
  TIMSK0 |= (1 << TOIE0); // ca. 31.2 kHz an pin D12
  TIMSK0 |= (1 << TOIE0) |(1 << OCIE0A) ; //31.25 kHz an pin D12 !!!
  TCCR0B |= (1 << CS00); // no scaler
  DDRB = (1 << DDB4); // arduino pin 11 -> output
  sei();
  while (1)
  {
  }
}

Serenifly:
Wenn du den Interrupt aktivierst solltest du auch eine ISR erstellen. Sonst kann es sein dass der Controller einfach ins Nirvana springt weil in dem Interruptvektor eine 0 steht

Ok vielen Dank. Das klappt..

combie:

#ifndef F_CPU

#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER0_OVF_vect)
{
 PINB = (1 << DDB4); // toggle pin
}

ISR(TIMER0_COMPA_vect)
{
}

int main(void)
{
 TCNT0 = 0;
 TIMSK0 |= (1 << TOIE0); // ca. 31.2 kHz an pin D12
 TIMSK0 |= (1 << TOIE0) |(1 << OCIE0A) ; //31.25 kHz an pin D12 !!!
 TCCR0B |= (1 << CS00); // no scaler
 DDRB = (1 << DDB4); // arduino pin 11 -> output
 sei();
 while (1)
 {
 }
}

Vielen Dank. Aber sollte der TIFR0 nicht resetet werden ?

karlma:
Vielen Dank. Aber sollte der TIFR0 nicht resetet werden ?

Das macht die HW, wenn sie die ISR aufruft.

. Sonst kann es sein dass der Controller einfach ins Nirvana springt weil in dem Interruptvektor eine 0 steht

Nicht ganz, aber fast.
Die Zeit bleibt auf jeden Fall beim Versagen auf der Strecke liegen.

Disassembly of section .text:

00000000 <__vectors>:
   0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
   4: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
   8: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
   c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  10: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  14: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  1c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  20: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  24: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  28: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  2c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  30: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  34: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  38: 0c 94 40 00 jmp 0x80 ; 0x80 <__vector_14>
  3c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  40: 0c 94 41 00 jmp 0x82 ; 0x82 <__vector_16>
  44: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  48: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  4c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  50: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  54: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  58: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  5c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  60: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
  64: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>

00000068 <__ctors_end>:
  68: 11 24       eor r1, r1
  6a: 1f be       out 0x3f, r1 ; 63
  6c: cf ef       ldi r28, 0xFF ; 255
  6e: d8 e0       ldi r29, 0x08 ; 8
  70: de bf       out 0x3e, r29 ; 62
  72: cd bf       out 0x3d, r28 ; 61
  74: 0e 94 46 00 call 0x8c ; 0x8c <main>
  78: 0c 94 58 00 jmp 0xb0 ; 0xb0 <_exit>

0000007c <__bad_interrupt>:
  7c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

Ok, vielen Dank erstmal.. Ich habe jetzt das CTC Mode. Ich habe OCR0A = 1 mit der Gedanke, dass
f = 16 MHz / (2*(1 +1 )) = 4MHz .. Was ich bekomme ist f = 205KHz. Wo ist mein Denkfehler?

#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER0_OVF_vect) {
}

ISR(TIMER0_COMPA_vect) {
	PORTB ^= (1 << DDB4); // toggle pin
}

int main(void)
{
	TCNT0 = 0;
	TIMSK0 |= (1<<TOIE0) |(1 << OCIE0A) ;
	TCCR0B |= (1 << CS00); // no scaler 
	TCCR0A |= (1<<WGM01); // CTC  Mode
	OCR0A = 1; // 16 MHz /(2 * 2) = 4MHz ??? ich bekomme 205kHz
	DDRB = (1 << DDB4) ; // arduino pin 11 -> output
	sei();
    while(1)
    {
	}
}

Hallo,

mit Interrupt schaffst du keine 4MHz. Du musst einen Pin am Timerausgang direkt toggeln. Die ISR selbst benötigt auch paar Takte zur Abarbeitung bis die Zeile toggeln abgearbeitet wird.
Etwas kann man noch rausholen per PIN Register statt PORT.
PINB = (1 << 4)

Da ist der ATMega zu langsam, dass schaffst Du nicht per Interrupt. Wenn Du so hohe Frequenzen willst, musst Du die HW den Pin toggeln lassen (Pin OC0A)

OK, zu langsam :wink:

Super, ich kann jetzt 8 MHz an dem Pin messen :slight_smile: .