Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   67 / 153
(#) nagzso hozzászólása Dec 27, 2012 /
 
Sziasztok!
Miért van az, hogy az XC8 v1.12 compiler-t használva, nem tudom átadni az egyik tömb elemeit a másiknak?
pl.: (most, hogy a "\0" karakter hozzá van adva a tömbhöz, vagy nincs nem számít, mert növeltem a tömb elemet meg csökkentettem is, és semmi; kínomba már kísérleteztem mindennel)
  1. char a[10];
  2. char b[8];
  3. char c[2];
  4.  
  5. for (int i = 0, j = 0; i < 10; i++) {
  6.     if (i < 8) {
  7.         b[i] = a[i];
  8.     } else if (i >= 8) {
  9.         c[j] = a[i];
  10.         j++;
  11.     }
  12. }

Olyan, mintha a tömböket keverné össze-vissza. Volt már máskor is gondom a tömbökkel benne, amikor egymás alatt többet deklaráltam és használtam őket egymás után.
(#) _vl_ válasza nagzso hozzászólására (») Dec 27, 2012 /
 
Idézet:
„Miért van az, hogy az XC8 v1.12 compiler-t használva, nem tudom átadni az egyik tömb elemeit a másiknak?”

Mi akadályoz meg benne?
Szerintem a leírt kóddal pontosan azt fogja csinálni a számítógép, mint amire megkérted.
"A számítógép nem az óhajainkat vagy a kívánságainkat teljesíti, hanem a parancsainkat".
(#) nagzso válasza _vl_ hozzászólására (») Dec 27, 2012 /
 
Szóval azt mondod a kód helyes? De akkor mégse írja ki amit kéne.
(#) _vl_ válasza nagzso hozzászólására (») Dec 27, 2012 /
 
Talán mást gondolsz annak, hogy "mit kéne", mint amit a számítógép...
(#) nagzso válasza _vl_ hozzászólására (») Dec 27, 2012 /
 
És megy.... Hihetetlen, és nem tudom, most miért jó, pedig már nem egyszer megírtam így is. Bár folyamatosan ment az MPLAB már vagy 8-9 órája, lehet azért kavart be. Hát már papíron is levezettem magamnak az "algoritmust", mondom, próbálkoztam mindennel. A fenti példából meg, mint mondtam eggyel kevesebb eleműek a tömbök, mint kéne lenniük, meg persze az a[11] fel van töltve 10 elemmel.
A hozzászólás módosítva: Dec 27, 2012
(#) Ideiglenes válasza nagzso hozzászólására (») Dec 27, 2012 /
 
Nekem furcsának tűnik az i és j változók létrehozása vagy kezelése. Az az int szócska teljesen nem odaillő, bár lehet, hogy az xc8 megemészti, de az akkor sem való oda. A tömbök után kellene deklarálni az i és j változókat, a for() sorából pedig törölni az int szócskát.
(#) icserny válasza Saggitarius hozzászólására (») Dec 27, 2012 /
 
Idézet:
„Tudom-e hasznalni a HiTech forditojat, akar korlatozasokkal?”
Az egyik "korlátozás" az, hogy csak PIC18-ig elérhető... Bővebben: Link

PIC32-höz az új XC32 vagy XC++32 választható, esetleg a régi MPLAB C32.
- Compilers
- Legacy compilers
(#) icserny válasza Ideiglenes hozzászólására (») Dec 27, 2012 /
 
Idézet:
„Nekem furcsának tűnik az i és j változók létrehozása vagy kezelése.”
Az úgynevezett "C99" szabvány (az ANSI 2000 májusában fogadta el) szerint a deklaráció immár lehet a for ciklusban is a C++-hoz hasonlóan).

A kérdés csak az, hogy az adott fordító támogatja-e, illetve milyen fordítási opciót kell megadni hozzá.
(#) nagzso válasza icserny hozzászólására (») Dec 27, 2012 /
 
Igen, C++ -ban engedélyezett, és az XC8 is támogatja és az alap fordítási beállításokkal megy. Programozást tanulok, ezért furcsálltam, hogy egy ilyen tömb átadást nem tudok megalkotni... De miután újra indítottam az MPLAB-ot, fordult rendesen.
(#) Stefan válasza nagzso hozzászólására (») Dec 27, 2012 / 1
 
Érdemes figyenli a build ablakot, hogy mit is fordít újra, mikor a build gombra nyomsz, valószínű az MPLAB rosszul indította a compilert. Ezért szoktam kisebb projekteknél mindig először cleanelni, aztán az egészet újra.

Amúgy ha egy tippet elfogadsz, ezt a "(....){ " zárójel tördelést felejtsd el, nagyon profinak tűnik, de gyakorlatilag csak olvashatatlanná teszi a kódot.
A hozzászólás módosítva: Dec 27, 2012
(#) Marko Ramiusz válasza ZsoltyFM hozzászólására (») Dec 28, 2012 /
 
Szia, ZsoltyFM! Hozzá lehet jutni ehhez a videótanfolyamhoz? Másfél éve vettem egy Mikroe EasyPIC6-ost, akkoriban irtó lelkes voltam, de a kudarcok visszavetettek, még addig sem jutottam el, hogy az általános beállításokban meg tudjam szüntetni a hibát, nemhogy egy LED-et működtetni (bár ez inkább kezdő kérdésekhez tartozna). Véletlenül beleolvastam a fórumba és újra belelkesültem. Szeretném megtanulni a "C"-t PC-n, aztán tényleg jöhet a PIC. Szóval tudnál segíteni a videók beszerzésében, vagy bármilyen segedletben? Üdvözlettel: Yoe
(#) icserny válasza Marko Ramiusz hozzászólására (») Dec 28, 2012 /
 
Idézet:
„vettem egy Mikroe EasyPIC6-ost, akkoriban irtó lelkes voltam, de a kudarcok visszavetettek”

Ez a könyv sem segített?
(#) Marko Ramiusz válasza icserny hozzászólására (») Dec 28, 2012 /
 
Szia! Természetesen letöltöttem és át is néztem, de - mint írtam - a programozásig el sem jutottam. Mindent úgy írtam be, mint ahogy a példaprogramokban van, mégsem tudtam semmit sem csinálni.
A hozzászólás módosítva: Dec 28, 2012
(#) nagzso hozzászólása Dec 29, 2012 /
 
Sziasztok!
Kezdek rájönni, hogy az XC8 semmire se való, vagy én nem tudok programozni.
  1. int maxRPM = 800;
  2. int minRPM = 200;
  3. int asd = minRPM * 1023 / maxRPM;

Ez se működik.
  1. load_dutyCycle(asd);

És ez se működik...
  1. load_dutyCycle(minRPM * 1023 / maxRPM);

Így viszont igen...
  1. load_dutyCycle(255);

Ez lenne a függvény, amit meghív.
  1. void load_dutyCycle(int szam){...}

A probléma, hogy rossz számot ad át a változókból. Tudom, hogy csak "int" típusú a változó, de a tizedesnél levág, így az "asd"-ba maradna simán egy egész szám, amit át tud adni. Mi lehet a gond?
(#) benjami válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Próbáld meg így:
  1. int asd = minRPM * 1023UL / maxRPM;

(#) _vl_ válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Idézet:
„Tudom, hogy csak "int" típusú a változó,”

Int típusú, tehát 16-bites.
Mivel 200 * 1023 > 65535, ezért már az első szorzásnál túl fog csordulni, és onnantól kezdve semmi köze nem lesz az eredménynek a valósághoz.

Jó dolog ez a "programozzunk 8-bites mikrokontrollereket C-ben", de alapvetően úgy működik a dolog, ha precízen végiggondoljuk, hogy milyen műveletet (és hány biten) szeretnénk végrehajtatni, majd utána olyan parancsokat írunk le, ami pont azt csináltatja meg.
Jelen esetben lehet azt kérni, hogy 4-byte-os egész számként (unsigned long) számoljon a fordító (minRPM * 1023UL), vagy el lehet azon gondolkodni, hogy a műveleteket hogyan lehetne optimalizálni, hogy beleférjünk a 16 bitbe.
Mondjuk ha pl. a maxRPM értéke fix, akkor lehet játszani olyat, hogy minRPM + ((minRPM + ((minRPM >> 1) - (minRPM / 25)) >> 2) >> 2), ez egy 8-bites mikrokontrolleren gyorsabb lesz, mint az unsigned long-os számolgatás.
(#) benjami válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Ha valamelyik RPM értéke fix, akkor azt célszerűbb inkább #define-vel megadni, és akkor a számítást nem a mikrovezérlő, hanem a fordító fogja elvégezni. Annak meg mindegy hogy 16, 32 vagy akár 64 biten csinálja. Ha ez az RPM valami fordulatszámot jelent, akkor inkább unsigned int legyen a típusa (a negatív fordulatszám amúgy is elég nehezen értelmezhető, legfeljebb ha ha forgásirány is számít), úgy később fog a túlcsordulások miatt fals eredmény keletkezni.
(#) whalaky hozzászólása Dec 30, 2012 /
 
Sziasztok!
Olyan gondom van és nem találok rá megoldást, hogy LAT PORT és TRIS biteket szeretném változóként kezelni. Vagyis valami ilyesmi kéne, de sehogy nem működik
  1. BIT xTRIS;
  2. BIT xLAT;
  3. BIT xPORT;
  4. ...
  5. switch (x) {
  6. case 0:
  7.     xTRIS = _TRISA9;
  8.     xLAT  = _LATA9;
  9.     xPORT = _RA9;
  10.     break;
  11. case 1:
  12.     xTRIS = _TRISA10;
  13.     xLAT  = _LATA10;
  14.     xPORT = _RA10;
  15.     break;
  16. ..... }
  17.  
  18. y = xPORT;
  19. xTRIS = 0;
  20. xLAT = 1;

Tulajdonképpen futásidőben dől el, hoyg épp melyik I/O lábat kell piszkálni. Remélem érthető hogy mit is szeretnék.... CCS-ben ez gond nélkül ment, de a C30-al nem boldogulok. Tudtok erre valami megoldást?
(#) nagzso válasza benjami hozzászólására (») Dec 30, 2012 /
 
Az RPM, igen fordulatszám lenne. Azt a hibát orvosoltam, "long" lett az "int"-ből. Sajnos az RPM értéke majd attól kell függjön, hogy menüből mekkora értéket adnak neki, amit az EEPROM-ban tárol majd. Itt a "dolgozó" program rész és hozzá a változók:
  1. const int temp_minRef = 695;
  2.     const int temp_maxRef = 518;
  3.     const int temp_perCent = temp_minRef - temp_maxRef;
  4.     int temp;
  5.     unsigned int maxTemp = 100; //eeprom-ba megy majd
  6.     unsigned int minTemp = 0; //eeprom-ba megy majd
  7.     unsigned int temp_dif = 2; //eeprom-ba megy majd, és értéke 0 lesz
  8.     unsigned int set_temp = minTemp + temp_dif;
  9.     unsigned long comp_temp = 0;
  10.     char t[] = "";
  11.     unsigned int cnt = 0;
  12.     unsigned int run = 0;
  13.  
  14.     unsigned int maxRPM = 800; //eeprom-ba megy majd
  15.     unsigned int minRPM = 200; //eeprom-ba megy majd
  16.     unsigned int halfRPM = (maxRPM + minRPM) / 2;
  17.     unsigned int slope = (maxRPM - halfRPM) / temp_dif;
  18.     unsigned int rpm_perCent = (maxRPM - minRPM) / 100;
  19.  
  20.     unsigned long low_dutyCycle = minRPM * 1023 / maxRPM;
  21.     const unsigned int high_dutyCycle = 1023;
  22.     unsigned long dutyCycle = 0;
  23.     unsigned int mid_dutyCycle = low_dutyCycle + (high_dutyCycle - low_dutyCycle / 2);
  24.  
  25.     //lcd_main(t,r);
  26.  
  27.     while(1) {
  28.         if (cnt >= 10) {
  29.             run = 0;
  30.         }
  31.  
  32.         comp_temp = (1000 * (temp_minRef - readADC())) / temp_perCent;
  33.         temp = comp_temp / 10;
  34.  
  35.         if (comp_temp <= ((set_temp - temp_dif) * 10)) {
  36.             load_dutyCycle(high_dutyCycle);
  37.         }
  38.  
  39.         if (comp_temp >= ((set_temp + temp_dif) * 10)) {
  40.             load_dutyCycle(low_dutyCycle);
  41.         }
  42.  
  43.         if (comp_temp == (set_temp * 10)) {
  44.             load_dutyCycle(mid_dutyCycle);
  45.         }
  46.  
  47.       /*/  if (comp_temp > ((set_temp - temp_dif) * 10)) {
  48.             if (comp_temp < (set_temp * 10)) {
  49.                 dutyCycle = comp_temp - (set_temp - temp_dif);
  50.                 dutyCycle = dutyCycle * (high_dutyCycle - low_dutyCycle);
  51.                 dutyCycle = dutyCycle * (slope / (rpm_perCent * 10));
  52.                 dutyCycle = high_dutyCycle - (dutyCycle / 100);
  53.                 load_dutyCycle(dutyCycle);
  54.             }
  55.         }
  56.  
  57.         if (comp_temp < ((set_temp + temp_dif) * 10)) {
  58.             if (comp_temp > (set_temp * 10)) {
  59.                 dutyCycle = comp_temp - (set_temp - temp_dif);
  60.                 dutyCycle = dutyCycle * ((high_dutyCycle - low_dutyCycle) / 100);
  61.                 dutyCycle = dutyCycle * (slope / (rpm_perCent * 10));
  62.                 dutyCycle = high_dutyCycle - dutyCycle;
  63.                 load_dutyCycle(dutyCycle);
  64.             }
  65.         }*/
  66.  
  67.         if (!PORTBbits.RB0 && (set_temp < maxTemp)) {
  68.             cnt = 0;
  69.             set_temp++;
  70.             run = 1;
  71.         }
  72.  
  73.         if (!PORTAbits.RA5 && set_temp > minTemp + temp_dif) {
  74.             cnt = 0;
  75.             set_temp--;
  76.             run = 1;
  77.         }
  78.  
  79.         switch (run) {
  80.             case 1:
  81.                 itoa(t, set_temp, 10);
  82.                 lcd_write_temp(t);
  83.                 Delay10KTCYx(100);
  84.                 lcd_write_temp(" ");
  85.                 cnt++;
  86.                 break;
  87.             default:
  88.                 itoa(t, temp, 10);
  89.                 lcd_write_temp(t);
  90.                 cnt = 0;
  91.                 break;
  92.         }
  93.         Delay10KTCYx(100);
  94.     }

A függvények, amiket meghív útközbe, azok tuti jók, így nem is másoltam be. Ahol ellentmondás lenne a változó neve és az elvárt értéke (pl.: temp_perCent megadásnál) között, az a tizedes jegyek kiküszöbölése miatt van.
Amit a program csinálna:
1. Beállított hőmérséklet - temp_dif alatt van a mért hőmérséklet, akkor max. RPM
2. Beállított hőmérséklet + temp_dif felett van a mért hőmérséklet, akkor min. RPM
3. Beállított hőmérséklet - temp_dif felett van a mért hőmérséklet, de a beállított alatt, akkor min. RPM
4. Beállított hőmérséklet + temp_dif alatt van a mért hőmérséklet, de a beállított felett, akkor min. RPM
5. Ha meg nyomom a gombokat, egyik csökkenti a hőmérsékletet, másik növeli, és beállítás közben az LCD-n mutatja a folyamatos változást villogás közben, majd 10 "kör"
után visszaáll a hőmérséklet mutatására.
Ha a kikommentezett részt berakom, teljesen más értékek jelennek meg, és még a set_temp is ugrált össze-vissza, amikor nem is adok neki értéket sehol, kivéve a gombnyomásokat.
Az RPM-es rész előtt minden ment szépen, úgy csinálta, ahogy kell, a jelenlegi hőmérsékletet viszont, mindig normálisa jeleníti meg.
Bocs a hosszú kommentért és a kódért, remélem valaki tud segíteni, hogy miért is nem megy rendesen, és hogy miért kapok más értéket ugyanarra a bemenetre a PWM kimeneten, ha a kommentes rész belekerül.
A hozzászólás módosítva: Dec 30, 2012
(#) _vl_ válasza whalaky hozzászólására (») Dec 30, 2012 /
 
Idézet:
„Tulajdonképpen futásidőben dől el, hoyg épp melyik I/O lábat kell piszkálni.”

Több megoldás létezik:
- shiftelgetős: LATA |= (1 << n), LATA &= ~(1 << n)
- elágazós: switch (n) { case ...
- függvénypointeres: mindegyik művelethez kell írni n db függvényt, és egy függvénypointerbe berakni a kívánt bitet változtató függvény címét

A shiftelgetős/elágazós esetben is külön függvénybe érdemes rakni, ha sokszor akarod meghívni, mert elég nagy lehet a generált kód mérete.

Egyik lassabb lesz, mint a másik.
A hozzászólás módosítva: Dec 30, 2012
(#) _vl_ válasza nagzso hozzászólására (») Dec 30, 2012 /
 
  1. unsigned int maxRPM = 800; //eeprom-ba megy majd
  2. unsigned int minRPM = 200; //eeprom-ba megy majd
  3. unsigned long low_dutyCycle = minRPM * 1023 / maxRPM;

Ez még mindig nem azt fogja csinálni, mint amit szeretnél.
Mivel a minRPM, az 1023, és a maxRPM is unsigned int, ezért rajtuk unsigned int-ként végzi el a számítást a rendszer, majd az eredményt kiterjeszti unsigned long-ra.
(#) nagzso válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Eh...elírtam. 3. és 4. pontnál nem minRPM, hanem arányosan csökkenő, azaz a max. RPM-ból a kívánt hőfokig 50%RPM, ha a kívántat túl lépi akkor ugyanúgy, arányosan csökken tovább a min. RPM-ig
(#) nagzso válasza _vl_ hozzászólására (») Dec 30, 2012 /
 
A maxRPM-t és a minRPM-t is átírtam long-ra, úgy se volt jó. (mindent átírtam longra, mert hely van, de láttam, hogy nincs változás így visszaírtam) Mondjuk nem írtam az 1023 mögé hogy L, lehet ez a gond akkor, ahogy írod? De nem lehet, mert mint mondtam a hőmérsékletnél az 1000-es szorzó meg jó és ott sincs L mögötte.
A hozzászólás módosítva: Dec 30, 2012
(#) _vl_ válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Arra már nem kéne szükség legyen. Elég a minRPM-et longra átírni (bár én inkább az 1023-at írnám át).

A programban amúgy van egy halom átgondolatlanság:
Ez pl.: "(high_dutyCycle - low_dutyCycle / 2)" nem azt csinálja, amit szeretnél. A /2 itt csak a második tagot fogja elosztani kettővel, pedig szerintem nem ez volt a gondolatod.
Vagy ott van a "(1000 * (temp_minRef - readADC())) / temp_perCent" - mi fog történni, ha az ADC a min referenciaértéknél nagyobb számot ad vissza?
Arról nem beszélve, hogy az 1000-rel történő szorzásnál ugyanez az int/long probléma fennállhat, hiszen a min és a max referenciaérték között ~180 a különbség, ezt 1000-rel felszorozva simán nem fér el 16-biten az eredmény.
(#) nagzso válasza _vl_ hozzászólására (») Dec 30, 2012 /
 
(high_dutyCycle - low_dutyCycle / 2) igazad van, köszi. Ez már a próbálkozások közbe ment el. Ha a minRef értéknél nagyobbat kap, akkor majd error-ral ki áll (azt jelentené hogy 100fok felett van a víz, ami már nagyon nem jó).
Szorzok-osztok, kipróbálom amit mondtál, az int és long közti dolgot.
(#) _vl_ válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Idézet:
„akkor majd error-ral ki áll”

Nade honnan fogja észrevenni? Mert a kivonás negatív eredményt ad, amit utána beraksz egy unsigned int változóba - na innentől kezdve már senki nem fogja tudni, hogy mi történt, lévén a negatív érték "átváltozik" valami pozitív számmá.
Szerencsésebb lenne az olvasott értéket olvasás után validálni, és ha nem stimmel, akkor valami más ágra terelni a feldolgozást.
Idézet:
„(azt jelentené hogy 100fok felett van a víz, ami már nagyon nem jó)”

Vagy hibás a referencia, amihez méred. Ez azért nem annyira lehetetlen esemény...
(#) nagzso válasza _vl_ hozzászólására (») Dec 30, 2012 /
 
A referenciát én állítom be, ki lett mérve 100fokon és 0fokon is. Majd ha végre működik az rpm-es dolog, meg amit még csinálni szeretnék, azután az ADC() egy változóba olvasom és levizsgálom, hogy az értékek közt van-e, ha igen akkor megy a mostani helyére a változóba az érték.
A hőmérő szenzorom 5db 1N4148-as összeforrasztva, másik topicba írták, hogy nem jó, meg nem pontos, és vegyek helyette ilyet meg olyat. De nagyon jól működik, és 5db dióda meg egy ellenállás kellett csak hozzá, amikből van egy rakás otthon. Én max. 0.5 fok eltérést tapasztaltam, ami bőven tökéletes
(#) nagzso válasza nagzso hozzászólására (») Dec 30, 2012 /
 
A probléma még mindig ugyanaz. Ha ezt a két "if"-et berakom elmászik minden, ha nincs bent akkor pedig jó, és 1.22V-ot és 4.88V-ot kapok a PWM kimeneten(200RPM = 0% = 1.22V, 800RPM = 100% = 4.88V).
  1. if (comp_temp > ((set_temp - temp_dif) * 10)) {
  2.             if (comp_temp < (set_temp * 10)) {
  3.                 dutyCycle = comp_temp - (set_temp - temp_dif);
  4.                 dutyCycle = dutyCycle * ((high_dutyCycle - low_dutyCycle) / 100);
  5.                 dutyCycle = dutyCycle * (slope / (rpm_perCent * 10));
  6.                 dutyCycle = high_dutyCycle - dutyCycle;
  7.                 load_dutyCycle(dutyCycle);
  8.             }
  9.         }
  10.  
  11.         if (comp_temp < ((set_temp + temp_dif) * 10)) {
  12.             if (comp_temp > (set_temp * 10)) {
  13.                 dutyCycle = comp_temp - (set_temp - temp_dif);
  14.                 dutyCycle = dutyCycle * ((high_dutyCycle - low_dutyCycle) / 100);
  15.                 dutyCycle = dutyCycle * (slope / (rpm_perCent * 10));
  16.                 dutyCycle = high_dutyCycle - dutyCycle;
  17.                 load_dutyCycle(dutyCycle);
  18.             }
  19.         }

Az előbb végig számoltam papíron, nincs hol túlcsordulnia, max. ha a tizedeseket nem levágja, hanem valami mást kezd velük. Szerintem az "if" feltételébe van a hiba, olyan mintha a set_temp új értéket kapna.
Minden integer típusú, most már azzal se lehet gond, a túlcsordulásos részeket lekezeltem.
(#) nagzso válasza nagzso hozzászólására (») Dec 30, 2012 /
 
Megcsináltam... A probléma pedig a következő volt: a feltételeknél a számításokat beleraktam egy változóba, és a két váltózót hasonlítottam össze. Úgy néz ki nem szereti az első megoldásomat...
(#) k válasza icserny hozzászólására (») Jan 2, 2013 /
 
Idézet:
„Az egyik "korlátozás" az, hogy csak PIC18-ig elérhető... Bővebben: Link”


Lehet, hogy megint nagyon 'láma' a kérdés, de letöltöttema v3.44 et, csap éppen indítható file nincs
esetleg valami tipp?

Előre is köszi
Következő: »»   67 / 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