You are here

8051 mikrokontrolleren hogyan lehet két külön kivezetésen EGYSZERRE két egymástól eltérő négyszögjelet generálni ?

19 posts / 0 new
Last post
zus
zus picture

Helló ! Kedves kollégák, a címben megénekelt problémára szeretnék egy egyszerű megoldást találni.

Tehát, 8051 mikrovezérlő egyik portján van két külön kivezetés, a P2 porton a P2.0 és a P2.1. Ezeken kell megjennie két, egymástól teljesen eltérő négyszögjelnek EGYSZERRE. Mindkét négyszögjelet a mikrovezérlőnek EGYSZERRE kell szolgáltatnia egy gomb megnyomására, tehát semmi külső kiegészítő áramkör nincs a rendszerben. Pláne, hogy ilyen a két négyszögjel kb. ilyen, mint 500 Hz és 700 Hz. Tehát az sem működik, hogy egy, a mikrovezérlő által biztosított négyszögjelet külső áramkörökkel osztogatok. Az áramkörnek amúgy a lehető legegyszerűbbnek kell lennie, így a mikrovezérlőnek kell megoldania a problémát, a frekvencia generálást (amit ő meg is tud oldani, csak sjanos én nem udom, hogy hogyan kezdjek neki).

Kérdésem az lenne, hogy tudna-e hozzáértő segíteni nekem egy egyszerű 8051-esre való C vagy Pascal (vagy Basic vagy ASM) kóddal ? Csak az EGYSZERRE történő négyszögjel generálásának a metódusa érdekel, a többi hozzátartozó sallanggal már meg fogok birkózni. 

Azért kérek segítséget, mert a különböző frekvenciák EGYMÁS UTÁN generálásával gondom nincsen, az megy. Az nem megy, ilyen jellegű tapasztalat híján, hogy EGYSZERRE, EGY IDŐBEN hogyan tudok KÉT külön frekvenciát generálni, KÉT külön kivezetésen ? A gép biztosan tudja ezt. Nyilván az "egyszerre generálás" az azt fogja jelenteni, hogy egy-két órajelciklus eltéréssel fog a két frekvencia megjelenni, de ez nem zavaró. A lényeg a folyamatosság. A mikrovezérlő 12-15 MHz-es kristállyal megy, tehát az az egy-két órajel eltérés nem lesz észrevehető.

Megköszönök minden hozzáértő segítséget. 8051 van kéznél, úgyhogy aki mással dolgozik, az kíméljen meg a "miért nem PIC-cel/mással próbálkozol ?" jellegű megjegyzésektől. Én tudom, hogy miért a 8051-re esett a választásom, nyilván megvan az oka. Köszönöm.

Comments
zus
zus picture

Kedves Kollégák ! Valóban az a szívás, hogy a soros programozással küzdök. Sajnos, semmilyen PWM lehetőségem nincs. az interruptra gondoltam én is.

Apropó PWM. Ezt az általam felvetett problémát pl. 90C8535-tel nem lehet megvalósítani ? Abban ugyanis van PWM, talán kettő és lábkompatíbilis nagyjából a 8051-gyel (talán még az Atmega8535 is ugyanez). Akárhogy is, ezt a PWM-es megvalósítást meg tudná nekem valaki világítani ?

0

ty
ty picture

Amit írtál, annak nem sok köze van a PWM-hez, azt leszámítva, hogy mind a kettő négyszög jel.
És igen, szinte mindegyik mikrokontrollerrel, processzorral meg lehet valósítani, mert egyszerű feladat.
De érdemes lenne az alapoknál elkezdeni, pl. megnézni, hogy hogyan tudod beállítani és használni a timer interruptot.
 

0

zus
zus picture

Szia ty ! A PWM az onnan került a képbe, hogy valahol valaki a neten azt véste, hogy ő PWM-mel oldotta meg ezt a problémát. A kérdésem ezért volt és nyilván a "hogyan" lett volna az érdekes. Ugyanis, én úgy tudom, hogy a PWM-et olyan helyeken alkalmazzák, ahol a kitöltési tényezőnek kell változnia, nem pedig a frekvenciának 

Amúgy, az ötleted zseniális volt, már hogy az interruptokkal bohóckodjak. Összeszedtem a gondolataim és sikerült végül egy olyan kódot vésnem, amiben egy nyomógomb megnyomására az egyik timer egyféle, a másik meg egy másik féle frekvenciájú négyszögjelet generál EGYSZERRE, EGYIDŐBEN, két akármelyik kivezetésen. Elég jó lett. Nyilván az "egy időben" az annyit jelent, hogy egy-két órajelciklus eltéréssel indulnak. De mondjuk ez mikroszekundumoknál annyira nem észrevehető. Úgyis csak korlátozott ideig kell működnie a rendszernek (a gomb megnyomása után pár másodpercig, aztán standby). Most még azon dolgozom, hogy azt hogyan tudom majd megcsinálni, hogy a frekvenciát is tudjam menetközben változtatni. Úgy értem, hogy pl. 1-2 s ideig az egyik négyszög A frekvenciájú, a másik meg B. Aztán az 1-2 s elteltével az első négyszög C frekvenciájú legyen, a másik négyszög meg D frekvenciájú. Már hogy programozástechnikailag hogyan tudom az inicializálását megcsinálni a timer interruptoknak az 1-2 s eltelte után. Na de majd ez is kialakul. Mindenesetre köszi az ötletet !

1

ty
ty picture

Köszi a visszajelzést! Örülök, hogy sikerült megoldanod!

0

zus
zus picture

Szia ty ! Szivesen. A mellékelt képen a szimulált frekvenciák láthatóak, amik nem a valós frekvenciák (csak az ötlet működőképességét ellenőriztem). Nyilván, az időértékek sem pontosak és köszönő viszonyban sincsenek a valósággal. A kódot majd bedobom egy 8051-be és akkor meglátjuk, hogy mennyire tér el az elmélet a valóságtól.

0

Ferenc.P
Ferenc.P picture
*

Szia!
https://www.electro-tech-online.com/threads/produce-2-square-wave-at-the...
pl. a Proteus ismeri a 8051-t, lehet kisérletezni a kódal.

0

zus
zus picture

Köszi, ezt ismertem. Igazából elegánsabban szerettem volna kivitelezni a dolgot. Ty kolléga ötlete az nagyon elegáns volt és ebben a helyzetben szinte tökéletes is. Lehet, hogy meg lehett volna oldani másképp is, valószínűleg igen, de én nem vagyok programozó. Amúgy meg, nem is bántam, hogy egy - az itteni népek szerint - "kőkorszaki" mikrovezérlővel kellett megoldani a dolgot. Ha ezzel meg tudom oldani a dolgot, akkor a profibbakkal biztosan. Jó kis önképzés, he-he. laugh

0

proba
proba picture

Magam eszétől valamely timmert felprogramoznám az egyik frekire egy másikat a másikra, amikor letelt, a hozzá tartozó kimenet vált. Megszakításból kezelve szerintem a 12MHz kvarccal az 500-700 Hzt tudnia kellene különösebb terhelés nélkül. Viszont 50-100 órajel hiba is lehet az élek között.  
Vagy megkeresed a frekvenciák periódusidejének a felének a legnagyobb közös osztóját arra felprogramozol egy timmert, és pl minden  10. megszakításnál az egyik kimenetet váltod, a 12. nél meg a másikat.
Az is kérdés mennyire fontos a pontosság ( a 700 Hz lehet pl 714, mert az osztásokból úgy jön ki)  változtathatónak kell e lenni? Mit kell még csinálni a processzornak, mennyi holtidő van?

0

zus
zus picture

Szerencsére nem voltak ennyire szigorúak a feltételek. Ellenkező esetben, sokkal nagyobb szívás lett volna, mert valóban még egy csomó dolgot figyelembe kellett volna venni. Ahogy vésted.

0

ty
ty picture

Szerintem ez programozástechnikailag egyáltalán nem egy bonyolult feladat.
Kb. 20 sor kódról beszélünk.
Két timer interruptra van szükséged.

#1 Az 500 Hz négyszögjel előállításához másodpercenként 1000 interrupt kell -> 1ms timer,

#2 a 700 Hz négyszögjel előállításához másodpercenként 1400 interrupt kell -> 714 us timer.

A két timer interruptban egyetlen egy sor kódot kell elhelyezz, azt ami átbillenti az adott IO lábat.

A nyomógomb megnyomása engedélyezheti/tilthatja/inicializálhatja a timer interruptokat,
attól függően, hogy pontosan hogyan szeretnéd a működést.

 

0

zus
zus picture

Ez jól hangzik, utánajárok. 700 ms ideig kell a dupla frekvenciáknak egyszerre menniük. Azon gondolkodom, hogy ezt hogy valósítom meg.

0

Istvan-lab
Istvan-lab picture

Szia

Szerény véleményem szerint csak akkor fogod tudni megvalósítani a két frekvenciát ha van közöttük valamilyen bineáris matematikai számítási viszony.
Ez az egyszeűbb út. De gyanítom nincs. Vagyis az egyik nem a másik kétszerese.
Ha fel tudsz írni bármilyen 2-es számrendszerű képletet akkor belső osztásokkal elő tudnád állítani.
Azt nem írtad, hogy van-e lehetőséged külső timer vagy jelgenerátor megvalósítására.
A soros programozás hátrányával küzdesz.
Ha nem sikerül megoldani akkor nekem csak extrémebb megoldások jutnak eszembe.
Az SMD technika miatt a 8051 "hátán" (tetején) már sok minden elfér :)
Nem tudom mibe akarod bele építeni, új vagy régi gépezet, és egyszerűbb lenne ha leírnád a két konkrét krekvenciát.

A másik fontos kérdés, hogy változtatható vagy fix frekiket szeretnél ?

István.

0

zus
zus picture

Az a baj, hogy miután eredetileg is perverz értékű frekvenciák voltak (és azokat kell most visszaadni), semmilyen matek nincs közöttük. Bár lett volna ! Meg lettem volna mentve. Négyféle frekvencia volt és látszólag semmi kapcsolat nincs közöttük. Amennyiben viszont meg tudom oldani a timer interruptok menetközbeni átinicializálását, akkor már csak türelemjáték, hogy a kérdéses frekvenciákat megkapjam. Mert ugye más a jól kiszámolt elmélet, más a fejlesztő környezet elképzelése a dolgokról (milyen tömör kódot generál ?) és más a valóság is. Gyanítom, hogy majd egy egyszerű kóddal ki fogom tapasztalni valahogy, hogy a két timer egyszerre működtetése mennyire terheli a rendszert, mennyire távolodnak el a generált négyszögjelek az elméletileg kiszámítottól ?

0

AzzA
AzzA picture
*

Szerintem az egyszerre az a multitask
az egy két ciklus pedig a soros programozásbòl eredö késés.
Ha külön külön megy, akkor tedd egy ciklusba.

0

zus
zus picture

Ja-ja, majdnem egy multitask. laugh Pont a soros programozással van a szívás. Pláne, ennél az egyszerű gépnél. 

0

AzzA
AzzA picture
*

Itt egy minta, használd T0 melett T1 -et is.
És  léteznek PWM kontrol IC-k is ha ....
Akkor talán nem kell a kontroller tetejére várat építeni blush

#include<reg51.h>

// PWM_Pin
sbit PWM_Pin = P2^0;           // Pin P2.0 is named as PWM_Pin

// Function declarations
void cct_init(void);
void InitTimer0(void);
void InitPWM(void);

// Global variables
unsigned char PWM = 0;      // It can have a value from 0 (0% duty cycle) to 255 (100% duty cycle)
unsigned int temp = 0;    // Used inside Timer0 ISR

// Main Function
int main(void)
{
   cct_init();              // Make all ports zero
   InitPWM();              // Start PWM
 
   PWM = 127;              // Make 50% duty cycle of PWM

   while(1)                // Rest is done in Timer0 interrupt
   {}
}

// Init CCT function
void cct_init(void)
{
    P0 = 0x00;   
    P1 = 0x00;   
    P2 = 0x00;   
    P3 = 0x00;  
}

// Timer0 initialize
void InitTimer0(void)
{
    TMOD &= 0xF0;    // Clear 4bit field for timer0
    TMOD |= 0x01;    // Set timer0 in mode 1 = 16bit mode
    
    TH0 = 0x00;      // First time value
    TL0 = 0x00;      // Set arbitrarily zero
    
    ET0 = 1;         // Enable Timer0 interrupts
    EA  = 1;         // Global interrupt enable
    
    TR0 = 1;         // Start Timer 0
}

// PWM initialize
void InitPWM(void)
{
    PWM = 0;         // Initialize with 0% duty cycle
    InitTimer0();    // Initialize timer0 to start generating interrupts
                     // PWM generation code is written inside the Timer0 ISR
}

// Timer0 ISR
void Timer0_ISR (void) interrupt 1   
{
    TR0 = 0;    // Stop Timer 0

    if(PWM_Pin)    // if PWM_Pin is high
    {
        PWM_Pin = 0;
        temp = (255-PWM)*PWM_Freq_Num;
        TH0  = 0xFF - (temp>>8)&0xFF;
        TL0  = 0xFF - temp&0xFF;    
    }
    else         // if PWM_Pin is low
    {
        PWM_Pin = 1;
        temp = PWM*PWM_Freq_Num;
        TH0  = 0xFF - (temp>>8)&0xFF;
        TL0  = 0xFF - temp&0xFF;
    }

    TF0 = 0;     // Clear the interrupt flag
    TR0 = 1;     // Start Timer 0

0

SzBálint
SzBálint picture
****

szia: 700x500 osztható?

Bálint

0

zus
zus picture

Persze. 1,4 lesz. De ezzel még nem voltam beljebb.

0

Sponsored links