Fórum témák

» Több friss téma
Fórum » PIC - Miértek, hogyanok haladóknak
Lapozás: OK   1172 / 1320
(#) Attila86 válasza watt hozzászólására (») Ápr 18, 2014 /
 
Egy egyébként másodpercekig tartó kis bitbillegtetést csinál (nagyon leegyszerűsítve), viszont a szubrutin meghívása előtt be lehet állítani hogy hányszor csinálja meg a feladatot. És nagyon nagy számot is be lehet írni, ezért tarthat el sokáig.
(#) Hp41C válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Egy golbális bit állapotjelzőnek. A rutin meghívása előtt a jelzőbitet törölni, a megszakítási rutinban a gomb megnyomásakor (pergésmentes) 1 -be állítani. A rutin figyeli a jelzőbitet, ha 1, akkor kilép a rutinból azaz a rutin függvényének viszzatéséri részére ugrik.
A hozzászólás módosítva: Ápr 18, 2014
(#) watt válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
A folyamat egy állapot tarthat bármeddig, ha megfelelő időközönként megvizsgálod egy állapotgép ciklusában, hogy mikor kell változtatni az állapotokon. Ugyanekkor az is megvizsgálahatod, hogy ki kell-e lépni az adott állapotból, vagy akár több állapotból...
A hozzászólás módosítva: Ápr 18, 2014
(#) Attila86 válasza Hp41C hozzászólására (») Ápr 18, 2014 /
 
Hát ilyen egyszerű megoldást én is tudok!
Persze, ez működne csak nem akarom átírni a szubrutint! Legalábbis ennyire nem. Az elejére és a végére egy ilyen bit be-ki billentése mint amit írtam még belefér, de az hogy a rutinban időnként ellenőrizzem hogy a gomb le lett-e nyomva már nem.
Mondok egy hasonlatot:
A szubrutinom egy SOS-jelzést ad le egy LED-en és így néz ki:
  1. Jelzes_SOS ;szubrutin címkéje
  2.  
  3. ;három rövid:
  4. bsf LED
  5. call delay200ms
  6. bcf LED
  7. call delay200ms
  8. bsf LED
  9. call delay200ms
  10. bcf LED
  11. call delay200ms
  12. bsf LED
  13. call delay200ms
  14. bcf LED
  15. call delay200ms
  16.  
  17. ;három hosszú:
  18. bsf LED
  19. call delay1s
  20. bcf LED
  21. call delay1s
  22. bsf LED
  23. call delay1s
  24. bcf LED
  25. call delay1s
  26. bsf LED
  27. call delay1s
  28. bcf LED
  29. call delay1s
  30.  
  31. ;három rövid:
  32. bsf LED
  33. call delay200ms
  34. bcf LED
  35. call delay200ms
  36. bsf LED
  37. call delay200ms
  38. bcf LED
  39. call delay200ms
  40. bsf LED
  41. call delay200ms
  42. bcf LED
  43. call delay200ms
  44.  
  45. RETURN

Nem akarok minden egyes "call delay..." után betenni egy nyomógomb-vizsgálatot (btfss, bra...) mert ronda és nem is jó. Mert ha meghívom az egyik 1 másodperces időzítést majd rögtön utána megnyomják a gombbot akkor még majdnem egy másodpercig nem fog megtörténni a "vészleállítás" dolog. Tudom, most azt fogjátok mondani hogy nem szabad ilyen, főleg nem ilyen hosszú delay késleltetéseket használni. De nem morzézni akarok a programban hanem ez csak egy hasonlat volt mert nem akarok bemásolni hatszáz sornyi kódot ami rajtam kívül mindenkinek valószínűleg érthetetlen lenne.
(#) Hp41C válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Furcsa az, amit kérsz: Nem tudjuk, mit csinál a programod, nem tudjuk mi a célod, csak egy konkrét kérdést teszel fel. Az ajánlott megoldás persze az információ hiánya miatt Neked elfogadhatatlan. De akkor miért teszed fel a kérdést? Írd át az egész pogramot Állapotgépre.
(#) watt válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Na erről beszéltem. Ez itt az elrettentő példa!
(#) Attila86 válasza watt hozzászólására (») Ápr 18, 2014 /
 
Pont ez a lényeg hogy nem akarom időnként megvizsgálni mert az "időnként" azt jelenti hogy két vizsgálat közt bizonyos idő fog eltelni amit nem engedhetek meg. Nem véletlen "vész"leállítás a funkciója az egésznek. Egy nagy piros vészgomb megnyomásakor AZONNAL meg kell történnie annak a változásnak amit a vészgombnak okoznia kell. Persze, csökkenthetném a vizsgálati időt de akkor sokat dolgozik majd feleslegesen a mikrovezérlő és ez nem túl elegáns. A legjobb megoldás a hardveres interrupt amit szeretnék. Igazából nem is az a gond hogy a gomb megnyomásakor azonnal hajtódjon végre egy valamiféle vészleállító rutin, hiszen ezt egyszerűen belepötyögöm az interruptba. A gond az, hogy miután a vészgomb megnyomását a megszakításban érzékeltük, lekezeltük és elvégeztük magát a "vészleállítást" (mely egyébként a PIC egyetlen lábának 0-ba állításával valósul meg), akkor a megszakításból ne a szubrutinba térjen vissza a PIC hiszen akkor folytatni fogja a szubrutint amit nem szabad neki! Tehát a lényeg hogy ne a szubrutinba térjen vissza a megszakításból hanem oda ahonnan a szubrutin meg lett hívva.
Rajzoltam nektek

szubrutin.png
    
(#) nedudgi válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Nem tudom, miért nem jó egy teljes reszet, de legyen.
Van egy komoly szubrutinunk, amit több helyről hívunk meg, és változó idejű a hosszúsága, mert különböző ismétlési paraméterekkel van meghívva. Gondolom, van egy memóriában levő számláló, amit a rutinban vizsgálsz. Az jó, ha a megszakításban ezt az értéket átállítod a visszatérést okozó értékre? Persze, ilyenkor a hosszúrutin végfeltételvizsgálat idejére tiltani kell az interruptot, hiszen nem feltétlenül egy utasításból áll a vizsgálat. Ezzel a módszerrel legfeljebb egyszer fut le a hosszúrutin, utána visszatér.
Azért a reszet sem az ördögtől való. A kontroller induláskor meg tudja állapítani, miért indult újra (tápmegszűnés/visszatérés, tápcsökkenés, reszet láb, reszet gomb). Ez típusfüggő, de sokféle állapot behatárolható, valószínűleg nem kell teljesen újra inicializálni mindent.
A hozzászólás módosítva: Ápr 18, 2014
(#) watt válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Sajnálom, hogy nem érted a módszert, most igazából azt sem tudom, hogyan kellene elmagyarázni neked, ha eddig nem értetted meg. A felhasználó szemszögéből az események, felfüggesztések, vészleállások azonnalinak tűnnek, de gépi folyamatok vezérlésénél is "azonnali" egy állapotváltozás hatása, ha megfelelő sebességű az állapotgép frissítése. A sebességet befolyásolja a vizsgálatok, elágazások száma, de ha jól láttam a te esetedben ez nem kritikus.
Gondold el, simán lehet szabályozni áramkörben egy feszültség nagyságát úgy, hogy az AD mér, kiértékelődik az eltérés, korrigálódik a PWM értéke és ez periódikusan ismétlődik, miközben LCD kijelzés, kommunikáció bármi más működik mellette. Gondolod, hogy pont LED-eket nem lehet villogtatni ilyen megbízhatóan?
(#) Attila86 válasza Hp41C hozzászólására (») Ápr 18, 2014 /
 
Szinte mindig ez történik mikor egy komolyabb kérdést teszek itt fel ebben a topikban: Felteszek egy kérdést és utána jönnek a válaszok hogy ez így nem jó ezt nem így kell stb. Kiváló példa erre a pár hónappal ezelőtti felvetésem ami több, körkörösen összekapcsolt mikrovezérlő közti kommunikáció mikéntjéről szólt. Ott is az elején leírtam hogy nem jó a master-slave megoldás és nincs semmi szinkronizálás, a mikrovezérlők nem tudják egymásról hogy hány van sorba kötve, nincs egyedi azonosítójuk stb. Utána két napig és három oldalon át tartott mire sikerült rávezetnem mindenkit és meggyőznöm hogy valóban nem jó a master-slave és azért nem jó amiért stb... Végül az eredeti kérdésemre nem is reagált senki mert az elveszett az ilyen felesleges elágazások erdejében.
Ezekből tanulva most már az adott problémát inkább próbálom leegyszerűsíteni és így feltenni a kérdésem itt a fórumon.


Tehát: szeretném hogy a megszakításból a mikrovezérlő ne oda ugorjon vissza ahonnan elugrott hanem a veremtárban egy (vagy több) címmel feletti címre. Ez elvileg szerintem egy egyszerű POP utasítással megvalósítható, csak ha a kérdéses szubrutinban is meghívtam egy másik szubrutint, akkor honnan tudja a PIC hogy a verem tetejéről hány címet kell eldobni?
A hozzászólás módosítva: Ápr 18, 2014
(#) watt válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
A helyzet az, hogy általában rosszul közelíted meg a feladatot, mi meg nem vagyunk hajlandóak beülni a körhintádba, mert nekünk nem tetszik a fordulata! Most is jobb lett volna, ha csendben maradok...
A hozzászólás módosítva: Ápr 18, 2014
(#) Attila86 válasza watt hozzászólására (») Ápr 18, 2014 /
 
Azt hiszem értelek Watt, de az egész szoftver átírása (állapotgépre) túl nagy munka lenne, legalábbis a funkció hasznát tekintve. Egy fél éve fejlesztett programot nem írnék át az alapjaiban, viszont egy ilyen megoldással szerintem nagyon szuperül implementálható lenne a dolog a mostani szoftverbe.
(#) Attila86 válasza watt hozzászólására (») Ápr 18, 2014 /
 
A példaként említett esetben is (mikrovezérlők közti kommunikáció) végül nagy nehezen kiderült hogy az a legjobb megoldás amit a legelején leírtam. Tehát jó volt az én körhintám, csak hosszadalmas volt elmagyarázni hogy miért.
A hozzászólás módosítva: Ápr 18, 2014
(#) watt válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Legyen így...
(#) Ktulu válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Minden szubrutin hívás előtt növelhetsz egy számlálót, (ami a main ciklusban 0) return előtt pedig csökkented egyel. A kérdés az, hogy mi alapján döntöd el, hogy hányat lépj vissza? (ha mondjuk a számlálód értéke éppen 5)
Legegyszerűbb, ha a vész megszakítás után mindig egy jól meghatározott helyre ugrasz a programban, ahonnan majd eldöntöd a továbbiakat. (előny a resettel szemben, hogy minden változód sértetlen)
(#) HeZ válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Honnan tudod, visszafelé a hányadik szubrutinra kell visszaugorni?
Más szóval: hány szubrutint kell kihagyni?
Ha nem tetszik az állapotgép felépítés, használj globális változót a verem mélység mérésére, azaz minden call-interrupt növelje ezen változó méretét, minden return csökkentse. Ha a vészgomb megszakítás pl. az 5-ös számláló értéknél történik és a 2.-hoz akarsz visszatérni, akkor a verem 2. címére kell ugornod.
Az ilyen sötét keverések miatt bug-os sok szoftver, ez az átláthatatlanság és rejtélyes hibajelenségek melegágya . De nem kell hinned Watt-nak, Hp41c-nek, nekem meg pláne nem .
(#) Attila86 hozzászólása Ápr 18, 2014 /
 
Utánaolvastam hogy mit értetek állapotgép alatt. Nos jelentem a programom jelenleg is így működik!
Az említett nyomógomb egy mátrixba van kötve és ennek a mátrixnak a kezelése történik jelenleg megszakításban. Bizonyos időközönként (5ms) megszakítást generál egy timer és a megszakításban a gombmátrixon továbblépteti a PIC a következő oszlophoz tartózó lábra a villanyt. A mátrix sorai pedig az INT lábakra vannak kötve azaz hardveres megszakítást generál minden gomblenyomás. A megszakításban pedig gyönyörűen megtörténik a pergésmentesítés az idő mérésével sőt, rövid és hosszú gombnyomások is megkülönböztethetőek. Az INT lábak megszakítási éle (fel vagy lefutó) dinamikusan változik és eszerint van a megszakításban egy szoftveres számláló növelve/nullázva, azaz gyakorlatilag mint egy stopper tudja a szoftver hogy az adott gomb mennyi ideig volt lenyomva. Ezzel egyben a pergésmentesítés is megoldott.
Végeredményben minden nyomógombhoz tartozik egy bit amit kijelöltem és elneveztem a gombok funkciója szerint és a megszakítás ezeket a biteket billegteti. Azaz ha kíváncsi vagyok hogy le lett-e nyomva egy gomb vagy sem, akkor a főprogramban csak le kell kérdeznem a hozzá tartozó bitet (btfss GOMB1, bra$-2).
Ezen felül az 5ms-os megszakítás több más számlálót is inkrementálgat, ezzel különböző, nagyon pontos időzítéseket is megvalósítok. Például a kis piezo csipogó csipogását; A főprogramban csak be kell billentenem egy bitet (nevezzük "csipogás_kérés" bitnek) és ezt a bitet figyeli a megszakításban egy programrész ami az előbb említett számlálók közül egyet inkrementálgat mindaddig míg el nem ér egy értéket és akkor lekapcsolja a piezot. Így ha azt akarom hogy mondjuk egy másodpercig sípoljon a piezo akkor a főprogram tud futni tovább, mert csak be kell billentenem ezt a bitet és a megszakítás gondoskodik róla hogy ha lejárt az idő akkor kikapcsoljon a piezo. Hasonlóképp egyébként kisebb dallamokat (rövid-hosszú sípolások) is meg tudok könnyen valósítani.

Szóval tudom én mi az az "állapotgép", csak a nevét nem ismertem.
(#) Hp41C válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Ennek sincs akadálya. Egy "quick and dirty" megoldás:
Legyen egy 24 bites (esetleg 16 bites, ha a program memória < 64K) változód, amibe beteszed a "kilépős" rutinod hívása utáni címet. Meghívod a "kilépős" rutinodat. A "kilépős" rutin is kimásolhatja a stack -ról. A megszakításban, ha a kilépési feltétel összejön, visszafejted a stack -et (pop) addig, ameddig a TOS meg nem egyezik az eltett címmel. Ekkor átírod a TOS -t a "másik" rutin kezdőcímére. Már csak a megszakítási rutin regiszter visszaállítási pontjára kell ugrani. Ha a megszakítási rutinból visszatér, a következő utasítás a "másik" rutin első utasítása lesz.
Fogadjunk, hogy már gondoltál rá...
A hozzászólás módosítva: Ápr 18, 2014
(#) Attila86 hozzászólása Ápr 18, 2014 /
 
Azt hiszem rájöttem:
Meghívom a kérdéses szubrutint. A szubrutinban rögtön az elején elmentem magának a szubrutinnak a címét egy regiszterbe. Utána megvizsgálok egy bitet melynek neve legyen "VÉSZSTOP". Ha ez az bit egy, akkor jön egy RETURN, ha pedig nulla akkor ugrik és végrehajtódik a szubrutin teste.
A megszakítás pedig úgy néz ki hogy ha a nyomógomb miatt a mikrovezérlő belép a megszakításba, akkor bebillenti ezt a VÉSZSTOP bitet majd megnézi a veremtárat hogy hol van benne a szubrutinnak a címe amit a szubrutin elején elmentettünk egy regiszterbe (ezért kellett elmenteni). A veremben felette lévő visszatérési címeket szépen eldobja hogy a szubrutin címe legyen legfelül. Utána RETFIE-vel kilép a megszakításból, na de mivel megbabráltuk a veremtárat ezért nem oda fog visszaugrani ahova eredetileg kellene neki, hanem a szubrutin elejére! Ott pedig ugyebár ott lesz a VÉSZSTOP bitjének vizsgálata, és mivel most 1-be van állítva így szépen ráugrik a RETURN-ra.
Ezzel a megoldással nyugodtan lehet a szubrutinon belül akárhány szubrutint hívni és a szubrutint is meg lehet bárhonnan hívni, a nyomógomb megnyomásával mindig oda tér vissza ahonnan meg lett hívva.
(#) Attila86 válasza Hp41C hozzászólására (») Ápr 18, 2014 /
 
Hehe...!
(#) Attila86 válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Csak szerintem ott fog megbukni a dolog hogy úgy emlékszem a Kónya-könyvből hogy a veremtárat nem lehet olvasgatni. Csak beleírni lehet legfelülre és a legfelsőt eldobálni, de úgy rémlik hogy kiolvasni sajnos nem lehet. Ugye rosszul emlékszem?
(#) Attila86 válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Igen, szerencsére rosszul emlékeztem mert olvasható is a verem, de csak a legfelső (TOS). Ami persze nem különösebb gond hiszen legrosszabb esetben kipakolászok belőle mindent majd a módosítás után szép sorban vissza. Bár visszaírni nem is kell mert csak kiolvasom, ha egyezik az elmentettel akkor oké ha nem akkor törlöm és vizsgálom a következőt stb.

Na, ugye hogy nem hülyeség a körhintám? Értelmeseket kérdezek én szerintem, csak meg kell győznöm titeket hogy értelmes a kérdésem. Vagy az is lehet hogy rosszul kérdezek.

Azért köszönöm mindegyikőtöknek a segítséget!
A hozzászólás módosítva: Ápr 18, 2014
(#) watt válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
De hülyeség. Valamint ez több időbe telik, mint ha normálisan szervezted volna a folyamatokat és nem menet közben kínlódnád össze olyan megoldásokkal, amit egy programozó indokoltnak látszó esetben is csak úgy használ, ha pisztolyt nyomnak a halántékához! Sok sikert a káoszhoz!
(#) Hp41C válasza Attila86 hozzászólására (») Ápr 18, 2014 /
 
Akkor lesz vele nagy gond, ha akkor nyomják meg a "Vészstop" -ot, ha nem ebben a rutinban kóvályog a program...
(#) Attila86 válasza Hp41C hozzászólására (») Ápr 18, 2014 /
 
Ezért kell egy másik bit ami globálisan engedélyezi ezt az egész műveletet. A szubrutin elején mikor elmentem a szubrutin címét akkor ezt a bitet is át kell állítani. Amikor a nyomógomb lenyomódik akkor a megszakításban azzal kezd hogy ellenőrzi ezt az engedélyező bitet. Ha 0 akkor rögtön ki is léphet a megszakításból rendesen a RETFIE-vel.
(#) proba válasza Attila86 hozzászólására (») Ápr 19, 2014 /
 
A magam eszétől, a delay ciklus mindegy, hogy semmit nem csinál vagy a gombot figyeli állandóan...
(#) Attila86 hozzászólása Ápr 22, 2014 /
 
Ma végre volt egy kis időm foglalkozni a pénteken felvázolt ötlettel. Volt pár kisebb gond de megoldottam. Abszolút jól használható ez a a dolog, el tudom menteni külön regiszterekbe és ki tudom olvasgatni a verem tartalmát, össze tudom hasonlítani, el tudom dobálni ami nem kell stb. Nincs ezzel gond, persze észnél kell lenni hogy miket dobálunk el és hova ugráltatjuk a mikrovezérlőt, de alapvetően szerintem ez egy teljesen jól használható megoldás.
(#) HeZ válasza Attila86 hozzászólására (») Ápr 22, 2014 /
 
Kikívánkozott belőlem a kisördög:
a programozásod olyan, mint a házasság: brilliáns megoldás olyan problémára, ami amúgy fel sem merül
(#) Attila86 hozzászólása Ápr 24, 2014 /
 
Hogyan lehet assembly-ben a fordítónak utasítást adni? Olyat szeretnék megvalósítani hogy nagyon könnyen változtatni lehessen hogy egy 4-5 soros kódrészletet befordítson-e a programba vagy sem. Hogy ne kelljen mindig kikommentelni...
(#) Hp41C válasza Attila86 hozzászólására (») Ápr 24, 2014 / 2
 
  1. #define NEMKELL
  2.  
  3. #ifndef NEMKELL
  4. ; kód, ami nem kell
  5. #endif
Következő: »»   1172 / 1320
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem