Úprava programu "nf generátor" pro ATTiny25-20

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#16 Příspěvek od FHonza »

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áš ?
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#17 Příspěvek od jade »

Mám tu ještě jednu verzi, ale ta je označena jako starší.

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

}

Ta poslední se nejspíš nedochovala :?
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#18 Příspěvek od FHonza »

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.
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#19 Příspěvek od jade »

Díky, sám to ale dohromady nedám. Pokud by se někdo uvolil, i nějakou tu kačku bych pustil.
V podstatě můžu výstup upravit, mám tam vyvedený ISP konektor, z něj můžu brát signál odkudkoliv.
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#20 Příspěvek od FHonza »

Když vydržíš do úterý, tak ti sem dám kód. Teď už jsem na odchodu a celé Velikonoce nezapnu počítač. Jenom ještě napiš jestli se má řešit debouncing tlačítek nebo jestli je vyřešen hardwarově.
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#21 Příspěvek od jade »

Rád počkám! Kontakty spínačů jsou ošetřeny kondenzátory 100n, docela to funguje.
Díky!
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#22 Příspěvek od AB1 »

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.

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 232 x
Naposledy upravil(a) AB1 dne 19 dub 2017, 14:03, celkem upraveno 1 x.
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#23 Příspěvek od FHonza »

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
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#24 Příspěvek od jade »

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!
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#25 Příspěvek od jade »

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]
Naposledy upravil(a) jade dne 19 dub 2017, 23:55, celkem upraveno 3 x.
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#26 Příspěvek od AB1 »

Pardon, měl jsem tam chybu.

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
   }                                 
}
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#27 Příspěvek od jade »

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ší...
Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 00:00

#28 Příspěvek od AB1 »

Tohle se rozběhlo, ale na frekvenci cca 3400 ? hz (zhruba podle osciloskopu, v měřáku mi došly baterky)

Potom asi nesouhlasí skutečný kmitočet krystalu s tím co jsi napsal do #define F_CPU.

Jak je to tam s těmi tlačítky?

Žádné tam nejsou.
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é.
Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 00:00
Bydliště: Praha

#29 Příspěvek od FHonza »

jade 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?


Nerozhodíš, ta konstanta

Kód: Vybrat vše

#define prescBr 93

určuje, kolikrát proběhne přerušení čítače než se zvýší hodnota pro určení šířky "pulzu". Šířka "pulzu" je rozdělená na deset částí, v které části se má přestat generovat výstupní signál určuje konstanta
[code]#define pulsePercent 8[-code].

Vlastně je to celé PWM s frekvencí 8Hz, střídou 80% modulovaná frekvencí 3723.63 Hz.
Uživatelský avatar
jade
Příspěvky: 1022
Registrován: 28 pro 2004, 00:00
Bydliště: Brno

#30 Příspěvek od jade »

Nejprve musím poděkovat za odpovědi :)

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!
Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“