Úprava programu "nf generátor" pro ATTiny25-20
Moderátor: Moderátoři
No právě, to je to co sem se snažil dopočítat. Jakmile navíc "compare" bude menší než počet taktů potřebných pro vykonání přerušení od časovače (72 "nopů" + kód vygenerovaný překladačem), tak se to začne chovat úplně jinak.
A další věc je ošetření "debouncingu" tlačítek. Jestli není ošetřen zákmit hardwarově, tak je to taky špatně.
Poslední verzi nemáš ?
A další věc je ošetření "debouncingu" tlačítek. Jestli není ošetřen zákmit hardwarově, tak je to taky špatně.
Poslední verzi nemáš ?
Mám tu ještě jednu verzi, ale ta je označena jako starší.
Ta poslední se nejspíš nedochovala ![Confused :?](./images/smilies/icon_confused.gif)
Kód: Vybrat vše
/*
*
* Created: 9.8.2012 20:02:00
* Author: Michal
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define F_CPU 3800000UL
// cas = x * (1 / 3.8E+6)
// frekvence= 3.8E+6 / x
// x = 3.8E+6 * pozadovany cas
// x = 3.8E+6 / pozadovana frekvence (pul periody!!!!!)
char compare = 0x80;
int i;
int main(void)
{
PORTB |= (0<<DDB2) | (1<<DDB1) | (1<<DDB0); //nastaveni pull up
DDRB |= (1<<DDB2) | (0<<DDB1) | (0<<DDB0); //smerovz registr
asm( "NOP");
PCMSK |= (1<<PCINT1) | (1<<PCINT0); //tlacitka povoleni pcint 1,0
GIMSK |= (1<<PCIE); //povoleni pcint
asm("NOP");
TIMSK |= (1<<TOIE0); //citac preruseni pri preteceni
TCCR0B |= (0<<CS02) | (0<<CS01) | (1<<CS00);//preddelicka 0
GTCCR |= (1<<TSM); //zastaveni
GTCCR |= (1<<PSR0);
OCR0A = compare; //zapsani komparacni hodnoty
TCNT0 = 0x00; //citac=0
GTCCR &= 01111110; //zapnuti
sei(); //vsechna preruseni
while(1)
{} //SMYCKA!!!!!!
return(1);
}
ISR (PCINT0_vect)
{
for (i=0;i<10;i++)
{
asm( "NOP");
}
if bit_is_clear(PINB,0) compare--;
if bit_is_clear(PINB,1) compare++;
}
ISR (TIMER0_COMPA_vect)
{
for (i=0;i<10;i++)
{
asm( "NOP");
}
PORTB ^= (1<<PORTB2); //zmena vystupu
GTCCR |= (1<<TSM); //vypnuti
GTCCR |= (1<<PSR0);
OCR0A = compare; //zapsani komparacni hodnoty
TCNT0 = 0x00; //citac=0
GTCCR &= 10000000; //zapnuti
}
![Confused :?](./images/smilies/icon_confused.gif)
V principu se to chce vykašlat na dolaďování frekvence vkládáním instrukce "nop". Jestli ještě nemáš hotovou desku, tak by asi bylo nejlepší jako výstup použít PB0. Timer0 nastavit do režimu CTC a povolit "toggle" na vývodu OC0 (PB0). Pak jenom nastavit předděličku pro Timer0 a spočítat OCR0A. V případě že se musí použít PB2, tak Timer0 nastavit do režimu Overflow, spočítat počáteční hodnotu TCNT0. A v každém přerušení opět nastavit TCNT0 a překlopit PB2. Jestli dobře počítám, tak to vychazí pro uvedený krystal přesně: předdělička na 8, TCNT0 na 191. Frekvence přerušení je pak přesně 7560Hz. A hlavně přesnost bude dána jenom přesností krystalu.
Edit: druhá možnost bude lepší pro generování toho přerušení tónu. Do timeru pak stačí dodělat počítadlo a při dosažení zvoleného počtu "tiků" odstavit na daný počet "tiků" generování signálu. Jakmile počítadlo dosáhne hodnoty 756, tak přestat generovat signál. Po dosažení 945 začít generovat a počítadlo vynulovat.
Edit: druhá možnost bude lepší pro generování toho přerušení tónu. Do timeru pak stačí dodělat počítadlo a při dosažení zvoleného počtu "tiků" odstavit na daný počet "tiků" generování signálu. Jakmile počítadlo dosáhne hodnoty 756, tak přestat generovat signál. Po dosažení 945 začít generovat a počítadlo vynulovat.
Ahoj,
Dolaďování pomocí změny OCR0A moc jemné není,
jak je vidět v kódu.
Jestli stačí pevná frekvence 3710,9 Hz tak zkus tento kód. (přikládám i hex)
Nemám tiny25, takže jsem ho nemohl vyzkoučet v reálu.
Dolaďování pomocí změny OCR0A moc jemné není,
jak je vidět v kódu.
Jestli stačí pevná frekvence 3710,9 Hz tak zkus tento kód. (přikládám i hex)
Nemám tiny25, takže jsem ho nemohl vyzkoučet v reálu.
Kód: Vybrat vše
// Attiny25, AvrStudio4
// Na pinu PB0 je modulovaný signál 3711 Hz
#define F_CPU 3800000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
TCCR0A = (1<<COM0A0)|(1<<WGM01); // mode CTC, toggle on compare
TCCR0B = (0<<CS01); // prescaler 8
OCR0A = 63; // 3710,9 Hz
// OCR0A = 62; // 3769,8 Hz
// OCR0A = 64; // 3653,8 Hz
while(1)
{
DDRB |= (1<<0); // modulace:
_delay_ms(160); // impuls 160 ms
DDRB &= ~(1<<0);
_delay_ms(40); // mezera 40 ms
}
}
- Přílohy
-
- test00.zip
- (266 bajtů) Staženo 141 x
Naposledy upravil(a) AB1 dne 19 dub 2017, 14:03, celkem upraveno 1 x.
Kód: Vybrat vše
#define F_CPU 3932160
#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned char setOCR0A = 65; // F_CPU / 2 / 8 / 3720
volatile unsigned char counterBr = 0;
volatile unsigned char pulse = 0;
#define prescBr 93 // frekvence pulzu -> frekvence preruseni / 47 = 80Hz
#define pulsePercent 8 // delka pulzu v desitkach procentech
ISR(TIM0_COMPA_vect)
{
if (pulse < pulsePercent)
{
PORTB ^= (1 << PINB2);
}
counterBr++;
if (counterBr == prescBr)
{
counterBr = 0;
pulse++;
if (pulse > 9)
{
pulse = 0;
}
}
}
void setup()
{
DDRB = (1 << PINB2);
TCCR0A = (1 << WGM01); // rezim CTC
TCCR0B = (1 << CS01); // // preddelicka 8
OCR0A = setOCR0A;
TIMSK |= (1 << OCIE0A); // preruseni
sei();
}
int main()
{
setup();
while (1) ;
return 0;
}
S krystalem 3,932160 MHz je generovana frekvence 3723,63 Hz, pauza je generovaná s frekvencí 8Hz, délka "pulzu" je 80%. Výstup je na PB2
Díky moc pánové!
AB1: Těch 10hz níž by snad tolik nevadilo, pokud by se dalo dolaďovat v krocích 10hz nebo jemněji, ale vyžadovalo by to pokaždé doladit oscilátor, aby ladil s výstupním LC. Jelikož maják většinou zanáší na místo nějaká ta mírně poučená osoba, která se zrovna na místě namane, bude lepší, když bude jakékoliv manipulace na místě co nejméně, tedy i dolaďování.
Děkuji i tak, použiji kód ke studijním účelům
, určitě vyzkouším!
FHonza: Jdu kompilovat a zkoušet!
Jeden dotázek: Pokud bych chtěl změnit frekvenci přerušování, tedy těch 8hz, nerozhodím si tím ten nf signál?
Ještě jednou děkuji!
AB1: Těch 10hz níž by snad tolik nevadilo, pokud by se dalo dolaďovat v krocích 10hz nebo jemněji, ale vyžadovalo by to pokaždé doladit oscilátor, aby ladil s výstupním LC. Jelikož maják většinou zanáší na místo nějaká ta mírně poučená osoba, která se zrovna na místě namane, bude lepší, když bude jakékoliv manipulace na místě co nejméně, tedy i dolaďování.
Děkuji i tak, použiji kód ke studijním účelům
![Smile :)](./images/smilies/icon_smile.gif)
FHonza: Jdu kompilovat a zkoušet!
Jeden dotázek: Pokud bych chtěl změnit frekvenci přerušování, tedy těch 8hz, nerozhodím si tím ten nf signál?
Ještě jednou děkuji!
FHonza: Něco jsem asi neudělal dobře, dává to 478hz. Pojistky jsem dal jako "EXT Crystal Osc. Frequency 3-8Mhz, Start-up time PWRDWN/RESET 1K CK/14CK+4.1ms [cksel=1100 SUT=11]"
Parametry PWRDWN/RESET nevím, co vlastně nastavují, možná jsem to dal blbě.
EDIT: Ještě kouknu, jestli jsem omylem nezapnul CKDIV8
EDIT2: Tak už chodí! Moje chyba. Momentálně mi ale došla baterka v měřáku a osciloskopem jen zhruba něco kolem 3700hz ( cca 270us)
AB1: Tvůj jsem nerozchodil vůbec
[/b]
Parametry PWRDWN/RESET nevím, co vlastně nastavují, možná jsem to dal blbě.
EDIT: Ještě kouknu, jestli jsem omylem nezapnul CKDIV8
EDIT2: Tak už chodí! Moje chyba. Momentálně mi ale došla baterka v měřáku a osciloskopem jen zhruba něco kolem 3700hz ( cca 270us)
AB1: Tvůj jsem nerozchodil vůbec
![Sad :(](./images/smilies/icon_sad.gif)
Naposledy upravil(a) jade dne 19 dub 2017, 23:55, celkem upraveno 3 x.
Pardon, měl jsem tam chybu.
Napiš do řádku #define F_CPU skutečnou frekvenci krystalu
a měř na PB0.
Napiš do řádku #define F_CPU skutečnou frekvenci krystalu
a měř na PB0.
Kód: Vybrat vše
// Attiny25, AvrStudio4
// Na pinu PB0 je modulovaný signál 3711 Hz
#define F_CPU 3800000UL // frekvence krystalu [Hz]
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
CLKPR = (1<<CLKPCE); // disable CKDIV8
CLKPR = 0;
DDRB = (1<<0); // PB0 výstup
TCCR0A = (1<<COM0A0)|(1<<WGM01); // mode CTC, toggle on compare
TCCR0B = (1<<CS01); // prescaler 8
OCR0A = F_CPU / 2 / 8 / 3720; // 3710,9 Hz
while(1)
{
DDRB |= (1<<0); // modulace:
_delay_ms(160); // impuls 160 ms
DDRB &= ~(1<<0);
_delay_ms(40); // mezera 40 ms
}
}
Tohle se rozběhlo, ale na frekvenci cca 3400 ? hz (zhruba podle osciloskopu, v měřáku mi došly baterky)
Než PB0 by mi lépe vyhovoval PB2, ale s tím bych se i smířil
Jak je to tam s těmi tlačítky?
Děkuji !
Edit: Vypadá to, že jsem rozchodil program od Honzy, zítra změřím frekvenci a ozkouším tlačítka. Už je zase půlnoc. Ten čas běží, když člověk něco řeší...
Než PB0 by mi lépe vyhovoval PB2, ale s tím bych se i smířil
![Smile :)](./images/smilies/icon_smile.gif)
Jak je to tam s těmi tlačítky?
Děkuji !
Edit: Vypadá to, že jsem rozchodil program od Honzy, zítra změřím frekvenci a ozkouším tlačítka. Už je zase půlnoc. Ten čas běží, když člověk něco řeší...
Potom asi nesouhlasí skutečný kmitočet krystalu s tím co jsi napsal do #define F_CPU.Tohle se rozběhlo, ale na frekvenci cca 3400 ? hz (zhruba podle osciloskopu, v měřáku mi došly baterky)
Žádné tam nejsou.Jak je to tam s těmi tlačítky?
Dolaďování tlačítkama o +- 10 Hz tady nepůjde.
K tomu by byl třeba jiný procesor, s 16-bitovým čítačem.
Tiny25 má jenom 8-bitové.
Nerozhodíš, ta konstantajade píše: Jeden dotázek: Pokud bych chtěl změnit frekvenci přerušování, tedy těch 8hz, nerozhodím si tím ten nf signál?
Kód: Vybrat vše
#define prescBr 93
Kód: Vybrat vše
#define pulsePercent 8[-code].
Vlastně je to celé PWM s frekvencí 8Hz, střídou 80% modulovaná frekvencí 3723.63 Hz.
Nejprve musím poděkovat za odpovědi ![Smile :)](./images/smilies/icon_smile.gif)
FHonza: Frekvence sedí, musel jsem měřit záznějovou metodou, protože měřák nepobral to přerušování. Vyšlo mi 3724hz, což je paráda.
Tlačítka nereagují
... Opravdu by nešlo nějak dodělat aspoň nějaké doladění?
AB1: Nechci se hádat, ale původní program na začátku tématu dolaďování tlačítky obsahuje a funguje to na ATtiny 25. Je to dáno jiným způsobem tvorby signálu?
Děkuji!
![Smile :)](./images/smilies/icon_smile.gif)
FHonza: Frekvence sedí, musel jsem měřit záznějovou metodou, protože měřák nepobral to přerušování. Vyšlo mi 3724hz, což je paráda.
Tlačítka nereagují
![Sad :(](./images/smilies/icon_sad.gif)
AB1: Nechci se hádat, ale původní program na začátku tématu dolaďování tlačítky obsahuje a funguje to na ATtiny 25. Je to dáno jiným způsobem tvorby signálu?
Děkuji!