Fórum témák

» Több friss téma
Fórum » PIC - Miértek, hogyanok haladóknak
Lapozás: OK   1194 / 1319
(#) usane válasza cross51 hozzászólására (») Júl 9, 2015 /
 
Az a baj, hogy nekem kódszinten kell. Csak ideiglenesen működne hídként amíg az eszközt felkalibrálom, aztán már egy másik firmware futna a PICben. Ezért felesleges a külön csip, ha aztán már nem használom, ráadásul növeli a költséget. Ha nincs más megírogatom, csak ez megint idő amiből nekem nincs.
(#) cross51 válasza usane hozzászólására (») Júl 9, 2015 /
 
Hát, ha mindenképpen kód szinten kell akkor ezt ajánlom Bővebben: Link.
(#) usane válasza cross51 hozzászólására (») Júl 9, 2015 /
 
A 2013 06 15-ös Legacy verziót már használtam 8 bitre. Ezt még nem néztem, de belenézek, köszi.
A hozzászólás módosítva: Júl 9, 2015
(#) zenetom hozzászólása Júl 19, 2015 /
 
Hali
18F-nél az External Block Table Read (EBTR) működése vagy nem egészen világos nekem, vagy valami huncutság van. Tegyük föl, bekapcsolom az összes EBTR-t. Ha pl. a Block0-ban van a program, ami a Block1-ből akar kiolvasni táblaolvasással, akkor ha jól értelmeztem az adatlapot, 0-t kéne kapnom. Ennek ellenére ugyanúgy kiolvassa.
Foglalkozott már valaki ezzel a témával?
(#) zenetom válasza zenetom hozzászólására (») Júl 19, 2015 /
 
Na valamivel előrébb vagyok. Egyszerűen nem írja be a PIC-be az EBTR konfigbitet a programozó, ha be van kapcsolva a többi kódvédelem. Ha kikapcsolom a többi kódvédelmet (vagy lehet elég csak az egyiket, de most lusta vagyok végigpróbálni..), akkor meg beírja...
Ördögi kör..
Szerk.: végülis most nincs rá szükségem, csak érdekes..
A hozzászólás módosítva: Júl 19, 2015
(#) zenetom válasza zenetom hozzászólására (») Júl 19, 2015 /
 
Bár nem próbáltam ki, de most esett le, hogy pont az EBTR konfigszava van a WRTC után, szóval ha a konfigvédelmet ki van kapcsolva, akkor már lehet menni fog...
Na ez jó kis monológ volt így a magam részéről, de majd egyszer hátha más is találkozik ezzel, és akkor már le van írva.
(#) Attila86 hozzászólása Júl 21, 2015 /
 
Sziasztok!
PIC18F25K80-al és XC8 fordítóval szeretnék kivitelezni kétszintű megszakítást.
A magas prioritású megszakítást a timer2 kezdeményezheti, az alacsonyat pedig a timer0. Pontosabban igazából nem a timer0 mert a timer0 ki van kapcsolva, csak a flagbitjét használom (használnám) fel arra hogy szoftverből kezdeményezhessek alacsony prioritású megszakítást.
Vagyis:
Ha a timer2 túlcsordul, akkor lépjen be a magas prioritású megszakításba. Ott pedig bizonyos feltételek fennállása esetén manuálisan 1-be billentem a timer0 flagbitjét. Majd halad tovább a magas prioritású megszakítás kiszolgálása és miután kilép belőle a PIC, elvileg azonnal bele kellene hogy lépjen az alacsony prioritású megszakításba. Erre azért van szükségem nyilván, hogy a manuálisan kikényszerített alacsony prioritású "timer0" megszakítást a közben beérkező újabb timer2 megszakítás meg tudja szakítani.

A megszakítás beállítása így néz ki:
  1. RCONbits.IPEN=1;        //Kétszintű megszakítások engedélyezése
  2. PIE1bits.TMR2IE=1;      //TMR2 megszakítás engedélyezése
  3. IPR1bits.TMR2IP=1;      //TMR2 megszakítás magas prioritású lesz
  4. INTCONbits.TMR0IE=1;    //TMR0 megszakítás-engedélyezése (csak a flagbitjét használjuk az alacsony pioritású megszakítások meghívásához!)
  5. INTCON2bits.TMR0IP=0;   //TMR0 megszakítás alacsony prioritású lesz
  6. INTCONbits.PEIE=1;      //periféria megszakítás engedélyezése
  7. INTCONbits.GIE=1;       //globális megszakítás engedélyezés


A megszakítások pedig:
(Kitöröltem belőle a sallangot hogy átláthatóbb legyen a lényeg)
  1. void interrupt high_priority High_Int(void)
  2. {
  3.     if(PIR1bits.TMR2IF)     //Ha a TMR2 okozta a megszakítást, akkor belelépünk
  4.     {
  5.         PIR1bits.TMR2IF=0;  //Flagbit törlése
  6. //Ide jön egy csomó sallang...
  7.         Sz10ms++;
  8.         if(Sz10ms>200)
  9.         {
  10.             Sz10ms=0;
  11.             UARTkuldesFlagbit=1;
  12.             INTCONbits.T0IF=1;      //Kérvényezzük az alacsony prioritású megszakítást!
  13.          }
  14. //Itt is van egy marék lényegtelen kódsor...
  15.     }
  16. }
  17.  
  18. void low_priority interrupt Low_Int(void)
  19. {
  20.     if(INTCONbits.TMR0IF)
  21.     {
  22.         INTCONbits.TMR0IF=0;    //Flagbit törlése
  23.         if(UARTkuldesFlagbit)
  24.         {
  25.             UARTkuldesFlagbit=0;
  26.             while(Busy1USART());
  27.             Write1USART('A');
  28. //Itt van még néhány lényegtelen UART-küldözgetős sor...
  29.         }
  30.     }
  31. }


Gyakorlatilag annyi történik hogy a magas prioritásúba belép rendesen, az alacsonyba pedig sosem. Van esetleg ötletetek hogy mi nem stimmel?
A hozzászólás módosítva: Júl 21, 2015
(#) AZoli válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Szia!
Régen foglalkoztam a 18F családdal, de nem vagyok biztos benne hogy egy flag bit 1-be állítása megszakítást vált ki, és még abban sem, hogy ezek a bitek nem csak törölhetőek-e?
TMR0 menjen belső órajelről, és HIPV -ben ha megszakítást akarsz, engedélyezd a TMR0 -t, és tölts 0xFF -et bele.
Amúgy kifejezetten erőltetett már az alapgondolat is, biztos hogy van szép megoldás is... mert hogy ez nem az.
A hozzászólás módosítva: Júl 21, 2015
(#) Attila86 válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Nos nem tudom hogy mi volt a baj de addig kutyulgattam a dolgokat mire egyszer végre sikerült megoldani a problémát. Most már pontosan azt csinálja amit szeretnék, rendesen belép az alacsony prioritású megszakításokba amikor azt kérem a magas prioritás kiszolgálásában.
(#) Attila86 válasza AZoli hozzászólására (») Júl 21, 2015 /
 
A flagbitek nem csak törölhetőek hanem 1-be is lehet őket állítani és ezáltal megszakítás generálódik. Ezt én tudtam már eddig is mert korábban már csináltam ilyet. Csupán a kétszintű megszakítás az az amire eddig még nem volt szükségem. Pontosabban már volt, de dsPIC-en és ott egész másképp vannak a megszakítások (sokkal jobb).

Idézet:
„Amúgy kifejezetten erőltetett már az alapgondolat is, biztos hogy van szép megoldás is... mert hogy ez nem az.”

Szerintem sem a legelegánsabb, de nem jutott eszembe jobb. A gyakorlatban (immár) viszont tökéletesen működik.
Nem feltétlen szeretnék belemenni a témába mert félek megint csak flame lenne belőle, de úgy gondolom hogy érdekes a téma és megéri megvitatni a dolgot. Ezért vázolom a teljes program működését, röviden:
- A timer2 pontosan 50us-onként megszakítást generál ahol elindítom az A/D-t hogy vegyen mintát a PIC egyik lábáról. A következő (50us múlva bekövetkező) timer2 megszakításkor a mintavételezés eredményét elmentem egy nagy tömbbe (addigra bőven lejár a mintavételezési idő, nem szükséges az ADIF-et figyelnem). Ez után ismét elindítom az A/D-t. Ez megy a végtelenségig. A mérendő jel felhasználásának célja miatt nem tehetem meg hogy kihagyok akár csak egyetlen mintát is a jelből. Vagyis minden 50us-onként mintát kell, muszáj vennem a jelből.
- 10ms-onként kiátlagolom a mintavételi tömbböt és az eredményt elküldöm UART-on. Az UART küldési részt meg kell hogy tudja szakítani a timer2, különben a küldés alatt nem fog mintavételezni a PIC.
- Logikus következtetés lenne a fentiek ismeretében, hogy akkor az UART küldés legyen a főprogramban, és így a timer2 simán meg tudja azt szakítani. Azonban a PIC végez még egy fontos dolgot: a mintavételi tömbbön különböző bonyolult és nagyon nagy számítási időt igénybe vevő matematikai számításokat hajt végre (pl Furier analízis). Ezek a függvények durván 100-150ms(!) időbe telnek míg lefutnak. Ezek a függvények értelem-szerűen a főprogramban foglalnak helyet, ahol igazából nincs is semmi más (a PIC inicializálásán kívül).
- Hogyha az UART küldést is a főprogramba tenném bele a bonyolult algoritmusok utánra, akkor nem tudnék 10ms-onként adatot kiküldeni az UART-on, csak akkor hogyha az analízisek lefutottak, mivel ezeken mint írtam durván 100-150ms alatt megy át a PIC.

Ezen információk ismeretében kíváncsi vagyok, hátha valóban van valakinek jobb ötlete mint amit én megvalósítottam. (Egy kikapcsolt periféria (timer0) flagbitjének manuális 1-be állítása és utána alacsonyabb prioritáson az UART küldés lebonyolítása).
Szerintem az hogy nem arra használok egy flagbitet amire a Microchip kitalálta, annyira nem ördögtől való. Itt azért nem a stack kiolvasásáról és eldobálgatásáról van szó...

Egyébként egyetlen más megoldás jut csak eszembe, hogy belenyúlok ezekbe a nagy idő alatt lefutó algoritmusokba és megpróbálom olyan részekre bontani amely részek lefutnak kevesebb mint 10ms alatt és ezeken a helyeken teletűzdelgetem az UART-küldő függvény meghívásával. De ez sem túl szép sőt, szerintem sokkal rondább megoldás. Egy függvény csak azt az egy dolgot csinálja szerintem ami az eredeti célja, mást ne. Péládul egyszerűen azért, mert így azokat a függvényeket nem lehet simán csak beinclude-olni más projektekbe, ahol jó eséllyel csak az analízis kellene, UART meg nem.
A hozzászólás módosítva: Júl 21, 2015
(#) ktamas66 válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Én is csináltam hasonlót asm-ben, működik, a tiedben sem találtam hibát (talán a 12. sorban a T0IF lehetne TMR0IF?). Az azonos időben indítandó AD-ra az ECCP modul ad lehetőséget (Compare mód -> Special event trigger -> ADCON1).
(#) benjami válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Ha feltétel a folyamatos 50usec mintavételezés, akkor a következőképpen csinálnám meg:
Timer2 - HI interrupt: A/D mintavételezés (felváltva két tömbbe ha van elég memória hozzá)
UART TX - LO interrupt: adat küldés a soros vonalon (szoftveres FIFO-t olvasást használva)
Főprogram hurok: minták feldolgozása, adat küldése a szoftveres FIFO-ba.

A mintavételezéskor kell ugye egy tömbelem számláló + egy bit, ami azt mondja meg melyik az éppen írás alatt levő tömb. A főprogram folyamatosan figyeli ezt a bitet, ha megváltozott lehet a már teleírt tömb adatait feldolgozni, a végén meg az UART-on elküldeni. Ha már nem fogadóképes az UART TX, akkor mehet a szoftver FIFO-ba, és lehet engedélyezni UART TX interruptot alacsony prioritáson, hogy a mintavételezést ne zavarja. Az alacsony prioritású UART TX megszakításkor szoftveres FIFO-ból lehet olvasni egy bájtot és TXREG-be betenni. Ha már üres, akkor meg le kell tiltani UART TX megszakítást. Ha nincs más tevékenység ezeken kívül, a szoftver FIFO és UART megszakítás nélkül is megoldható simán a főprogramban is a teljes üzenet elküldése.
(#) Attila86 válasza benjami hozzászólására (») Júl 21, 2015 /
 
Nem vagyok benne teljesen biztos hogy jól értem amit írsz de lehet hogy félreértjük egymást egy kicsit. Ha jól értem ugyanis, az UART küldés az elgondolásod szerint akkor hívódna meg hogyha a tömb tele van írva (és ezt figyelné egy bit segítségével a főprogram?). Ez azért nem jó mert 10ms-onként muszáj adatokat küldeni az UART-on. Olyat nem lehet hogy pufferolom az adatokat egy FIFO-ba és amikor van rá lehetőség akkor kiürítem. Tehát 10ms-onként kell egy adatcsomagot küldeni, nem lehet olyat csinálni hogy mondjuk 300ms-ig nem küldök semmit aztán gyorsan kitolom mind a 30 csomagot (300ms/10ms=30).

------------------------------

Amúgy a FIFO-t én nem így szoktam csinálni. Nálam így néz ki egy FIFO:
  1. typedef struct
  2. {
  3.     u16 Wp;
  4.     u16 Rp;
  5.     u16 Size;
  6.     u8  Ures :1;
  7.     u8  Tele  :1;
  8.     u8  Reserved :6;
  9.     RXAdatType Tomb[500];
  10. }RXFIFOtype;

- A FIFO-ba elmentéskor a tömb [Wp] elemébe írom az adatot (Write pointer), majd inkrementálom a Wp-t és a Size-t, illetve 0-ba állítom az Ures nevű bitet. Ha a Wp értéke itt egyenlő az Rp értékével, akkor a FIFO megtelt, a Tele bit 1 lesz.
- A FIFO ürítésekor pedig a tömb [Rp] elemét kiolvasom (Read pointer), inkrementálom az Rp-t és dekrementálom a Size-t, illetve 0-ba állítom a Tele nevű bitet. Ha az Rp értéke itt egyenlő az Wp értékével, akkor a FIFO kiürült, az Ures bit 1 lesz.
- Mindkét esetben (íráskor és olvasáskor is) figyelem hogy a ponterek elértek-e a tömb végére és ha igen akkor nullázom őket. Azaz a körbeforog az egész FIFO.
Nálam ez így nagyon jól bevált.
A hozzászólás módosítva: Júl 21, 2015
(#) Attila86 válasza ktamas66 hozzászólására (») Júl 21, 2015 /
 
A special event triggerre én is gondoltam csak a timer2 amúgy is kell mert különböző időzítéseket is azzal valósítok meg.

Amúgy egy dolog még eszembe jutott most, mégpedig a DMA. Azzal lehetne ügyeskedni és vagy a mintavételezést-tömbfeltöltést, vagy az UART küldözgetést teljesen automatizálni. (Inkább az előbbit.) De sajnos ebben a mikrovezérlőben (PIC18F25K80) nincs DMA.
(#) AZoli válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Nyilván ha van egy működő kód, én sem biztos változtatnék rajta, csak az érdekesség kedvéért folytatom.
TMR1 miért nem saját erőből okoz LP megszakítást 10ms-onként, és küldi UART-on az adatokat?
Ekkor ő megszakíthatja Fouriert, és őt megszakíthatja TMR2.
Kérdem ezt úgy, hogy nem néztem adatlapot, nem tudom hogy órajel vagy egyéb hw akadálya van-e.
(#) Attila86 válasza AZoli hozzászólására (») Júl 21, 2015 /
 
Öhhmm... nos ez eszembe sem jutott. Pedig valóban, elég logikus és így nem kell felhasználni a timer0 (vagy valamilyen periféria) flagbitjét. Még csak azt sem mondhatom hogy azért nem csináltam így mert pontos időzítés kell és arra már elhasználtam a timer2-t, hiszen még ott van a timer4 ami ugyan az. Az ilyen egyszerű megoldás eszembe sem jutott.
(#) Attila86 hozzászólása Júl 21, 2015 /
 
Apropó, ha már írtam: Tudja valaki hogy miért dobja fel ezt az ablakot akkor hogyha másolatot készítek egy projektből, majd azt lefordítom? "BUILD SUCCESSFUL"-al lefordul rendesen, csak a végén kidobja ezt a hibaüzenetet.
(Projects ablakban jobb kattintás a projekt nevére majd "Copy...".)
MPLABX 3.00 csinálja ezt.
(#) kissi válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Sziasztok!
Lehet, hogy nem jól értem, de Attila azt írta, hogy ő billenti be a FLAG-et aszerint, hogy kell vagy sem... ebből én arra következtettem, hogy nem fix az idő, aminek az eltelte után kell küldeni az infót... Nem jól gondolom?
(#) kissi válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Ez az MPLABX már nem érzékeny a speciális karakterekre ( "-" ) és az útvonal hosszára ?!
(#) Attila86 válasza kissi hozzászólására (») Júl 21, 2015 /
 
Szia!
De, fix az idő. 10ms-onként kell adatot küldeni. Ha lenne benne valami függőség akkor (is) jó lenne a megoldásom, így is használható csak valójában felesleges. A timer4 is befogható lenne 10ms-os alacsony prioritású megszakítások generálására.
(#) Attila86 válasza kissi hozzászólására (») Júl 21, 2015 /
 
Úgy tudom a kötőjel nem fáj neki, legalábbis az elmúlt kb 8 hónap amióta MPLABX-et használok ugyan ilyen elérési útjai voltak a projekteknek és eddig nem dobta fel ezt a hibaüzenetet. Csak most kezdte pár napja. Mint látszik a 12. verziónál tart ez a projekt is, idáig ugyan ilyen másolásos módszerrel eljutott, csak a 13. nem tetszik neki. Talán babonás?
(#) kissi válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Így még mindig nem biztos, hogy a 2 timer szinkronban lenne, szerintem jobb a Te megoldásod , felesleges timert járatni!
(#) kissi válasza Attila86 hozzászólására (») Júl 21, 2015 /
 
Ez a kötőjel, ékezet azért nem tuti ( legalábbis az MPLAB előző verzióinál ), néha nem okozott gondot, néha igen ugyanannál a projektnél ( gondolom, attól is függ, hogy a windows hogy érzi magát a háttérben, azaz mi fut ! ) !
(#) Buvarruha válasza kissi hozzászólására (») Júl 21, 2015 /
 
Ismerős, de én a csillagok aktuális álásához kötöttem azt, hogy mikor jó és mikor nem.
(#) potyo válasza Attila86 hozzászólására (») Júl 21, 2015 / 1
 
Timer1 sem kell. USART-ot beállítod, hogy alacsony prioritású megszakításokat okozzan (már ami kell, ha csak küldesz, akkor persze csak TX), de nem engedélyezed a TXxIE-t. Timer2-ben növelsz egy számlálót, amikor az elért 200-ra (=10ms/50us), akkor bebillented a TXxIE-t. Ezután amint kiért a Timer2 megszakításból, azonnal belép az alacsony prioritásúba, hogy kiszolgálja az USART TX-et, mert időköben ugye a transmit buffer üres már. Az usart megszakításban pedig amikor betetted az utolsó bájtot is a bufferbe, akkor törlöd a TXxIE bitet, ezzel letiltod az usart megszakítást egészen addig, amíg a Timer2-ben ismét 200-ra nem ér a számláló. Tehát valami ilyesmi:

  1. void high_isr(void)
  2. {
  3.         static unsigned char sz=0;
  4.         if (TMR2IE && TMR2IF)
  5.         {
  6.                 TMR2IF=0;
  7.                 sz++;
  8.                 if (sz==200)
  9.                 {
  10.                         sz=0;
  11.                         hanyadik=0;
  12.                         TX1IE=1;
  13.                 }
  14.                 //adc_kezelese
  15.         }
  16. }
  17.  
  18. void low_isr(void)
  19. {
  20.         if (TX1IE && TX1IF)
  21.         {
  22.                 TXREG=puffer[hanyadik++];
  23.                 if (hanyadik==10)
  24.                 {
  25.                         TX1IE=0;
  26.                 }
  27.         }
  28. }
A hozzászólás módosítva: Júl 21, 2015
(#) kissi válasza Buvarruha hozzászólására (») Júl 21, 2015 /
 
Lehet, hogy benne van a képletben, mint "eredmény kijövési együttható" !
(#) ktamas66 válasza Attila86 hozzászólására (») Júl 22, 2015 /
 
Ha special event triggerrel indítod az AD-t attól még időmérésre is használhatod, hiszen a CCP1IF bitet beállítja így okozhat megszakítást. Ha viszont egy másik CCP-t használsz a 10ms-hoz lehet nem is kell két szintű IT hiszen az AD is küldhet megszakítást, ami lehet már nem időkritikus. Így az ISR is rövidebb lehet, nem kell timer beállításokkal és számlálókkal foglalkozni.
(#) zilahi hozzászólása Júl 22, 2015 /
 
Sziasztok!

Két kérdésem lenne:

Meg lehet azt oldani, hogy a pic-ben a processzor két, vagy annál több dolgot hajtson végre egyszerre?

Pl.: Ledet kezd el villogtatni, ha jel érkezik az egyik bemenetre (tehát figyeli a bemenetet (Pwm nélkül)) és közben egy motor fordulatszámát változtatja az analóg bemeneti jelnek megfelelően.


Hogyan lehet egy motort fordulatszámát a terheléstől függetlenül állandóan tartani?
(nem a motor feszültsége lesz állandó, hanem a motor fordulatszáma)

Előre is köszönöm a segítségeket.
(#) matheattila válasza zilahi hozzászólására (») Júl 23, 2015 /
 
Az, hogy "egyszerre" relatív, mert ránézésre valóban úgy néz ki mintha egyidőben történnének a dolgok de valójában csak egymás után (bár ez függ a perifériáktól is, mert pl a PWM mehet egyidőben a a timer-el meg ADC-vel...) de mivel a poci viszonylag nagy frekvencián pörög ezért nem látszik ez.
(#) proba válasza zilahi hozzászólására (») Júl 23, 2015 /
 
Motor fordulatszámot a tengelyre szerelt jeladóval tudod mérni (optosan vagy mint a mosógépekben van, egy második tekerccsel) , esetleg a visszaindukált feszültségből tudsz rá következtetni.
Következő: »»   1194 / 1319
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