Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   129 / 153
(#) c27 hozzászólása Júl 19, 2016 /
 
Sziasztok! Egy 18F4431 PIC-kel kapcsolatban szeretnék kérdezni. C18 fordítót használok és már van egy úgymond működő programom pár hónapja csináltam tesztelt stb... szóval elvileg rendben van.
Most szerettem volna módosítani a működésén csupán a PTPER regiszternél akartam más értéket beírni. Amennyiben a PTPER értéke 128 vagy annál nagyobb (előosztás 1:1) minden működik normálisan ha 128-nál kisebb a PTPER értéke akkor problémák merülnek fel. A program beolvassa az adc-re kötött potenciométer helyzetét ami 0-255 között mozog és hozzáad 127-et (a példa kedvéért). Ekkor 127-382 között van a PTPER értéke és ennek megfelelő PWM jelet állít elő komplementer üzemmódban és count up-down beállítással.
A hiba lényegében az, hogy az adc középhelyzetében 2,5V (és kis környezetében) a PWM leáll áthaladva ezen a sávon újra elindul. Nem igazán tudom a jelenség okát áradásul ha 127 a PTPER értéke attól még a poti 0 helyzeténél (PTPER=127) működik a PWM csak középállásban nem (azt nem tudtam ellenőrizni, hogy megfelelően működik a PWM a középállástól magasabb frekvencián). Ha azt írom be hogy PTPER=120+POT1; akkor is ugyan az a hiba, de ha 120 helyett legalább 128 szerepel minden ok.
A hozzászólás módosítva: Júl 19, 2016
(#) ktamas66 válasza c27 hozzászólására (») Júl 19, 2016 /
 
Nem értem pontosan mit szeretnél. A PTPER a frekvenciát állítja, a PDC a kitöltést. Itt nem tudjuk mennyi a PDC értéke, de hogy a PWM működjön PDC nem lehet nagyobb a PTPER-nél, tehát a PTPER értékét nem csökkentheted a PDC értéke alá.
(#) c27 válasza ktamas66 hozzászólására (») Júl 19, 2016 /
 
A maximális kitöltési tényező PDC=4*PTPER.
Sajnos elég bonyolult a dolog nehéz megfogalmazni. Még csinálok pár tesztet hogy pontosabb hibaleírást tudjak adni, majd írok.
(#) Dress hozzászólása Júl 28, 2016 /
 
Sziasztok!
Szeretnék segítséget kérni! A kis programom azt csinálja, hogy ha megnyomok egy nyomógombot (amiből kettő van, ny1;ny2; ) az egyik kimenetem 1-be megy. Ha eltelik egy bizonyos idő (K változó eléri a 7000-et) vagy a be3-as bemenetet 3-szor megnyomom, a kimenetek 0-ba mennek.
Ez így működik is, viszont ki szeretném egészíteni azzal, hogy ha bármelyik kimenetem 1-ben van és jön egy gombnyomás (ny1 vagy ny2) kapcsolja 0-ba a kimeneteket.
Biztos, hogy van ötletetek

  1. #define ny1      GPIO.GP0
  2. #define ny2      GPIO.GP1
  3. #define jobb     GPIO.GP4
  4. #define bal      GPIO.GP5
  5. #define be3      GPIO.GP2
  6.  
  7. bit gomb1; hosszu_gomb1; be3_van;  gomb2; hosszu_gomb2;
  8. unsigned int  K;  gomb1_ido; gomb2_ido;
  9. char J; be3sz;
  10.  
  11. void interrupt ()  //0,1 ms-omkent
  12. {
  13.        K++;
  14.                
  15.        if(gomb1_ido>=1000)  {hosszu_gomb1=1; gomb1=0;}
  16.  
  17.        if((gomb1_ido>=100) && (gomb1_ido<=1000)) {gomb1=1;}
  18.        
  19.        if(ny1==1) {gomb1_ido++; jobb=0; bal=0; }
  20.        
  21.        if(ny1==0) {gomb1_ido=0;gomb1=0; hosszu_gomb1=0;}
  22.        
  23.        if(gomb2_ido>=1000)  {hosszu_gomb2=1; gomb2=0;}
  24.  
  25.        if((gomb2_ido>=100) && (gomb2_ido<=1000)) {gomb2=1;}
  26.  
  27.        if(ny2==1) {gomb2_ido++; jobb=0; bal=0; }
  28.  
  29.        if(ny2==0) {gomb2_ido=0;gomb2=0; hosszu_gomb2=0;}
  30.  
  31.      
  32.        INTCON.T0IF = 0;                  //Clear timer interrupt
  33.  }
  34.  
  35.  
  36. void main()
  37. {
  38.  
  39.  
  40.          gomb1=0;
  41.          hosszu_gomb1=0;
  42.          gomb1_ido=0;
  43.          
  44.          gomb2=0;
  45.          hosszu_gomb2=0;
  46.          gomb2_ido=0;
  47.          
  48.          J=0;
  49.          be3_van=0;
  50.          be3sz=0;
  51.          K=0;
  52.          
  53.          
  54.           while (1)
  55.           {
  56.           //be3
  57.           if (be3==1) {be3sz++; be3_van=0;}
  58.           if (be3sz>=100) {be3_van=1;}
  59.           if ((be3==0) && (be3_van==1)) {J++;be3_van=0;be3sz=0;}
  60.          
  61.  
  62.           if ((ny1==0) && (gomb1==1) && (hosszu_gomb1==0)) {jobb=1;K=0;}
  63.           if ((ny1==0) && (gomb1==0) && (hosszu_gomb1==1)) {K=0;}
  64.  
  65.          
  66.           if ((ny2==0) && (gomb2==1) && (hosszu_gomb2==0)) {bal=1;K=0;}
  67.           if ((ny2==0) && (gomb2==0) && (hosszu_gomb2==1)) {K=0;}
  68.          
  69.  
  70.           if ((J==3) || (K==7000)) {jobb=0;bal=0;J=0;K=0;}
  71.           }
  72.  
  73. }
A hozzászólás módosítva: Júl 28, 2016
(#) c27 válasza ktamas66 hozzászólására (») Júl 30, 2016 /
 
Időközben rájöttem a különböző változók típusaival voltak problémák.
(#) usane válasza Dress hozzászólására (») Aug 1, 2016 /
 
Hello!

1. A kimenet az gondolom a jobb meg a bal.
2. Nem egészen értem a főciklusban miért kell vizsgálni a nyomógomb állapotát is meg a hozzá tartozó változókat is.
3. 2 Gombot írtál, mi a be3?

Mindezeken túl mi a kérdés lényege? Nem kell vizsgálni, magas e valamelyik kimenet gombnyomáskor, egyszerűen csak nullázood mind a két kimenetet bármelyik gomb megnyomásakor, mielőtt a megfelelő kimenetet magasba állítanád.
(#) Dress válasza usane hozzászólására (») Aug 1, 2016 /
 
1. Igen, a kimenet a jobb meg a bal
2. a főciklusban megy a kimenet magasba, ha elengedtem a nyomógombot és a nyomás ideje rövid volt
3. a be3 egy bemenet, ami ha 3-szor magasba került , a kimenetek 0-ba menek
(próbálom érthetően... remélem sikerül)
Azt szeretném, hogy ha valamelyik kimenet magas és e-közben jön bármelyik gombnyomás, akkor a kimenetek 0-ba menjenek.
(#) usane válasza Dress hozzászólására (») Aug 2, 2016 /
 
Igazából még mindíg nem értem a problémád, mert ennek most is így kéne működnie, ha valamit be nem néztem.

Idézet:
„if(ny1==1) {gomb1_ido++; jobb=0; bal=0; }
if(ny2==1) {gomb2_ido++; jobb=0; bal=0; }”


Vagy akkor mit is szeretnél elérni?
(#) Dress válasza usane hozzászólására (») Aug 2, 2016 /
 
Igen. Ezeket a sorokat szépen végre is hajtja, viszont, ha a gombnyomás megfelelően rövid, felhúzza a hozzá tartozó kimenetet 1-be. Azt szeretném, hogy ha magasban van valamelyik kimenet és gombot nyomok akkor menjen minden 0-ba.
(#) c27 hozzászólása Aug 3, 2016 /
 
Sziasztok!

Egy 4 bites változó számjegyeit szeretném tükrözni pl. 1011 helyett 1101-et szeretnék, magyarul a 4. számjegyből legyen az 1. a 3.->2., 2.->3. ...
Hogy lehet a legegyszerűbben megtenni?
(#) killbill válasza c27 hozzászólására (») Aug 3, 2016 /
 
Idézet:
„Egy 4 bites változó számjegyeit szeretném tükrözni pl.”

Shift-eléssel vagy táblázattal. Ez bonyolultnak tunik, de ez osszesen hat shift-elest tartalmaz:
  1. x = ((x & 3) << 2) | ((x & 0x0c) >> 2);
  2. x = ((x & 5) << 1) | ((x & 0x0a) >> 1);

Ez egyszerubbnek nez ki, de ebben 8 shifteles van:
  1. x = ((x & 1) << 3) | ((x & 2) << 1) | ((x & 4) >> 1) | ((x & 8) >> 3);

A tablazatos megoldas pedig:
  1. static char revtab[] = {0, 8, 4, 12, 2, 10, .. stb};
  2.  
  3. x = revtab[x];
(#) c27 válasza killbill hozzászólására (») Aug 3, 2016 /
 
Köszi.
Egyébként melyik a gyorsabb a táblázat vagy a 6 shift?
A hozzászólás módosítva: Aug 3, 2016
(#) Hp41C válasza c27 hozzászólására (») Aug 3, 2016 /
 
Ebben csak 4 darab btfsc, 4 darab bsf, két movlw, két andwf és egy swapf van:
  1. x &= 0x0f;
  2. if (x & 0x8) x|=0x10
  3. if (x & 0x4) x|=0x20
  4. if (x & 0x2) x|=0x40
  5. if (x & 0x1) x|=0x80
  6. x >>= 4;

CSak 13 utasítás..
(#) c27 válasza killbill hozzászólására (») Aug 3, 2016 /
 
Egy kicsit pontosítok 8 bites a változóm, de csak az alsó 4 bitjét használom.
Hp41C programjának működését nem igazán értem.
A hozzászólás módosítva: Aug 3, 2016
(#) Hp41C válasza c27 hozzászólására (») Aug 3, 2016 /
 
  1. x &= 0x0f;              // Felső 4 bit törlése
  2. if (x & 0x8) x|=0x10;// A felső 4 biten az alsó 4 bit fordítottjának előállítása
  3. if (x & 0x4) x|=0x20;
  4. if (x & 0x2) x|=0x40;
  5. if (x & 0x1) x|=0x80;
  6. x >>= 4;                // Felső 4 bit léptetése az alsó 4 bitre, a felső 4 bit törlése
(#) c27 válasza Hp41C hozzászólására (») Aug 3, 2016 /
 
Aha kösz, végig kellett játszani papíron.
Egyébként a 6 shiftes nem gyorsabb?
A hozzászólás módosítva: Aug 3, 2016
(#) usane válasza Dress hozzászólására (») Aug 3, 2016 /
 
Csak hogy biztoan értsük egymást: Most ha megnyomod a gomb egyet röviden akkor a jobb kimenet lesz magas, ha a gomb2-t akkor a bal. Azt akarod, hogy bármelyik gomb megnyomása törölje ezeket. Eddig rendben van, egyszerű csak ki kell venni a következő sorokból
if ((ny1==0) && (gomb1==1) && (hosszu_gomb1==0)) {jobb=1;K=0;}
if ((ny2==0) && (gomb2==1) && (hosszu_gomb2==0)) {bal=1;K=0;},
amit kivastagítottam.
Értelem szerűen amelyikből kiveszed az a gomb fogja mindkétkimenetet törölni, ha mindkettőt kiveszed akkor mindkettő gomb ezt csinálja, de ha a gombok törölni fognak akkor mi fogja magasba állítani a kimeneteket?
(#) Hp41C válasza c27 hozzászólására (») Aug 3, 2016 /
 
Talán nem. Miután minden léptetés után a belépő bitet törölni kell, így minden rlc, rrc utasítás után egy andlw vagy bcf utasítás is fordul.
(#) c27 válasza Hp41C hozzászólására (») Aug 3, 2016 /
 
Értem és a táblázatos módszer?
(#) Hp41C válasza c27 hozzászólására (») Aug 3, 2016 /
 
PIC16F : Megszakítás kiszolgálóban PCLATH mentése, visszaállítása + PCLATH feltöltése, rutinhívás, PCL módosítása + 16 retlw = kb 25 utasítás, egy verem és egy változó
PIC16F1 : rutinhívás, brw + 16 retlw = kb 19 utasítás, egy verem avagy FSRxH feltöltése, FSRxL feltöltése + indirekt olvasás = kb. 6 utasítás + 16 konstans
PIC18F: rutinhívás PCLATU, PCLATH feltöltése (movf PCL,w) PCL módosítása (2*x -el) + 16 retlw = kb. 20 utasítás, avagy TBLPTRU, TBLPTRH feltöltésre, PBLPTRL feltöltése, TBLRD, TABLAT kiolavasása + 16 konstans (ami csak 8 utasítás) = kb. 16 utasítás

Assembly:
Ha WREG címezhető:
  1. andlw 0x0F
  2. btfsc WREG,3
  3. iorlw 0x10
  4. btfsc WREG,2
  5. iorlw 0x20
  6. btfsc WREG,1
  7. iorlw 0x40
  8. btfsc WREG,0
  9. iorlw 0x80
  10. swapf WREG,W
  11. andlw 0x0F

11 utasítás
(#) killbill válasza c27 hozzászólására (») Aug 3, 2016 /
 
Egy 'rendes' processzoron valoszinuleg a tablazat, de 8 bites PIC-ek eseteben barmi is lehet.
(#) c27 válasza Hp41C hozzászólására (») Aug 3, 2016 /
 
Ok, kösz a részletes választ.
(#) c27 válasza Hp41C hozzászólására (») Aug 3, 2016 /
 
Még egy kérdés. Hogyan tudom a leggyorsabban vizsgálni, hogy egy szám negatív e?
Asm-ben könnyű, mert a legmagasabb bit 1-es negatív esetén, ha if(x<0){...} ez a legmagasabb bit vizsgálatát jelenti C-ben vagy valami bonyolultabbnak fordítja?
A hozzászólás módosítva: Aug 3, 2016
(#) Hp41C válasza c27 hozzászólására (») Aug 4, 2016 /
 
C18 a PIC18F2550 -re ezt fordítja:
  1. char empty0B;
  2. 553:               empty0B = -2;
  3.   205E    0102     MOVLB 0x2
  4.   2060    0EFE     MOVLW 0xfe
  5.   2062    6FFF     MOVWF 0xff, BANKED
  6. 554:              
  7. 555:               if (empty0B < 0) empty0B = -empty0B;
  8.   2064    34E8     RLCF 0xfe8, W, ACCESS
  9.   2066    E301     BNC 0x206a
  10.   2068    6DFF     NEGF 0xff, BANKED
(#) usane hozzászólása Aug 5, 2016 /
 
Üdv!

Tudja valaki XC32-ben hogy lehet hozzáférni a cp0_status IE bitjéhez? Vagy hogy másképp mondjam a megszakításokat hogyan lehet tiltani és engedélyezni? De megint én vagyok a lüke, hogy XC-t használok.
(#) cross51 válasza usane hozzászólására (») Aug 6, 2016 /
 
Én az asm("di) és asm("ei") szoktam használni.
De ott van a__builtin_disable/enable_interrupts a disable egy integer-rel tér vissza arra már nem emlékszem mit jelöl, de a plib-es is van az INTDisableInterrupts, INTRestoreInterrupts (és lehet van, de ebbe nem vagyok biztos) INTEnableInterrupts és a plib XC32 1.40-óta (asszem) nincsen.
(#) usane válasza cross51 hozzászólására (») Aug 6, 2016 /
 
Legújabb XC32 van fenn, mert MM szériához kell, és valóban nincs plib, illetve valahol benne van a legacy könyvtárban, de nem ismeri fel az INTDis... és enable utasításokat, ezeket próbáltam én is.
Kipróbálom a másik kettőt, köszönöm.
A hozzászólás módosítva: Aug 6, 2016
(#) kormika hozzászólása Aug 7, 2016 /
 
Sziasztok! Egy egyedi RC modell építéséhez szükségem van egy igencsak egyedi szabályzóra, sehol nem találtam ilyet készen, szóval marad a megépítés. A lelke elgondolásom szerint egy PIC 16F884 lenne, mivel a szabályzónak többek között 2 motort kell függetlenül vezérelnie ezért szükség van a 2db egymástól független PWM jelre, amire (ha jól fejtettem meg az adatlapot) ez a PIC képes. A kérdésem arra irányulna leginkább, hogy a vevőből érkező PWM jelekből hogyan tudok pl. 8 bites változókat kreálni, amikből utánna majd kikalkulálom, hogy melyik motornak mekkora PWM kell. CCS fordítót használok, a példák között van egy impulzusszélesség méréses példa, de nem akart működni többszöri kísérletezés után sem. A szóban forgó modell egy hernyótalpas szovjet tüzérségi vontató, a két hernyótalpat külön motor hajtja, és a menetiránynak megfelelően a különböző lámpákat is vezérelni kell, és egy szintén PIC-es dizelmotor hanggenerátort is vezérelni kell a szabályzónak. Találtam ugyan tankokba való gyári szabályzót, de pl. egyik sem olyan, hogy ún. pisztoly távirányítóval lehessen vezérelni. Nekem olyan szabályzóra van szükségem, ami 2 csatorna jeléből dönti el, hogy mi a szitu, az egyik csatorna az előre-hátramenet, a másik pedig a kormányzás. Ha a kormány középen van, akkor mindkét motort ugyanúgy kell vezérelnie a gázkar hatására, ha pedig elfordítom valamelyik irányba a kormányt, akkor az adott oldalhoz tartozó motort kell arányosan lassítania. Erre még találtam egy gyári szabályzót ebay-en "potom" 200 dollárért, de az egyik legfontosabb funkiót az sem tudja mégpedig azt, hogyha nem adok gázt, de elfordítom a kormánykereket valamelyik irányba, akkor az iránynak megfelelően az egyik motort előrefelé kell elindítania, a másikat pedig hátrafelé. Erről még éppenséggel lemondanék, de a gond ezzel a szabályzóval az, hogy eléggé kicsi méretarányú modellről van szó, és fizikailag nem fér el benne, ezért is vagyok rákényszerülve a saját szabályzó építésére.
(#) c27 válasza Hp41C hozzászólására (») Aug 7, 2016 /
 
Ismét kellene egy kis segítség.

Van egy 360 elemű tömböm 16 bites számokkal (0-2048 között) szinusz értékek. Az amplitúdót szeretném változtatni egy poti segítségével mondjuk 8 biten. Szóval arra gondoltam, hogy fogom a tömböm elemeit megszorzom a poti értékével majd elosztom 255-tel.
A probléma az hogy mindez megszakítás alatt történik elég sok dologgal együtt és persze rövid az idő. Hogy lehetne ezt a lehető leggyorsabban megoldni?
Próbáltam olyat is, hogy a tömböm elemeit eleve 4-el osztva pakolom be és akkor már csak 6-tal kell shiftelni (256-os osztással is megelégszek). Ez is lassúnak bizonyult, mivel a PWM regiszterekbe is bele kell írni plusz külön kell választani low és high bájtra szóval körülményes.
Valami ötlet, egy trükkös megoldás?
A hozzászólás módosítva: Aug 7, 2016
(#) cross51 válasza kormika hozzászólására (») Aug 7, 2016 /
 
Még gyakorlati szinten sose foglalkoztam impulzus szélesség méréssel, de hátha esetleg segít az alap elv.
Van a CCP abból a Capture mód-al szokták ezt csinálni, azt hogy pontosan, hogyan abba mást szerintem nagyobb segítséget tud nyújtani. Ezzel az előbbivel az egy probléma, hogy az adott PIC-ben csak CCP modul van és ebből neked mind a kettő kell PWM-re, egy másik működű lehetőség csinálsz megszakítást a lábra mikor a pwm jel elkezdett felfutni elindítasz egy timer-t mikor lefut megállítod és a timer értékből látod milyen hosszú a bejövő impulzus.
Következő: »»   129 / 153
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