forum.mcontrollers.com - hlavní stránka forum.mcontrollers.com - fórum

 

.: fórum - hlavní stránka :.
Technology Stronghold by Rudolf Vesely
How to build Microsoft System Center hosted cloud series
FAQFAQ HledatHledat Seznam uživatelůSeznam uživatelů Uživatelské skupinyUživatelské skupiny RegistraceRegistrace
ProfilProfil StatistikaStatistika Soukromé zprávySoukromé zprávy PřihlášeníPřihlášení

 
Generátor: Generovaní sinusového a trojúhelníkového průběhu
Jdi na stránku Předchozí  1, 2, 3, 4, 5  Další
 
Přidat nové téma   Zaslat odpověď    Obsah fóra mcontrollers.com -> AVR
 
hypnoz
Anonymní





PříspěvekZaslal: 06 květen 2013, 15:28    Předmět: Citovat

Zdravim. Presne takto jsem si predstavoval Vase rady... Strucne, jasne a vystizne. Takze vsem moc dekuji. Hned jak bude chvilka, tak se na to vrhnu a poslu Vam sem vysledek.
Návrat nahoru
 

 
Radius
Profesionál
Profesionál


Založen: 22.2.2013
Příspěvky: 491

PříspěvekZaslal: 07 květen 2013, 1:08    Předmět: Citovat

A naposled vložím metodu poslední záchrany za kterou mě zde nejspíš ukamenují Smile

while(1)
{
PORTB=hodnota_1;
PORTB=hodnota_2;
PORTB=hodnota_3;
PORTB=hodnota_4;
PORTB=hodnota_5;
.
.
.
.
PORTB=hodnota_n;
}


Plus ještě test tlačítka a přechod do další takové stupidní smyčky....atd.

Prostě co smyčka to jedna výstupní fukce.


Akorát je potřeba dát pozor na optimalizaci kompilátoru a nebo to nejlíp rovnou napsat v ASM
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovy WWW stránky
 

 
AB
Profesionál
Profesionál


Založen: 24.2.2010
Příspěvky: 420

PříspěvekZaslal: 07 květen 2013, 7:44    Předmět: Citovat

citace:
A naposled vložím metodu poslední záchrany

Tato metoda nic nezachrání.
Vzorky se musí posílat s přesně vypočítanými časovými odstupy,
ne je hrnout jeden za druhým co procesor dá.

To o čem se tu bavíme je vlastně pulsní kódová modulace.
Na googlu se o tom dá něco najít.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1473

PříspěvekZaslal: 07 květen 2013, 8:31    Předmět: Citovat

Ak sa ma testovat tlacitko a signal ma byt spojity, potom sa tlacitko musiniekedy testovat a toto testovanie nesmie narusit spojitost signalu. Naviac nestaci iba testovat tlacitko, ale vyhodnotit nabeznu (dobeznu hranu), lebo ako som pochopil tlacitko ma fungovat ako prepinac. Musi mat samozrejme osetrene zakmity, lebo ak prepnem tvar signalu iba detekovanim stlacenia tlacitka, program bude medzi stavmi pri stlaceni velmi rychlo prepinat a nemam istotu na generovani ktoreho signalu sa zastavi.
Ak taketo vyhodnotenie tlacitka nema narusit kontinuitu signalu, malo by sa dat stihnut medzi lubovolnymi vzorkami. Este by sa dala pouzit metoda "rozprestrenia" vyhodnotenia tlacitka medzi jednotlive vzorky.
Kedze ide o cas, samozrejme by sa dala pouzit Radiusova metoda. Kedze su znama vystupna frekvencia, program sa moze napisat a nastavit taktovaci generator (Xtal, RC, ...) procesora tak, aby vystupna frekvencia zodpovedala poziadavku. Do "pomalsieho" signalu by sa medzi jednotlive vzorky vhodne vlozili NOPy.

Toto vsak cele povazujem za nejaky ulet nejakeho profesora. Ak sa jedna o skolske zadanie, podmienky mal vyucujuci zatat take, aby sa student mohol niecomu priucit a nie hned na zaciatku vymyslat krkolomne riesenia aby sa stihlo generovat 50kHz. A ani s krkolomnymi zverstavmi nebude sinus na osciloskope vyzerat ako sinus ale bude zatazeny velkym skreslenim. K comu je toto dobre, nerozumiem.

Ak je to realny problem, v takom pripade by som skor odporucil MCU + svab s frekvencnou syntezou. Na to tie obvody su. Alebo pouzit externu RAM a ani nemusi byt hned dvojportova. Najprv MCU do nej naseka vzorky a potom su tieto vzorky vycitavane a posielane do DA, pricom v druhej faze adesu RAM zabezpecuje 74HC393.
74HC393 dostava hodiny z vystupu jedneho z casovaco procesora. Ak bude pamat napriklad 1024B, zmesti sa do nej 4x256 vzoriek, co by mohlo zodpovedat styrom signalom. Ktory z nich sa ma aktualne vysielat moze urcit procesor pomocou svojich dvoch noziciek.
Toto by som povazoval za slusne riesenie aj pre vyssie frekvencie. A procesor nie je presnym casovanim a rychlym vysielanim signalu prakticky vobec zatazovany. Ak sa nepouzije 2port RAM, treba este medzi dolnych 8b adresej zbernice RAM a vystupmi 74HC393 vlozit nejaky 3stavovyu oddelovat, napriklad 74HC245. Signal RD, WR a CS tej RAMky je plne v rezii MCU.

Takze na to cele by malo stacit pouzit MCU, DA, RAM, 74HC393 a 74HC245

Prajem pekny den Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Radius
Profesionál
Profesionál


Založen: 22.2.2013
Příspěvky: 491

PříspěvekZaslal: 07 květen 2013, 9:25    Předmět: Citovat

AB napsal:
citace:
A naposled vložím metodu poslední záchrany

Tato metoda nic nezachrání.
Vzorky se musí posílat s přesně vypočítanými časovými odstupy,
ne je hrnout jeden za druhým co procesor dá.

To o čem se tu bavíme je vlastně pulsní kódová modulace.
Na googlu se o tom dá něco najít.



Nevím co myslíš tou pulzní modulací, když se jedná o generátor funkce-cí, ale pokud potřebuješ co nejlépe zachovat tvar funkce což znamená co nejvíce vzorků na periodu, tak rychleji ty vzorky z cpu nedostaneš.
Testování tlačítka a přechod mezi funkcemi taky nevidím jako problém.
Vzdálenost vzorků je důležitá , nicméně technicky vzato klidně nemusí být mezi všemi vzorky stejná, podstatné je aby odpovídala výstupní hodnota v daný čas.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovy WWW stránky
 

 
Panda38
Profesionál
Profesionál


Založen: 18.9.2012
Příspěvky: 398
Bydliště: Praha, Most

PříspěvekZaslal: 07 květen 2013, 9:51    Předmět: Citovat

Radius napsal:
A naposled vložím metodu poslední záchrany....
Trochu to už připomíná dobu, kdy se na 8bitech počítaly takty kvůli správnému časování load/save. Ale jo, proč ne. Už by to ale mělo být v assembleru a počítat přesně taktování - např. prokládat instrukce pro výstup instrukcemi obsluhy tlačítek (což už v C nelze). Pak lze dosáhnout podstatně vyšší frekvence a také přesnosti (např. při snížení frekvence vzorky z tabulky interpolovat).
Radius napsal:
...ale pokud potřebuješ co nejlépe zachovat tvar funkce což znamená co nejvíce vzorků na periodu, tak rychleji ty vzorky z cpu nedostaneš.
To jen v případě, že by tabulka sin měla mnohem vyšší jemnost, ale tady má daný počet vzorků a je potřeba zajistit správnou výstupní frekvenci, takže je potřeba zajistit i správné časování vzorků.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovy WWW stránky
 

 
Radius
Profesionál
Profesionál


Založen: 22.2.2013
Příspěvky: 491

PříspěvekZaslal: 07 květen 2013, 15:31    Předmět: Citovat

Souhlas. Pro takové úlohy už není tento cpu podle mě dost silný. Potíž není s průběhem sin x kde se dá dodatečnš použít analogový interpolační filrt ale s takovými průbehy jako troj x a podobně kde se vyskytují vyšší harmonické.

Arrow administrator: příspěvek byl upraven
Předchozí příspěvky se necitují.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovy WWW stránky
 

 
Radius
Profesionál
Profesionál


Založen: 22.2.2013
Příspěvky: 491

PříspěvekZaslal: 07 květen 2013, 22:01    Předmět: Citovat

Poslední Martinův příspěvek to shrnuje asi nejlíp - pokud toto zadání mělo posloužit jako test pro studenty, tak měla být výstupní frekvence volena v této konfiguraci nejvýše v jednotkách KHz a úloha mohla být zkomplikována jinými požadavky.
_________________
x51 , ARM , XILINX
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovy WWW stránky
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1473

PříspěvekZaslal: 08 květen 2013, 1:06    Předmět: Citovat

No tak som sa vybuzeroval a tu je vysledok. Ak sa bude zdat byt niekomu zdrojak prilis dlhy, je to v najlepsom slova zmysle jeho problem Smile
Prekladane pre ATmega8 20MHz, -O3, GCC


Testoval som nasledovne varianty. Teda bolo ich omnoho viac, ale za zdielanie stoja tieto ako hlavne predstavitelky socialneho experimentu.

1) dalsia vzorka najrychlejsie ako sa da - oba priebehy (SINUS a TROJUHOLNIK) maju rovnaky pocet vzoriek a teda aj rovnaku pevnu rychlost. Ide o demonstrovanie maximalnej rychlosti a zaroven demonstrovanie roznej rychlosti pri roznom algoritmyckom konstrukte.

Frekvencia sa da nastavit vhodnym poctom vzoriek, pripadne dosolichat roznym poctom ASM inistrukcii "nop". V priklade su vlozene nop-y vyREMovane

2) dalsia vzorka najrychlejsie ako sa da - rozna frekvencia pre SINUS a TROJUHOLNIK sa da dosiahnut roznym poctom vzoriek, podla zadania bude mat SINUS 1.2x viac vzoriek ako TROJUHOLNIK. Dalej sa da frekvencia znizit vlozenim potrebneho poctu "nop"-ov

3) dalsia vzorka sa zapise na zaklade zmeny hodnoty predvolby casovaca, oba signaly maju rovnaky pocet vzoriek

4) dalsia vzorka sa zapise na zaklade zmeny hodnoty predvolby casovaca, oba signaly maju rozny pocet vzoriek


Spolocne rysy:
Aby sme usetrili cas, vyuzijeme nasledovne javy.

1) Tlacitko sa vyhodnoti cez interupt (dobezna hrana), netreba teda neustale testovat jeho stav.

2) Nebude sa pri kazdej vzorke testovat aky tvar signalu sa ma generovat, ale vyuzije sa ukazovatel na zaciatok pola premennych pre ten ktory signal. Pri stlaceni tlacitka sa zmeni pociatocna hodnota ukazatela na zaciatok prislusneho pola a zaroven sa (podla demonstrovaneho pripadu) pripadne zmeni prednastavena hodnota poctu prvkov toho pola.

Spolocny kod na zaciatku - v roznych variantoch ho uz nebudem opakovat, ved naco Smile

kód:

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))

#define TRUE 0x00
#define FALSE 0xff
#define PREDVOLBA_CZ 10 // je naschval nizka, aby sw nestihal a tak sa ukazali jeho maximalne moznosti
#define MAX_VZORKY_TROJUHOLNIK 20
#define MAX_VZORKY_SINUS 32
#define PORT_PRE_DA PORTB
#define SMER_PORT_PRE_DA DDRB

uint8_t generuj_signal = SINUS;
uint8_t stav_tlacitka_new,  stav_tlacitka_old, i;

uint8_t sinu  [MAX_VZORKY_SINUS] = {127,138,149,160,171,182,193,205,      //127-205
                     205,193,182,171,160,149,138,127,      //205-127
                     127,116,105,94,83,72,61,49,         //127-49
                     49,61,72,83,94,105,116,127};      //49-127
uint8_t troj  [MAX_VZORKY_TROJUHOLNIK] = {0,12,24,36,48,      //0-48
                     60,71,82,93,103,      //60-103
                     114,125,136,147,154,      //114-154
                     124,93,62,31,0,};   //124-0

// trojuholnik s rovnakym poctom prvkov ako SINUS.
uint8_t troj2  [MAX_VZORKY_SINUS] = {0,10,20,30,40,50,60,70,
                     80,90,100,110,120,130,140,150, 
                     160,150,140,130,120,110,100,90,   
                     80,70,60,50,40,30,20,10};   


Pripad 1a) maximalna rychlost, oba priebehy maju rovnaky pocet vzoriek.
Cas sa da upravit odREMovanim "nop"-ov pripadne zvysenim/znizenim poctu vzoriek. Cas behu slucky je 0.3us. Tento cas povazujem za velmi slusny. Smile

kód:

volatile uint8_t *p_bajt_pom;

int main(void)
{
register uint8_t i, predvolba;
register uint8_t *p_bajt;

    sei(); //povolenie globálneho prerušenia 
   SET(GICR,INT0); // povolenie prerušenia od INT0
   SET(MCUCR, ISC01); // prerusenie na dobeznu hranu
   p_bajt_pom = sinu;
   p_bajt = (uint8_t *)p_bajt_pom;
   
   predvolba = MAX_VZORKY_SINUS;
   i = predvolba;
   SMER_PORT_PRE_DA = 0xff;
   while(1) {

// kod s ktorym slucka s tou istou funkcionalitou trva 0.3us
      if (i == 0) {
         i = predvolba;
         p_bajt = (uint8_t *)p_bajt_pom;
/*
asm volatile("nop\n\t"
             "nop\n\t"
             ::);
*/
      }
      else {

/*
asm volatile("nop\n\t"
             "nop\n\t"
             "nop\n\t"
             "nop\n\t"
             "nop\n\t"
             "nop\n\t"
             ::);
*/
      }
// ----------------------------------------------------------
      
      PORT_PRE_DA = *p_bajt;
      i--;
      p_bajt++;

   }

}


// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
ISR (INT0_vect) {
   if (p_bajt_pom == sinu) {
       p_bajt_pom = troj2;
   }   
   else {
      p_bajt_pom = sinu;
   }
   return;   




Pripad 1b) to co predtym, len s horsie napisanym algoritmom. Testovanie na konstantu moze trvat dlhsie ako testovanie na nulu. Vsimnite si tiez poprehadzovanie riadkov s dekrementom i a inkrementom ukazatela. Ich umiestnenim na povodne miesto v zdrojaku bude mat vplyv na rychlejsi beh programu.

Cas trvania slucky 0.45us.
kód:


volatile uint8_t *p_bajt_pom;

int main(void)
{
register uint8_t i, predvolba;
register uint8_t *p_bajt;

    sei(); //povolenie globálneho prerušenia 
   SET(GICR,INT0); // povolenie prerušenia od INT0
   SET(MCUCR, ISC01); // prerusenie na dobeznu hranu
   p_bajt_pom = sinu;
   p_bajt = (uint8_t *)p_bajt_pom;
   
   predvolba = MAX_VZORKY_SINUS;
   i = predvolba;
   SMER_PORT_PRE_DA = 0xff;
   while(1) {

      PORT_PRE_DA = *p_bajt;

      if (i == predvolba) {
         i = 0;
         p_bajt = p_bajt_pom;
      }
      else {
      }
      i++;
      p_bajt++;
   }
}

// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
ISR (INT0_vect) {
   if (p_bajt_pom == sinu) {
       p_bajt_pom = troj2;
   }   
   else {
      p_bajt_pom = sinu;
   }
   return;   



2) premenna predvolba uz musi byt typu volatile kvoli spracovaniu cez interupt (obmedzenie je len z hladiska pouzitia prekladaca C, pre ASM by to neplatilo). Vysledny kod trva 0.45us
kód:

volatile uint8_t *p_bajt_pom, predvolba;

int main(void)
{
register uint8_t i;
register uint8_t *p_bajt;

    sei(); //povolenie globálneho prerušenia 
   SET(GICR,INT0); // povolenie prerušenia od INT0
   SET(MCUCR, ISC01); // prerusenie na dobeznu hranu
   p_bajt_pom = sinu;
   p_bajt = (uint8_t *)p_bajt_pom;
   
   predvolba = MAX_VZORKY_SINUS;
   i = predvolba;
   SMER_PORT_PRE_DA = 0xff;
   while(1) {

// kod s ktorym slucka trva 11.35us
      if (i == 0) {
         i = predvolba;
         p_bajt = p_bajt_pom;
      }
      else {
      }
// ----------------------------------------------------------

      PORT_PRE_DA = *p_bajt;
      i--;
      p_bajt++;
   }
}


// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
ISR (INT0_vect) {
   if (p_bajt_pom == sinu) {
       p_bajt_pom = troj;
       predvolba = MAX_VZORKY_TROJUHOLNIK;
   }   
   else {
      p_bajt_pom = sinu;
      predvolba = MAX_VZORKY_SINUS;
   }
   return;   





3) Vzorkovanie je riadenie presne casovacom. Kratky cas slucky je 0.7us
kód:


PREDVOLBA_CZ_1 20  // pre casovanie pod 1us,  pre trojuholnik 20 vzoriek
PREDVOLBA_CZ_2 24  // pre casovanie pod 1.2us, pre sinus tiez 20 vzoriek


volatile uint8_t *p_bajt_pom;

int main(void)
{
   register uint8_t i, predvolba, j;
   register uint8_t *p_bajt, p_bajt_pom;

   p_bajt_pom = sinu;
   p_bajt = p_bajt_pom;
      
   predvolba = MAX_VZORKY_SINUS;
   i = predvolba;
   DDRB = 0xff;

   OCR2 = PREDVOLBA_CZ;
   SET(TCCR2,WGM21);
   SET(TCCR2,CS20); // delicka 1


   while(1) {

      j = TIFR;
      if (TST(j, OCF2)) {
         TIFR = j;

         if (i == 0) {
            i = predvolba;
            p_bajt = p_bajt_pom;
         }
         else {
            i++;
            p_bajt++;
         }

         PORTB = *p_bajt;
      }
   }
}

// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
ISR (INT0_vect) {
   if (p_bajt_pom == sinu) {
       p_bajt_pom = troj2;
//   OCR2 = PREDVOLBA_CZ_1;

   }   
   else {
      p_bajt_pom = sinu;
//   OCR2 = PREDVOLBA_CZ_2;
   }
   return;   



4) cas slusky je 0.85us. V tomto stave si mozeme dovolit konfort rozneho poctu vzoriek a roznej periody presne definovanej casovacom a nie dlzkou programu pri roznych rozhodovacich vetveniach. Netreba ich teda vyhodnocovat a zaprasovat kod "nop"mi
kód:

volatile uint8_t *p_bajt_pom, predvolba;

int main(void)
{
   register uint8_t i, j;
   register uint8_t *p_bajt, p_bajt_pom;

   p_bajt_pom = sinu;
   p_bajt = p_bajt_pom;
      
   predvolba = MAX_VZORKY_SINUS;
   i = predvolba;
   DDRB = 0xff;

   OCR2 = PREDVOLBA_CZ;
   SET(TCCR2,WGM21);
   SET(TCCR2,CS20); // delicka 1


   while(1) {

      j = TIFR;
      if (TST(j, OCF2)) {
         TIFR = j;

         if (i == 0) {
            i = predvolba;
            p_bajt = p_bajt_pom;
         }
         else {
            i--;
            p_bajt++;
         }

         PORTB = *p_bajt;
      }
   }
}

// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
ISR (INT0_vect) {
   if (p_bajt_pom == sinu) {
       p_bajt_pom = troj;
       predvolba = MAX_VZORKY_TROJUHOLNIK;
   }   
   else {
      p_bajt_pom = sinu;
      predvolba = MAX_VZORKY_SINUS;
   }
   return;   



Vysledky su medzi casmi 0.3us na vzorku az 0.85us na vzorku. Pravdu povediac, sam som milo poteseny vybornymi vysledkami prekladaca GCC. ASm som ciastocne analyzoval a kujon jeden, zdrojak prelozil v celku efektivne. Vzhladom k tomu, ze zapis v C vedie k daleko lepsie udrziavatelnejsiemu kodu, ktory je zaroven lepsie zdielatelny s komunitou, pracovat v cistom ASM neprinasa nejaku znatelnu efektivitu.

Zaver:
Pre rovnaku frekvenciu a maximalne casovanie oboch signalov je mozne pouzit 66.67 vzorky signalu na frekvenciu 50kHz. Vzorkovanie treba na presnu frekvenciu dosolichat nopmi z in-line asembleru.

Pre rozne frekvencie a maximalne casovanie je mozne pouzit 44 vzorky na periodu pre 50kHz a 53 vzorky pre 41.67kHz. Vzorkovanie treba na presnu frekvenciu dosolichat nopmi z in-line asembleru.

Pre roznu frekvenciu nastavenu casovacom je mozne pouzit na 50kHz 23 vzorky a dosolichat casovac a na 41.67kHz 49 vzoriek.

Osobne by som siel na casovu zakladnu 1us. Na generovanie trojuholnika by som pouzil 20 vzoriek a na generovanie sinusu 24 vzoriek. Tym sa dosiahnu frekvencie presne podla zadania.
Medzi nami , nie je to z hladiska skreslenia boh vie co, ale signal sa bude ako tak podobat a vyucujuci by mal byt spokojny.

Usetreny cas by som venoval napriklad moznej komunikacii s PC a cez neho nastavovaniu vystupnej frekvenie alebo typu priebehu.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
hypnoz
Anonymní





PříspěvekZaslal: 08 květen 2013, 11:04    Předmět: Citovat

BRAVO!!!

To Martin:
Tak toto sem fakt necekal Very Happy Nejlepsi clanek, ktery jsem kdy cetl! Jde videt, ze se v tomto prostredi umis pohybovat Wink Very Happy Diky
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1473

PříspěvekZaslal: 08 květen 2013, 12:56    Předmět: Citovat

No tak pekne dakujem Smile
Tak este prikladam konecnu verziu aj s vypisom v ASM. Pravoverni ASM by este videli moznost optimalizovat kod pri plneni ukazatela nie z RAM ale z registrov, ale to su uz len marginalne opatrenia. Pod 0.6us na periodu sa myslim vyrazne nedostanu (>10%). Ale mozno to tu niekto predvedie, tesim sa Smile

samotny program slucky trva 0.6us a pri prednastaveni hodnot (jeden krat za periodu) 0.7us.

Hodnoty v poliach si musis prepocitat na 25vzoriek a na pozadovanu amplitudu ucitelom.

perioda sinusu je od 23.7 do 23.9us, tak ze priemer je 23.74us
(pocitane z desiatich period v simulatore).
Jedna vzorka sa napni za 1us, po niekolkych vzorkach za 0.8us tak, ze priemer je tych 0.9496us na vzorku aby na periodu bolo tych 23.74us.
Frekvencia je od pozadovanej o 1% vyssia, to by nemalo vadit. Vhodnejsie hodnoty som skusmo nenasiel.

Perioda trojuholnika je od 20,00us do 20,10us. Priemer z desiatich period je 20.00us.
Jedna vzorka sa naplni vzdy pravidelne za 0.8us.


kód:

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>


#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))

#define TRUE 0x00
#define FALSE 0xff
#define SINUS TRUE
#define TROJUHOLNIK FALSE
#define PREDVOLBA_CZ_SINUS 18 // 41.67kHz predv.18,vz25=42.12kHz, predv.18,vz26=40.48kHz, predv.17/vz26=42.74kHz, predv.17,vz27=41.15kHz
#define PREDVOLBA_CZ_TROJUHOLNIK 15 // 50kHz: predvolba 15,vz.25 

// pri rovnakom pocte vzoriek 25 a predvolbe 15 je vystupna frekvencia signalu 50kHz
// pri rovnakom pocte vzoriek 25 a predvolbe 18 je vystupna frekvencia signalu 42.12kHz, co je o 1% vyssia frekvencia aka bola pozadovana


#define POCET_VZORIEK 25

#define PORT_PRE_DA PORTB
#define SMER_PORT_PRE_DA DDRB

uint8_t generuj_signal = SINUS;
uint8_t stav_tlacitka_new,  stav_tlacitka_old, i;

uint8_t sinu  [POCET_VZORIEK] = {127,138,149,160,171,182,193,205,      //127-205
                     205,193,182,171,160,149,138,127,      //205-127
                     127,116,105,94,83,72,61,49,         //127-49
                     49,61,72,83,94,105,116,127};      //49-127

// trojuholnik s rovnakym poctom prvkov ako SINUS.
uint8_t troj2  [POCET_VZORIEK] = {0,10,20,30,40,50,60,70,
                     80,90,100,110,120,130,140,150, 
                     160,150,140,130,120,110,100,90,   
                     80,70,60,50,40,30,20,10};   


volatile uint8_t *p_bajt_pom;

int main(void)
{
   register uint8_t i, j;
   register uint8_t *p_bajt;

   p_bajt_pom = (uint8_t *)sinu;
   p_bajt = (uint8_t *)p_bajt_pom;
      
//   predvolba = MAX_VZORKY_SINUS;
//   i = predvolba;
   i = POCET_VZORIEK;
   SMER_PORT_PRE_DA = 0xff;

   OCR2 = PREDVOLBA_CZ_SINUS;
   SET(TCCR2,WGM21);
   SET(TCCR2,CS20); // delicka 1

   while(1) {
      j = TIFR;
      if (TST(j, OCF2)) {
         TIFR = j;
         i--;
         if (i == 0) {
            i = POCET_VZORIEK;
            p_bajt = (uint8_t *)p_bajt_pom;
         }
         PORT_PRE_DA = *p_bajt;
          p_bajt++;
      }
   }
}

// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
// frekvencia sa bude menit zmenou hodnoty v OCR2
ISR (INT0_vect) {
   if (p_bajt_pom == (uint8_t *)sinu) {
       p_bajt_pom = (uint8_t *)troj2;
       OCR2 = PREDVOLBA_CZ_SINUS;
   }   
   else {
      p_bajt_pom = (uint8_t *)sinu;
      OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
   }
   return;   




vypis strojoveho kodu z prekladaca.
kód:

43:       {
+0000002F:   E6E0        LDI       R30,0x60       Load immediate
+00000030:   E0F0        LDI       R31,0x00       Load immediate
+00000031:   93F00094    STS       0x0094,R31     Store direct to data space
+00000033:   93E00093    STS       0x0093,R30     Store direct to data space
53:          SMER_PORT_PRE_DA = 0xff;
+00000035:   EF8F        SER       R24            Set Register
+00000036:   BB87        OUT       0x17,R24       Out to I/O location
55:          OCR2 = PREDVOLBA_CZ_SINUS;
+00000037:   E182        LDI       R24,0x12       Load immediate
+00000038:   BD83        OUT       0x23,R24       Out to I/O location
56:          SET(TCCR2,WGM21);
+00000039:   B585        IN        R24,0x25       In from I/O location
+0000003A:   6088        ORI       R24,0x08       Logical OR with immediate
+0000003B:   BD85        OUT       0x25,R24       Out to I/O location
57:          SET(TCCR2,CS20); // delicka 1
+0000003C:   B585        IN        R24,0x25       In from I/O location
+0000003D:   6081        ORI       R24,0x01       Logical OR with immediate
+0000003E:   BD85        OUT       0x25,R24       Out to I/O location
52:          i = POCET_VZORIEK;
+0000003F:   E199        LDI       R25,0x19       Load immediate
62:             j = TIFR;
+00000040:   B788        IN        R24,0x38       In from I/O location
63:             if (TST(j, OCF2)) {
+00000041:   FF87        SBRS      R24,7          Skip if bit in register set
+00000042:   CFFD        RJMP      PC-0x0002      Relative jump
64:                TIFR = j;
+00000043:   BF88        OUT       0x38,R24       Out to I/O location
65:                i--;
+00000044:   5091        SUBI      R25,0x01       Subtract immediate
67:                if (i == 0) {
+00000045:   F419        BRNE      PC+0x04        Branch if not equal
69:                   p_bajt = (uint8_t *)p_bajt_pom;
+00000046:   E6E0        LDI       R30,0x60       Load immediate
+00000047:   E0F0        LDI       R31,0x00       Load immediate
68:                   i = POCET_VZORIEK;
+00000048:   E199        LDI       R25,0x19       Load immediate
71:                PORT_PRE_DA = *p_bajt;
+00000049:   9181        LD        R24,Z+         Load indirect and postincrement
+0000004A:   BB88        OUT       0x18,R24       Out to I/O location
+0000004B:   CFF4        RJMP      PC-0x000B      Relative jump
@0000004C: __vector_1
79:       ISR (INT0_vect) {
+0000004C:   921F        PUSH      R1             Push register on stack
+0000004D:   920F        PUSH      R0             Push register on stack
+0000004E:   B60F        IN        R0,0x3F        In from I/O location
+0000004F:   920F        PUSH      R0             Push register on stack
+00000050:   2411        CLR       R1             Clear Register
+00000051:   932F        PUSH      R18            Push register on stack
+00000052:   938F        PUSH      R24            Push register on stack
+00000053:   939F        PUSH      R25            Push register on stack
80:          if (p_bajt_pom == (uint8_t *)sinu) {
+00000054:   91800093    LDS       R24,0x0093     Load direct from data space
+00000056:   91900094    LDS       R25,0x0094     Load direct from data space
+00000058:   E020        LDI       R18,0x00       Load immediate
+00000059:   3680        CPI       R24,0x60       Compare with immediate
+0000005A:   0792        CPC       R25,R18        Compare with carry
+0000005B:   F081        BREQ      PC+0x11        Branch if equal
85:             p_bajt_pom = (uint8_t *)sinu;
+0000005C:   E680        LDI       R24,0x60       Load immediate
+0000005D:   E090        LDI       R25,0x00       Load immediate
+0000005E:   93900094    STS       0x0094,R25     Store direct to data space
+00000060:   93800093    STS       0x0093,R24     Store direct to data space
86:             OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
+00000062:   E08F        LDI       R24,0x0F       Load immediate
+00000063:   BD83        OUT       0x23,R24       Out to I/O location
89:       } 
+00000064:   919F        POP       R25            Pop register from stack
+00000065:   918F        POP       R24            Pop register from stack
+00000066:   912F        POP       R18            Pop register from stack
+00000067:   900F        POP       R0             Pop register from stack
+00000068:   BE0F        OUT       0x3F,R0        Out to I/O location
+00000069:   900F        POP       R0             Pop register from stack
+0000006A:   901F        POP       R1             Pop register from stack
+0000006B:   9518        RETI                     Interrupt return
81:              p_bajt_pom = (uint8_t *)troj2;
+0000006C:   E789        LDI       R24,0x79       Load immediate
+0000006D:   E090        LDI       R25,0x00       Load immediate
+0000006E:   93900094    STS       0x0094,R25     Store direct to data space
+00000070:   93800093    STS       0x0093,R24     Store direct to data space
82:              OCR2 = PREDVOLBA_CZ_SINUS;
+00000072:   E182        LDI       R24,0x12       Load immediate
+00000073:   BD83        OUT       0x23,R24       Out to I/O location
89:       } 
+00000074:   919F        POP       R25            Pop register from stack
+00000075:   918F        POP       R24            Pop register from stack
+00000076:   912F        POP       R18            Pop register from stack
+00000077:   900F        POP       R0             Pop register from stack
+00000078:   BE0F        OUT       0x3F,R0        Out to I/O location
+00000079:   900F        POP       R0             Pop register from stack
+0000007A:   901F        POP       R1             Pop register from stack
+0000007B:   9518        RETI                     Interrupt return
89:       }


Rozhodenie signalu pocas spracovanie interuptu od tlacitka nevidim ako problem, lebo aj tak chcem menit typ signalu, tak na tych par mikrosekundach rozhodenia casovaca aj tak nezalezi.

Tot vsjo, drzim Ti palce Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
hypnoz
Anonymní





PříspěvekZaslal: 08 květen 2013, 13:16    Předmět: Citovat

Takto jsem to zkusil ja. Myslite ze je to OK?

kód:
#define F_CPU 20000000UL
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>


#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))   //nastav!
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))   //je nastaven?

#define OCR_SINUS 19 //24*41670=1000000;20000000/(1*1000000)-1=19
#define OCR_TROJUHELNIK 19 //20*50000=1000000;20000000/(1*1000000)-1=19

#define DA_SMER_PORT DDRB   //DA na porte B
#define DA_PORT PORTB   //DA na porte B

#define TLACITKO_SMER_PORT DDRD //tlacitko na porte D
#define TLACITKO_PORT  PIND //tlacitko na porte D
#define TLACITKO_BIT  2 //tlacitko PD2

#define VZORKY_SINUS 24   //pocet vzorku
#define VZORKY_TROJUHELNIK 20   //pocet vzorku

uint8_t signal = SINUS;
uint8_t i=0;

unsigned char sinu  [VZORKY_SINUS] =
{};
unsigned char troj  [VZORKY_TROJUHELNIK] =
{};

int main(void)
{
   //========= inicializace ===========
   sei(); //globalni preruseni
   SET(GIMSK,INT0); //preruseni od INT0
   SET(MCUCR, ISC01); // preruseni na dobezne hrane
   OCR0A = OCR_SINUS;
   SET(TCCR0A,WGM01);   //CTC
   SET(TCCR0B,CS00);   //preddelicka: f/1
   SET(TLACITKO_SMER_PORT,TLACITKO_BIT); //tlacitko na PD2
   DA_SMER_PORT = 0xFF; //vystup pro DA
   
   //==================================
   while(1)
   {
      if (TST(TIFR,OCF0A))   //je nastaven OCF0A?
      {
         SET(TIFR,OCF0A);   //vynuluj TIFR
         //========= generovani vzorku ============
         if (signal == SINUS)
         {
            DA_PORT = sinu[i];
            i++;
            if (i >= VZORKY_SINUS)
            {
               i = 0;
            }
         }
         else
         {
            DA_PORT = troj[i];
            i++;
            if (i >= VZORKY_TROJUHELNIK)
            {
               i = 0;
            }
         }
         //=======================================
      }
   }
}
ISR (INT0_vect)
   {
      if (signal == sinu)
      {
         signal = troj;
         OCR0A = OCR_TROJUHELNIK;
      }
      else
      {
         signal = sinu;
         OCR0A = OCR_SINUS;
      }
      return;      
   }


Jen si jeste nejsem jist tim RETURN; Myslim zde:

kód:
ISR (INT0_vect)
   {
      if (signal == sinu)
      {
         signal = troj;
         OCR0A = OCR_TROJUHELNIK;
      }
      else
      {
         signal = sinu;
         OCR0A = OCR_SINUS;
      }
      return;       
   }

Jakou presne funkci to plni?
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1473

PříspěvekZaslal: 08 květen 2013, 13:30    Předmět: Citovat

navrat z podprogramu.
Ak vracias aj nejaku hodnotu tak tam byt musi, ak vracias hodnotu void, teda ziadnu a do zdrojaku slovo return nenapises, prekladac ho tam doplni sam. No stabna kultura je stabna kultura. Smile
Aspon pri zlozitejsich podprogramoch s viacerymi vystupnymi bodmi vidis, kde sa funkcia vlastne konci.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
hypnoz
Anonymní





PříspěvekZaslal: 08 květen 2013, 13:33    Předmět: Citovat

Dekuji za odpoved. A co rikas na program, ktery jsem sem poustnul?
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1473

PříspěvekZaslal: 08 květen 2013, 15:05    Předmět: Citovat

Co Ti povedali testy v simulatore?

Vidno, ze si to neskusal ani len prelozit. Ty nas skusas? To nerob, mohlo by nas to tu prestat bavit Smile

1) Nemas zadefinovanu konstatnu SINUS.
2) Priradujes premennej ukazatel a nie premennu. Konkretne

kód:

signal = troj;
...
signal = sinu;



Zmena jednej vzorky Ti trva priemerne 1.12us. Ak si s tymto spokony, potom je vsetko OK (samozrejme po odstraneni chyb ktore som uviedol)
1.12us pri 20 vzorkach na trojuholniku Ti neda 50kHz. 17-18 vzoriek uz ano.

kod bez chyb:
ATtiny2313, -O3,

kód:

#define F_CPU 20000000UL
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>


#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))   //nastav!
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))   //je nastaven?
#define SINUS 0xff
#define TROJUHOLNIK 0x00
#define OCR_SINUS 19 //24*41670=1000000;20000000/(1*1000000)-1=19
#define OCR_TROJUHELNIK 19 //20*50000=1000000;20000000/(1*1000000)-1=19

#define DA_SMER_PORT DDRB   //DA na porte B
#define DA_PORT PORTB   //DA na porte B

#define TLACITKO_SMER_PORT DDRD //tlacitko na porte D
#define TLACITKO_PORT  PIND //tlacitko na porte D
#define TLACITKO_BIT  2 //tlacitko PD2

#define VZORKY_SINUS 24   //pocet vzorku
#define VZORKY_TROJUHELNIK 20   //pocet vzorku

uint8_t signal = SINUS;
uint8_t i=0;

unsigned char sinu  [VZORKY_SINUS] =
{};
unsigned char troj  [VZORKY_TROJUHELNIK] =
{};

int main(void)
{
   //========= inicializace ===========
   sei(); //globalni preruseni
   SET(GIMSK,INT0); //preruseni od INT0
   SET(MCUCR, ISC01); // preruseni na dobezne hrane
   OCR0A = OCR_SINUS;
   SET(TCCR0A,WGM01);   //CTC
   SET(TCCR0B,CS00);   //preddelicka: f/1
   SET(TLACITKO_SMER_PORT,TLACITKO_BIT); //tlacitko na PD2
   DA_SMER_PORT = 0xFF; //vystup pro DA
   
   //==================================
   while(1)
   {
      if (TST(TIFR,OCF0A))   //je nastaven OCF0A?
      {
         SET(TIFR,OCF0A);   //vynuluj TIFR
         //========= generovani vzorku ============
         if (signal == SINUS)
         {
            DA_PORT = sinu[i];
            i++;
            if (i >= VZORKY_SINUS)
            {
               i = 0;
            }
         }
         else
         {
            DA_PORT = troj[i];
            i++;
            if (i >= VZORKY_TROJUHELNIK)
            {
               i = 0;
            }
         }
         //=======================================
      }
   }
}
ISR (INT0_vect)
   {
      if (signal == sinu)
      {
         signal = TROJUHOLNIK;
         OCR0A = OCR_TROJUHELNIK;
      }
      else
      {
         signal = SINUS;
         OCR0A = OCR_SINUS;
      }
      return;     
   }
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

Zobrazit příspěvky z předchozích:   
Zobrazit předchozí téma :: Zobrazit následující téma  
Přidat nové téma   Zaslat odpověď    Obsah fóra mcontrollers.com -> AVR Časy uváděny v GMT + 2 hodiny
Jdi na stránku Předchozí  1, 2, 3, 4, 5  Další
 
Strana 3 z 5
Přejdi na:  
Můžete přidat nové téma do tohoto fóra.
Můžete odpovídat na témata v tomto fóru.
Nemůžete upravovat své příspěvky v tomto fóru.
Nemůžete mazat své příspěvky v tomto fóru.
Nemůžete hlasovat v tomto fóru.
Můžete k příspěvkům připojovat soubory
Můžete stahovat a prohlížet přiložené soubory
 



Num Lock Holder - app to hold Numlock
Copyright © 2018 Rudolf Veselý, mcontrollers.com.
Je zakázáno používat části tohoto webu bez souhlasu autora. || Powered by phpBB © 2001, 2002 phpBB Group - with RedSquare DoubleJ(Jan Jaap)