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
 
Radius
Profesionál
Profesionál


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

PříspěvekZaslal: 04 květen 2013, 21:33    Předmět: Citovat

Myslím že problém není v kalkulačce Sad
_________________
x51 , ARM , XILINX
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: 506

PříspěvekZaslal: 04 květen 2013, 21:33    Předmět: Citovat

Myslím že problém není v kalkulačce Sad
_________________
x51 , ARM , XILINX
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovy WWW stránky
 

 
hypnoz
Anonymní





PříspěvekZaslal: 05 květen 2013, 13:34    Předmět: Citovat

Zdravim... No s tou kalkulackou si me dostal Very Happy Very Happy Very Happy Asi sem se preklep Wink A kdyz chci aby perioda SINU byla 20us pri aproximaci 32 vzorku a perioda TROJ byla 23,998us pri aproximaci 20 vzorku, jak mam tedy spocitat hodnotu do OCR0A + preddelicku??? Toto je jedina vec, na kterou stale nemohu prijit...

To Martin: Promin, ale z toho tveho programu si nevemu vubec nic... Je tam tolik zadefinovanych veci a komentu, ze se v tom vubec nemuzu vyznat... Trochu sem ten program prekopal:


kód:
#define F_CPU 20000000UL      //zakladni frekvence
#include <avr/io.h>            //input/output

unsigned char sinu  [32] = {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
unsigned char troj  [20] = {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
unsigned char i=0, y=0;

void sinu1()
{
   TCCR0A = 0;
   TCCR0B = 0;
   /* 20000000/(1*256)=78125;78125/256=305;41670/305=137 */
   OCR0A = 0x89;      //137
   /* T0:Fast PWM;/1 */
   TCCR0A |= (1<<0)|(1<<1);
   TCCR0B |= (1<<3)|(1<<0);
   
   while (1)
   {
   if((TIFR & 0x01)==1)      //TCNT0==OCR0A?
      {
         i1();
      }
   /*ZMENA SIGNALU PO STISKNUTI TLACITKA:*/      
      if(PIND==0x04)      //je zmacknute tlacitko?
      {
         PORTB = 0;      //signal 0
         troj1();
      }
   }
}

void i1()
{
         TIFR=TIFR | 0x01;      //nuluje registr TIFR (zapsanim 1)
         PORTB = sinu[i];      //hodnota z tabulky
         i++;
         if (i==31)
         {
            i=0;
         }
}

void troj1()
{
   TCCR0A = 0;
   TCCR0B = 0;
   /* 20000000/(1*256)=78125;78125/256=305;50000/305=164 */
   OCR0A = 0xA4;      //164
   /* T0:Fast PWM;/1 */
   TCCR0A |= (1<<0)|(1<<1);
   TCCR0B |= (1<<3)|(1<<0);
   
   while (1)
   {
   if((TIFR & 0x01)==1)      //TCNT0==OCR0A?
      {
         i2();
      }
   /*ZMENA SIGNALU PO STISKNUTI TLACITKA:*/      
      if(PIND==0x04)      //je zmacknute tlacitko?
      {
         PORTB = 127;      //signal 0
         sinu1();
      }
   }
}

void i2()
{
         TIFR=TIFR | 0x01;      //nuluje registr TIFR (zapsanim 1)
         PORTB = troj[y];      //hodnota z tabulky
         y++;
         if (y==24)
         {
            y=0;
         }
}

int main(void)
{   
   DDRB = 0xFF;      //vystup pro signal
   DDRD = 0x00;      //vstup pro tlacitko
   PORTD = 0x00;      //pull-up OFF
   sinu1();
}


Hlavne teda ZDE:

kód:
/*ZMENA SIGNALU PO STISKNUTI TLACITKA:*/       
      if(PIND==0x04)      //je zmacknute tlacitko?
      {
         PORTB = 0;      //signal 0
         troj1();
      }


A co se tyce tech podle tebe nesmyslnych smicek jako je:

kód:
while (1)
   {
   if((TIFR & 0x01)==1)      //TCNT0==OCR0A?
      {
         i1();
      }
   /*ZMENA SIGNALU PO STISKNUTI TLACITKA:*/       
      if(PIND==0x04)      //je zmacknute tlacitko?
      {
         PORTB = 0;      //signal 0
         troj1();
      }
   }


Tak program se tu nesekne donekonecna, ale jen do te doby, nez se bud odvola na void i1() nebo na void troj1()

Takze budu velice rad, kdyz mi nekdo vysvetli, jak nastavit PERIODU SINU a TROJ prubehu. Dekuji.
Návrat nahoru
 

 
hypnoz
Anonymní





PříspěvekZaslal: 05 květen 2013, 13:38    Předmět: dodatek Citovat

A kdybych chtel misto void i1() a void i2() pouzit preruseni, musel bych pouzit C/T0 i C/T1, coz je zbytecne. A me to nijak neomezi, kdyz program nebude delat vice veci najednou, protoze C/T pracuje nezavisle na ostatnich vecech a o nic jineho mi nejde...
Návrat nahoru
 

 
Panda38
Profesionál
Profesionál


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

PříspěvekZaslal: 05 květen 2013, 16:00    Předmět: Citovat

hypnoz škoda že ses nepoučil z toho co Ti radil Martin, tvůj program je napsaný fakt otřesně. Tam nepomohou jednoduché rady.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovy WWW stránky
 

 
hypnoz
Anonymní





PříspěvekZaslal: 05 květen 2013, 16:18    Předmět: Citovat

Tak promin, ale zkratka jsem to nepochopil... To neni o tom, ze bych si nechtel nechat poradit!
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


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

PříspěvekZaslal: 05 květen 2013, 18:50    Předmět: Citovat

To je uplne v poriadku. Pytaj sa dokedy nebudes rozumiet.
V mojom programe je vela komentov preto, aby mu bolo rozumiet (aspon sa snazim Smile ), ale ako mi tu uz niekto v dobrom radil, menej je viac. Tak to skusim este raz a ak nebudes niecomu KONKRETNEMU v programe rozumiet, pytaj sa kludne bod po bode. Smile

kód:


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

// Definice makier s parametrami, toto jednoducho akceptuj a aj v dalsich svojich programoch pouzivaj obdobne substitucie.
// vedie to k prehladnejsiemu a zrozumitelnejsiemu kodu.
// to ocenis, najma ak sa budes niekoho pytat o radu. Cim neprehladnejsi zdroja, tym menej ochotnych sa nim zaoberat :-)
#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 7
#define TLACITKO_BIT  5 // nech je tlacitko na piatom bite
#define TLACITKO_PORT  PIND // nech je tlacitko na porte D
#define TLACITKO_SMER_PORT DDRD // nech je tlacitko na porte D
#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;

unsigned char 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
unsigned char 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

int main(void)
{
   // ========= zaciatok inicializacie ===========
   OCR2 = PREDVOLBA_CZ_SINUS;
   SET(TCCR2,WGM21);
   SET(TCCR2,CS22);
   RES(TLACITKO_SMER_PORT,TLACITKO_BIT);
   SMER_PORT_PRE_DA = 0xff;

   if (TST(TLACITKO_PORT,TLACITKO_BIT)) stav_tlacitka_new = TRUE;
   else stav_tlacitka_new = FALSE;
   stav_tlacitka_old = stav_tlacitka_new;
   // ========= koniec inicializacie ===========

   while(1) {
      if (TST(TIFR,OCF2)) {
         SET(TIFR,OCF2);
         // =========== zaciatok testovania tlacitka ===========
         if (TST(TLACITKO_PORT,TLACITKO_BIT)) stav_tlacitka_new = TRUE;
         else stav_tlacitka_new = FALSE;
         if (stav_tlacitka_new == FALSE) && (stav_tlacitka_old == TRUE)) {
            if (generuj_signal == SINUS) {
               generuj_signal = TROJUHOLNIK;
               // trojuholnik moze mat inu periodu ako sinus
               OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
            }
            else {
               generuj_signal = SINUS;
               // sinus moze mat inu periodu ako trojuholnik
               OCR2 = PREDVOLBA_CZ_SINUS;
            }
            i = 0;
         }
         stav_tlacitka_old = else stav_tlacitka_new;
         // =========== koniec testovania tlacitka ===========

         // ========= zaciatok generovania vzorky ===========
         // volba spravnej funkcie na zaklade stavu "tlacitka"
         if (generuj_signal == SINUS) {
            PORT_PRE_DA = sinu[i];
            i++;
            if (i >= MAX_VZORKY_SINUS) i = 0;
         }
         else {
            PORT_PRE_DA = troj[i];
            i++;
            if (i >= MAX_VZORKY_TROJUHOLNIK) i = 0;
         }
         // ========= koniec generovania vzorky ===========

      }
   }

   return;
}


Periodu menis roznym nastavenim hodnoty v OCR2. Bud tam vlozis
hodnotu PREDVOLBA_CZ_SINUS alebo hodnotu PREDVOLBA_CZ_TROJUHOLNIK. Na substitucie cisel textom si zvykni, je to velmi uzitocne. Nema to nijaky vplyv na vysledny kod, iba a vylucne na lepsiu citatelnost kodu.

Drzim palce, pytaj sa dalej Smile

P.S. Moj kod je kratsi ako Tvoj, tak sa skus cez neho preluskat a skus ho vyskusat. Po skuske mozno budes mat dalsie otazky, mozno na simulatore v AVR studiu zistis, ako kod pracuje.

P.S.2: Pokial som si dobre vsimol, Tvoj kod postupne vola sinu() a z neho troj() a potom sinu() a znovu troj() a znovu sinu() a znovu troj()... Az kym sa nezaplni zasobnik a program neskolabuje. Vsetko zavisi od poctu stlacenia tlacitka a od velkosti volnej pamate. Skratka tak ako som si stacil vsimnut, program je odsudeny na to ist do kytiek a preto som tie while(1) nazval nezmyselnymi. Smile

P.S.3: Vsimni si, ze kod testovania tlacitka je dlhsi ako cely kod na generovanie trojuholnika a sinusu dokopy Smile


Naposledy upravil Martin dne 05 květen 2013, 19:03, celkově upraveno 1 krát.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Panda38
Profesionál
Profesionál


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

PříspěvekZaslal: 05 květen 2013, 18:57    Předmět: Citovat

Martin to už mezitím připsal a vysvětlil, ale nechám to beze změn:

hypnoz: jedna z chyb (jak psal už Martin) - křížové volání funkcí sinu1 a trojl. Při volání funkce se ukládá do zásobníku návratová adresa. Když funkce voláš křížově mezi sebou, ukazatel zásobníku se neustále posouvá. Což po pár vnoření bude mít za následek přetečení zásobníku a zhroucení programu.

Jiná chyba - PIND vrací stav bitů portu D, nelze proto jednoduše testovat stisk tlačítka (PIND==0x04). Je nutné testovat stav jen jednoho bitu.

Dále - tlačítko nastavuje stav bitu po celou dobu držení. Nelze tedy testovat stisk tlačítka jednoduchou podmínkou, mělo by to za následek neustálé překlápění stavu po celou dobu držení (ve Tvém případě vnořování do funkcí s následkem zahlcení zásobníku ihned po stisku). Je nutno testovat změnu stavu bitu a navíc by bylo vhodné ošetřovat ještě zákmity tlačítka.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovy WWW stránky
 

 
hypnoz
Anonymní





PříspěvekZaslal: 05 květen 2013, 20:36    Předmět: Citovat

Borci, strasne Vam dekuji. Konecne jsem to pobral. Jen jeste nechapu PREDVOLBA_CZ_SINUS a PREDVOLBA_CZ_TROJUHOLNIK to je hodnota, ktera se zapise do OCR? Myslim ze ANO, ale nevim, jak ji spocitat... Muzete mi nekdo dat vzorecek? Wink DIKY.
Návrat nahoru
 

 
hypnoz
Anonymní





PříspěvekZaslal: 05 květen 2013, 20:41    Předmět: Citovat

A mohu nastavit preddelicku takto?

SET(TCCR0B,CS01);
SET(TCCR0B,CS00); //:64

Nevadi, ze se nenastavi zaroven?
Návrat nahoru
 

 
hypnoz
Anonymní





PříspěvekZaslal: 05 květen 2013, 20:51    Předmět: Citovat

A posledni dotaz:

#define VZORKY_SINUS 32 //pocet vzorku
#define VZORKY_TROJUHOLNIK 20 //pocet vzorku

nemelo by tam byt 31 a 19? Protoze v te mnozine je sice 32 a 20 hodnot, ale pocita to od nulte hodnoty.

if (i >= VZORKY_SINUS)
{
i = 0;
}

Takze zde se i vynuluje az je vetsi nebo rovno 32 (ale to je 33 hodnot)
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


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

PříspěvekZaslal: 06 květen 2013, 0:00    Předmět: Citovat

Ako som Ti uz pisal,

kód:

#define PREDVOLBA_CZ_SINUS 7 // spravnost hodnoty predvolby teraz neskumam, treba si ju vypocitat podla Tvojich potrieb
#define PREDVOLBA_CZ_TROJUHOLNIK 5 // spravnost hodnoty predvolby teraz neskumam, treba si ju vypocitat podla Tvojich potrieb


hodnoty si prepocitaj podla Tvojich potrieb (ci 32 lebo 31 alebo 19 alebo 20, to je cisto Tvoja vec)

vzhladom k tomu ze:

kód:

   OCR2 = PREDVOLBA_CZ_SINUS;
...
   OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;


asi tie hodnoty budu predvolby casovej zakladne Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
AB
Profesionál
Profesionál


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

PříspěvekZaslal: 06 květen 2013, 8:44    Předmět: Citovat

Pro sinus trvá jedna perioda 24 us (1/41670).
Jestli chceme mít 32 vzorků na periodu, musí timer vyvolat přerušení ne za 24us ale za 24/32 = 0,75us.
Jinak řečeno, frekvence přerušení musí být 32*41670 = 1 333 440 Hz.

V módu CTC
frekvence = (F_CPU/prescaler)/(OCR0A+1)
OCR0A = ((F_CPU/prescaler)/frekvence)-1

Pro frekvenci 1333440 Hz a předdělič 1 dostaneme OCR0A = 13,99

kód:
//nastavení timeru
   TCCR0A = (1<<WGM01); // mód CTC
   TCCR0B = (1<<CS00);  // prescaler 1
   OCR0A  = 14;   


Při každém přerušení zapíšeme hodnotu z tabulky sinus.

Důležité je, že tento zápis nesmí trvat déle než 0,75 us, to jest, než přijde další přerušení.
Nemůžeme tady použít kód od Martina, protože tam bude trvat zápis podstatně déle.

Dokonce ani nejjednodušší kód bez testování tlačítka:

kód:
   while (1)
   {
      if(TIFR & (1<<OCF0A))
      {
         PORTB = sin_tab[i&0b00011111]; // "i" se vynuluje po hodnotě 31
         i++;
         TIFR = (1<<OCF0A);  // clear flag
      }
   }   

se nedá použít, trvá 0,8us. (Avrstudio 4.17.666 - Winavr 20100110)


Proto bych zvolil menší počet vzorků na periodu, třeba 16 a zkontroloval jestli časování bude sedě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: 1486

PříspěvekZaslal: 06 květen 2013, 9:42    Předmět: Citovat

Inak v mojom kode sa bude vyberat z pola s indexami 0 az 31 a 0 az 19. Pri dosiahnuti 32 respektive hodnoty 20 sa premenna i vynuluje. Takze ak Ti slo o velkost deklarovaneho pola v mojom kode, malo by byt vsetko OK Smile

kód:
 
if (generuj_signal ==
SINUS) {
PORT_PRE_DA = sinu
[i];
i++;
if (i >=
MAX_VZORKY_SINUS) i = 0;
}
else {
PORT_PRE_DA = troj
[i];
i++;
if (i >=MAX_VZORKY_TROJUHOLNIK) i = 0;
 
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
AB
Profesionál
Profesionál


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

PříspěvekZaslal: 06 květen 2013, 14:18    Předmět: Citovat

V poslední poště jsem ukázal, že přerušení musí být vyvoláno každých 0,75us. Ty máš nastaveno
F_CPU=20MHz
prescaler=64
OCR2=7
takže přerušení nastane za 22,4us.
Všech 32 vzorků odešleš za 22,4*32=716,8us.
To znamená, že kmitočet na výstupu bude 1000/716,8 = 1,395 kHz.
Požadováno bylo 41,67 kHz.

Ale ani předdělič 1 nepomůže, jak je vidět v mé ukázce.
Jedině zmenšit počet vzorků na periodu, aby mezi zápisem vzorků bylo více času.
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 2 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)