Jaký nejjednodušší generátor frekvence?

Zatím jsem timer/counter používal jen na nějaká periodická přerušení. Takže nějaké další funkce teprve začínám zkoumat.

Teď ale vyvstala potřeba generovat na nějaký výstup ferkvenci cca 200kHz, která se nebude měnit , jen na vnější událost (komparátor) zapínat, nebo vypínat.
Jedná se o AtMega 8
Po hodinovém studiu datasheetu se mi jako nejlepší jeví použít timer/counter1 mode: CTC, TOP=OCR1A=0x0027(pro 8MHz), výstup OC1A jako toggle on compare match.

  1. Budu mít na výstupu OC1A zvolenou frekvenci ? Nemám momentálně k dispozici ani osciloskop ani čítač.

  2. Používáte nějaké jiné řešení.

S tímhle nastavením bude mít compare match frekvenci 200kHz. Pokud budeš při každé události negovat výstup, výsledná frekvence bude poloviční. Máš to tedy SKORO dobře :slight_smile:.
OCR1A=0x13

Dík za upozorněnění, i když zatím mi to moc nechodí - zkusil jsem tam dát nižší frekvenci - 100Hz abych to byl schopný změřit na zkoušku multimetrem, ale jaksi se nemůžu ničeho doměřit.
Když jsem zkusmo přepínal výstup v přerušení od timeru, tak to chodilo, ale přeušení nechci používat - zdá se mi to zbytečné.

Příhoď kód s nastavením timeru.

hodnoty TCNT/OCR1A jsou pro 50Hz

toto nefunguje:

[code]#include <mega8.h>

void main(void)
{

DDRB=0x02; //PORTB.1 jako výstup
// Timer/Counter 1 initialization
// Clock source: System Clock
// dělička 1/64
// Mode: Normal top=FFFFh
// OC1A output: Toggle
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x40;
TCCR1B=0x03;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x04;
OCR1AL=0xE1;
OCR1BH=0x00;
OCR1BL=0x00;

while (1)
{
}
}[/code]

toto ano[code]#include <mega8.h>

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
TCNT1H=0xFB;
TCNT1L=0x1E;
PORTB.1=~(PORTB.1); //takto se neguje vystup v CV
}

void main(void)
{
DDRB=0x02; //PORTB.1 jako vystup

// Timer/Counter 1 initialization
// Clock source: System Clock
// dělička 1/64
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x03;
TCNT1H=0xFB;
TCNT1L=0x1E;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

TIMSK=0x04; //povoleni preruseni od timeru

ACSR=0x80; // Analog Comparator: Off

// Global enable interrupts
#asm(“sei”)

while (1)
{

  };

}[/code]
je to sice zápis z codevisionu, ale myslím že srozumitelný každému

ještě jsem to zkusil v simulátoru AVR studia - dal jsem ještě přerušení na compare A match a sledoval co se děje na pinu PORTB.1 a nedělo se nic - zato se přepínal PINB.1 !!??

Srozumitelný sice kód je, ale ta magická čísla luštit nehodlám.
Tu je funkční blikátko 2Hz pro gcc, z něho bys měl zvládnout vytvořit co potřebuješ.

[code]#include <avr/io.h>

void timer1Init(void)
{
//
ICR1 = 1952; // 4Hz -> blikani 2Hz
TCCR1A |= 1<<COM1A0; // Toggle OC1A on Compare Match
TCCR1B |= 1<<WGM13 | 1<<WGM12 | 1<<CS12 | 1<<CS10;
// CTC, TOP = ICR1, start timer, clkI/O/1024 (From prescaler)
}

void main(void)
{
DDRB |= 1<<PB1; // OC1A as output

timer1Init();

for(;;)
{
	//

} 

}[/code]
Simulovat timery v avr studiu bývá ztráta času, jsou tam chyby a chodí to podle nálady (často to náladu nemá :slight_smile:).