Stránka 3 z 3
Napsal: 22 dub 2017, 11:59
od FHonza
Pro přesné změření výstupní frekvence stačí okomentovat podmínku v přerušení komparátoru (přestane se pak generovat pauza):
Kód: Vybrat vše
...
ISR(TIM0_COMPA_vect)
{
// if (pulse < pulsePercent)
{
...
Otázkou je, jestli dolaďování má smysl. Frekvence je dána vztahem
f
gener = f
cpu / (2 × Presc × (1 + OCRA))
Presc je předdělička čítače a může být 1, 8, 64, 256 a 1024. Další "nejbližší" frekvence je pro (OCRA == 66) 3668.06 Hz, pro (OCRA == 64) to je 3780.92 Hz (Samotné přerušení se vykonává s dvojnásobnou frekvencí, proto je prescBr nastaven na 93: 7447.26 / 93 == 80.07). Tak jako v původním programu samozřejmě jde dodělat nastavování OCRA tlačítky.
Napsal: 22 dub 2017, 13:25
od lesana87
Proto je v tom původním programu použitá předdělička 1, aby to dolaďování smysl mělo.
Napsal: 22 dub 2017, 16:03
od FHonza
Lesana mě donutila dopočítat ty "nopy", čemuž sem se chtěl vyhnout
Mělo by to být takto:
Kód: Vybrat vše
#define F_CPU 3932160
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
volatile unsigned char setOCR0A = 56;
volatile unsigned char counterBr = 0;
volatile unsigned char pulse = 0;
#define prescBr 83
#define pulsePercent 8 // delka pulzu v desitkach procentech
int i;
ISR (PCINT0_vect)
{
if ((PINB & (1 << PINB0)) == 0)
{
setOCR0A--;
}
if ((PINB & (1 << PINB1)) == 0)
{
setOCR0A++;
}
}
ISR(TIM0_COMPA_vect)
{
GTCCR = (1 << TSM) | ( 1 << PSR0);
for (i = 0; i < 69; i++)
{
asm( "NOP");
}
if (pulse < pulsePercent)
{
PORTB ^= (1 << PINB2);
}
counterBr++;
if (counterBr == prescBr)
{
counterBr = 0;
PORTB ^= (1 << PINB1);
pulse++;
if (pulse > 9)
{
pulse = 0;
}
}
TCNT0 = 0;
OCR0A = setOCR0A;
GTCCR = 0;
}
void setup()
{
DDRB = (1 << PINB2);
PORTB = (1 << PINB1) | (1 << PINB0);
GTCCR = (1 << TSM) | (1 << PSR0); // zastaveni citace
TCCR0A = (1 << WGM01); // rezim CTC
TCCR0B = (1 << CS00);
OCR0A = setOCR0A;
TIMSK |= (1 << OCIE0A); // preruseni
PCMSK |= (1 << PCINT1) | (1 << PCINT0); // preruseni od tlacitek na PINB0 a PINB1
GIMSK |= (1 << PCIE); // povoleni preruseni PCINT
GTCCR = 0; // start citace (TSM nulovan)
sei();
}
int main()
{
setup();
while (1) ;
return 0;
}
Předpokládá se že, je hardwarově ošetřen "debouncing" tlačítek. Se změnou frekvence se úměrně mění i frekvence "pauzy". Neměl sem to momentálně jak ověřit, je to čistá teorie. Tak to vyzkoušej a dej vědět.
Napsal: 25 dub 2017, 18:11
od jade
Bohužel na stisknutí tlačítek změnou frekvence nereaguje.

Napsal: 25 dub 2017, 20:56
od FHonza
Jak jsou zapojený ? Podle prvního programu jsem předpokládal že stisk příslušný pin přitáhne k zemi. A sedí frekvence ?
Napsal: 26 dub 2017, 19:37
od jade
Tlačítka jsou, jak říkáš. Piny 5 a 6 jsou spínány k zemi.
Pokud chci měřit frekvenci, tak musím vyřadit přerušování. Nepohne to s frekvencí?
Děkuji
Napsal: 27 dub 2017, 10:14
od FHonza
Pohne, ale minimálně. "Ozávorkuj" to takhle:
Kód: Vybrat vše
if (pulse < pulsePercent)
{
asm( "NOP");
}
PORTB ^= (1 << PINB2);
Budu doma až v pondělí večer, pak to postavím a vyzkouším. Ať jenom neteoretizuju a konečně se to vyřeší.
Napsal: 04 kvě 2017, 22:06
od jade
Povedlo se? Taky teď mám poněkud méně času...
Prozatím jsem upravil původní program (pomocí navrhované sekvence ze začátku vlákna) a poněkud zdlouhavě, metodou pokus - omyl, došel k požadované frekvenci. Tlačítka fungují, snad by to mohlo zůstat tak?