Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   119 / 153
(#) benjami hozzászólása Jan 12, 2016 /
 
Sziasztok!
Elég gyakori eset, ha valami periféria használatánál a párszáz nanoszekundum, egy-két mikroszekundumos késleltetéseket néhány Nop utasítással oldjuk meg. Igen ám, de ennek az a mellékhatása, hogy a fordító (legalább is a C18) az inline assembly beszúrása miatt ettől kezdve a teljes függvényre vonatkozóan kikapcsolja az optimalizációt, ami miatt tele lesz felesleges movlb utasítással a kapott kód.
Jelenleg ezt úgy oldottam meg, hogy a program futását nem befolyásoló értékadással helyettesítettem a Nop-okat (pl. #define Nop() PCLATU = 0).
Van-e ötletetek, hogyan lehetne ezt valami elegánsabb megoldással megoldani?
(#) Hp41C válasza benjami hozzászólására (») Jan 12, 2016 /
 
A C18 fejlesztői gondoltak erre is.
A hozzászólás módosítva: Jan 12, 2016

C18_Nop.jpg
    
(#) potyo válasza Hp41C hozzászólására (») Jan 12, 2016 /
 


A Note 1 alatt pont azt írja, hogy ezen makrók használata befolyásolja a függvény optimalizálását
(#) potyo válasza ativagyok hozzászólására (») Jan 12, 2016 / 1
 
Egyébként ha az if-es szerkezet futását szeretnéd gyorsítani, akkor csinálhatsz valami ilyesmit:

  1. if (ADC < hatar25)
  2. {
  3.         if (ADC <  hatar12)
  4.         {
  5.                 if (ADC < hatar6)
  6.                 {
  7.                         if (ADC < hatar3)
  8.                         {
  9.                                 if (ADC < hatar1)
  10.                                 {
  11.                                        
  12.                                 }
  13.                                 else if (ADC < hatar2)
  14.                                 {
  15.                                
  16.                                 }
  17.                                 else    // ADC < hatar3
  18.                                 {
  19.                                
  20.                                 }
  21.                         }
  22.                         else    // ADC >= hatar3
  23.                         {
  24.                                 if (ADC < hatar4)
  25.                                 {
  26.                                
  27.                                 }
  28.                                 else if (ADC < hatar5)
  29.                                 {
  30.                                
  31.                                 }
  32.                                 else    // ADC < hatar6
  33.                                 {
  34.                                
  35.                                 }
  36.                         }
  37.                 }
  38.                 else    // ADC >= hatar6
  39.                 {
  40.                         ...
  41.                 }
  42.         }
  43.         else
  44.         {
  45.                 ...
  46.         }
  47. }
  48. else
  49. {
  50.         ...
  51. }
A hozzászólás módosítva: Jan 12, 2016
(#) killbill válasza potyo hozzászólására (») Jan 12, 2016 /
 
Persze ezt nem fix if-ekkel, hanem egy 8-10 soros ciklussal, es a hatarertekek egy tablazatban vannak leteve. A felezős módszerrel. Az 1024 elembol 10 vizsgalattal megtalalja a keresett ereket. 50 elemu tabla eseten max. 6 vizsgalat. Hamár programozunk...
(#) Hp41C válasza potyo hozzászólására (») Jan 12, 2016 /
 
Bocsánat, benéztem...
(#) dani9228 hozzászólása Jan 13, 2016 /
 
Hello. Olyan kérdésem lenne, hogy a MikroC PRO-ba lehet e hozzáadni további pic típusokat? Van egy 16F505-öm és azt szeretném programozni. EasyPIC v7-em van, de ha van másik olyan program amiben megtudom írni a programot, és kompatibilis az EasyPIC-el, az is tökéletes lenne.
Köszi!
(#) Hp41C válasza dani9228 hozzászólására (») Jan 13, 2016 /
 
16F505 - 1k program memória, 72 byte RAM, 2 szintű stack -- Nem hísználnék C fordítót.
(#) Lamprologus hozzászólása Jan 14, 2016 /
 
  1. int i=0;
  2.  
  3. if (i>0) i--;
  4.  else i=4;

Ha van egy ilyen programrészem, akkor hogyan fordulhat elő a program futása közben, hogy az i mondjuk 65??? (Máshol az i csak a feltételvizsgálatnál van felhasználva!)
A hozzászólás módosítva: Jan 14, 2016
(#) pipi válasza Lamprologus hozzászólására (») Jan 14, 2016 /
 
Hali!
pl "máshol" elírtál egy feltételvizsgálatot (==) értékadásra(=) ?
vagy valahol van egy pointered, ami rossz helyre mutat..
nézd meg debuggerrel mi történik.
(#) Lamprologus válasza pipi hozzászólására (») Jan 15, 2016 /
 
Feltételvizsgálatok rendben vannak.
Pointert nem használok.

Nézem debuggerrel ... sajnos elég ritkán jelentkezik a hiba, én nem mindig, csak azt látom, hogy a változó olyan értéket vett fel amit elvileg nem kéne. azt hogy mikor vette fel azt már nem tudni.
(#) Hp41C válasza Lamprologus hozzászólására (») Jan 15, 2016 /
 
Karakterfüzér (string) változó túlírása? 65 a kis "a" betü kódja.
(#) ativagyok hozzászólása Jan 25, 2016 /
 
Sziasztok!
Nyomógombok kezelésével próbálkozom, ezen belül lenne szükségem egy olyan funkcióra, ami két gomb együttes megnyomása esetén lép működésbe. A nehézséget az okozza számomra, hogy az együttes lenyomásnak ki kellene zárnia a gombok egyedüli megnyomáskori funkcióját. Remélem sikerült érthető formában leírom a problémát.
(#) kissi válasza ativagyok hozzászólására (») Jan 25, 2016 /
 
Egy lehetséges megoldás, ha NY_A és NY_B '1'-t ad nyomáskor !
  1. if (NY_A  & NY_B )  fuggveny_AB();
  2. else if (NY_A)  fuggveny_A();
  3. else if ( NY_B) fuggveny_B();
(#) kissi válasza kissi hozzászólására (») Jan 25, 2016 /
 
Már nem tudtam módosítani :
Egy lehetséges megoldás, ha NY_A és NY_B '1'-t ad nyomáskor !
  1. if (NY_A  & NY_B )  fuggveny_AB();
  2. else if (NY_A)  fuggveny_A();
  3. else if ( NY_B) fuggveny_B();


szerk.: Persze a nyomógombokat érdemes "prellmentesíteni" is és NY_A-t, NY_B-t csak segédváltozóként használni !
(#) ativagyok válasza kissi hozzászólására (») Jan 25, 2016 /
 
Ezzel az a gond, hogy mikor elengedjük a két gombot, egy pillanatig az egyik még nyomva marad, és lefut annak a függvénye is.
Valószínűleg létezik egyszerűbb, de jelenleg azzal próbálkozom, hogy (NY_A & NY_B) függvényében elindítok egy timer-t, és NY_A, vagy NY_B csak ennek letelte után tud lefutni.
Szerk.: A gombok hardveresen és szoftveresen is vannak prellmentesítve.
A hozzászólás módosítva: Jan 25, 2016
(#) abcdabcd válasza ativagyok hozzászólására (») Jan 25, 2016 /
 
Tegyél a programodba akkor egy változót, amit beállítasz valamilyen értékre, amikor elindul a "kétgombos" üzemmód, és az "egygombos" egy-egy rutin elején meg ellenőrzöd, hogy az a változó "kétgombos érték"-ben van-e, és akkor ne fusson le az egygombos rutin... ja és akkor itt az "egygombos" rutinban pedig egyben nullázni is tudod ezt a "kétgombos" változót, hogyha legközelebb csak az egyik gombot nyomod meg, akkor már fusson... vagy valami hasonlót lehet kivitelezni... így első gondolatra ez nekem jónak tűnik így, aztán lehet esetleg mégse pont így jó, hanem valamit módosítani kell esetleg a gondolatmeneten, vagy valami apró részletet hozzáadni...
(#) kissi válasza ativagyok hozzászólására (») Jan 25, 2016 /
 
Hát az alap, hogy egy nyomógombot "prellmentesítés" elfogadás után egy darabig tiltani kell ( pl. minden NY_A és/vagy NY_B aktiválás után elindítasz egy számlálót, ami mondjuk 0,5 s-ig tiltja az újabb elfogadást!) ! Enélkül nem megy, de ez ugyanolyan fontos a NY kezelésben, mint a "prellmentesítés" !
A hozzászólás módosítva: Jan 25, 2016
(#) ativagyok válasza kissi hozzászólására (») Jan 25, 2016 /
 
Én más megoldást használok:
A gomb lenyomásakor átállít egy flag bitet, majd elengedéskor aktiválódik, ha aktív a flag bit, és egyben vissza is állítja a flag bitet. Így nem volt szükség a számlálós tiltásra.
abcdabcd: Időzítés nélkül sajnos nem jó, mivel a két gomb elengedése után biztosan lesz olyan pillanat, amikor még az egyik nyomva van, és ilyenkor aktiválódik az egy gombos funkció.
(#) abcdabcd válasza ativagyok hozzászólására (») Jan 25, 2016 /
 
Akkor esetleg vagy kezeld gyorsabban a gombokat, pl megszakításból... mert legalábbis elméletben eléggé kicsi az esélye annak, hogy a két gombot pontosan egyszerre engedik fel, valamelyik valószínű nyomvamarad ha nem is túl sokáig... Aztán persze ez lehet nem jó megoldás, mert véletlenül valószínűleg előfordulhat olyan, hogy mégis épp egyszerre van a két gomb felengedve...

Vagy akkor még lehet akár az ellenkezőjét is csinálni, vagyis, hogy az egygombos rutinok elején beolvasod a gombok állását, és ha a másik gomb is nyomva van, akkor a kétgombos rutin fusson...
Viszont valami időzítés meg ahogy kissi is írta valószínű kell, mert lehet akkor az adott rutinok túl rövidek, és amire lefutnak, a felhasználó csak akkor engedi fel a gombot, ami amúgy gondolom csak annyi, hogy valaki megnyomja, és a másodperc töredéke múlva már engedi is fel...

A késleltetés meg akkor lehet végülis akár a rutin végén is (vagy az elején), vagy pedig lehet valahogy úgy is csinálni, hogy ott ahol a gombnyomásokat kezeled és a megnyomott gombnak megfelelően indítod el a különböző funkciókat, hogy akkor oda kell rakni valami "tiltást", hogy egy gomb megnyomása után meddig ne érzékeljen másik gombnyomást --> feltételezve, hogy a felhasználók úgyse tudják végtelen rövid idő alatt "értelmesen kezelve" nyomkodni a gombokat --> így, ha pl túl gyorsan jön bármilyen két gombnyomás egymáshoz képest, akkor az valószínűleg nem "érvényes" gombnyomás...
És akkor a kétgombos üzemmódot meg ezen a "tiltási időn" belül valami még rövidebb időn belül lehet "érvényes két gomb megnyomásának" tekinteni... Vagy mondjuk azt akár lehet úgy is, hogyha valami megszakítással érzékeli a program a gombnyomást, hogy akkor megnézni, hogy esetleg mind a kettő meg lett-e nyomva, és akkor az időzítős részt nem kell ezzel bonyolítani...
A hozzászólás módosítva: Jan 25, 2016
(#) Kovidivi válasza ativagyok hozzászólására (») Jan 25, 2016 / 1
 
És mi lenne, ha megvárnánk, amíg mindkét gomb felengedésre kerül? Utána pedig jöhetne a függvény. Igaz, hogy ilyenkor blokkolódik a program, de ha olyanok az igények, belefér. Vagy megszakításban mondjuk 10mS-ként le van kérdezve minden gomb állapota, ha le van nyomva, a hozzá tartozó változó növelve lesz 1-gyel. A főprogramban meg kell annyi segédváltozó, ahány gomb van, amiket mondjuk 100mS-ként egyenlővé teszed a gombhoz tartozó változóval. Így sima feltételrendszerrel megállapítható, hogy melyik gombok voltak lenyomva ( amelyiknek a 100mS-mal előző értéke kisebb, mint a jelenlegi). Itt nem kell prellmentesíteni se. Az időket tetszés szerint kell módosítani, hogy ne legyen se gombnyomásvesztés, se semmi tévesztés.
A hozzászólás módosítva: Jan 25, 2016
(#) abcdabcd válasza ativagyok hozzászólására (») Jan 25, 2016 /
 
Idézet:
„mivel a két gomb elengedése után biztosan lesz olyan pillanat, amikor még az egyik nyomva van, és ilyenkor aktiválódik az egy gombos funkció.”

De pont erre írtam, hogy ezért az egygombos elején ellenőrizd a változót (vagy a te esetedben flag-et), hogy aktív-e... vagyis ne a kétgombos rutin végén tiltsd le, hanem az egygombos elején ellenőrzöd, ha még aktív (--> ami azt jelenti, hogy épp lefutott a kétgombos) akkor tiltod a flag-et és az egygombos rutint viszont ekkor nem futtatod...
Persze lehet jobb ezt valahogy "üzembiztosabban" kezelni, mert ha meg mégis pont egyszerre van felengedve a két gomb, vagy csak azon az "időfelbontáson" belül, amilyen felbontással a készüléked ellenőrizni tudja a gombok állapotát, akkor így meg az azutáni egygombos gombnyomás érvénytelen, és akkor a felhasználónak újra meg kell nyomnia a gombot, hogy érvényes legyen --> az meg nem biztos, hogy jó, mert akkor meg a felhasználó szempontjából úgy tűnik, mintha nem érzékelne minden gombnyomást a készülék...
A hozzászólás módosítva: Jan 25, 2016
(#) kissi válasza ativagyok hozzászólására (») Jan 25, 2016 /
 
Idézet:
„Én más megoldást használok:
A gomb lenyomásakor átállít egy flag bitet, majd elengedéskor aktiválódik, ha aktív a flag bit, és egyben vissza is állítja a flag bitet. Így nem volt szükség a számlálós tiltásra.”


Ezek szerint a prell ezen kívül szűrve !
Viszont így egy gomb lenyomásával ( felengedés nélkül!) "beragad", idegesebb emberek nagyon erősen fogják nyomni a gombot, mert nem reagál egyből ! Szerintem nem ez a jó megoldás, de Te tudod!
(#) ativagyok hozzászólása Jan 26, 2016 /
 
Köszönöm mindenkinek a segítséget. Sikerült megoldani, az alábbi kód megfelelően működik:
  1. If(NY_A =1 && timerflag) flag0 = 1;
  2. If(NY_A = 0 && flag0 = 1) függvény_A; flag0 = 0;
  3. If(NY_B =1 & timerflag) flag1 = 1;
  4. If(NY_B = 0 && flag1 = 1) függvény_B; flag1 = 0;
  5. If(flag0 && flag1) flag2 = 1;
  6. If(flag2 && NY_A = 1 && NY_B = 1) {
  7. függvény_C;
  8. flag2 = 0;
  9. timerstate = 0;
  10. TMRxON_bit = 1;  // A timer megszakításában timerstate = 1;
  11. }


kissi: Ebben a formában lenyomott gomb esetén a program tovább fut, nem ragad be.

Kovidivi:A Te megoldásod is nagyon jónak tűnik, bár lehet hogy kicsit belekeverednék.
Elmentem későbbre, még jól jöhet.

abcdabcd:Valami hasonlóval próbálkoztam először, de időzítés nélkül sajnos nem jó.
A hozzászólás módosítva: Jan 26, 2016
(#) janimester hozzászólása Jan 26, 2016 /
 
Üdv. Lenne egy olyan kérdésem, hogy csinálnék az autómba egy pices turbónyomás feszültség és mi egyéb mérő műszert és az értékeket bar graph megjelenítéssel szeretném csinosítani a kijelzett számok- értékek mellé. Egy "előnyagyolt" programot össze tudtam barkácsolni. Amit szeretnék rajta változtatni, hogy ne az összes vagyis 5X7-es karakterenként lépjen a kijelzés hanem karakterenként külön függőleges sorokban vagyis finomabb kijelzéssel működjön a dolog és ne egy egyszerű kijelző törléssel távolítsa el az előző mért értéket hanem valami ésszerűbb megoldással, így rengeteget frissít a kijelző és mindíg nulláról fut fel az érték (bar). Szeretném ha valaki tudna segíteni mit kéne átírni , hogy a fentieknek vázolt módon működjön a program. Linkelek egy videót mégis mire gondoltam. LCD BARGRAPH Igazából a progress bar ha működne onnan már megoldanám csak sajna nincs akkora tudásom kivitelezni
  1. sbit LCD_RS at LATD0_bit;
  2. sbit LCD_EN at LATD1_bit;
  3. sbit LCD_D4 at LATD2_bit;
  4. sbit LCD_D5 at LATD3_bit;
  5. sbit LCD_D6 at LATD4_bit;
  6. sbit LCD_D7 at LATD5_bit;
  7. sbit LCD_RS_Direction at TRISD0_bit;
  8. sbit LCD_EN_Direction at TRISD1_bit;
  9. sbit LCD_D4_Direction at TRISD2_bit;
  10. sbit LCD_D5_Direction at TRISD3_bit;
  11. sbit LCD_D6_Direction at TRISD4_bit;
  12. sbit LCD_D7_Direction at TRISD5_bit;
  13.  
  14. unsigned int adc_rd, diff;
  15. unsigned long int BarSegmentNum;
  16. char adcprint, i;
  17.  
  18. const char character[] = {31,31,31,31,31,31,31,31};
  19.  
  20. void CustomChar(char pos_row, char pos_char)
  21.      {
  22.      char ip;
  23.      Lcd_Cmd(64);
  24.      for (ip = 0; ip<=7; ip++) Lcd_Chr_CP(character[ip]);
  25.      Lcd_Cmd(_LCD_RETURN_HOME);
  26.      Lcd_Chr(pos_row, pos_char, 0);
  27.      }
  28.  
  29. void main()
  30. {
  31.      ADCON1 = 1;            // Configure RA0 pin as analog
  32.      TRISA.F0  = 1;            // Configure RA0 pin as input
  33.  
  34.      Lcd_Init();               // Initialize LCD
  35.      Lcd_Cmd(_LCD_CLEAR);      // Clear LCD
  36.      Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off
  37.  
  38.  
  39.      while(1)
  40.          {
  41.          adc_rd = ADC_Read(0);         // Get ADC value from 1st channel
  42.          inttostr(adc_rd, adcprint);   // Conversion to string
  43.          Lcd_out(1,1,adcprint);        // Prints ADC steps in LCD first row
  44.  
  45.          if (diff != adc_rd)
  46.               {
  47.               BarSegmentNum = adc_rd/(1023/16); // Calculate numbers of bar graph segments
  48.  
  49.               Lcd_out(2,1,"                ");  // Clears LCD second row
  50.  
  51.               for (i=0;i<BarSegmentNum;i++)     // Loop to print each bar segment in second row
  52.                     {
  53.                     CustomChar(2,i+1);          // Print custom character for bargraph segment
  54.                     }
  55.               }
  56.          Delay_ms(10);                   // Stabilize LCD display
  57.  
  58.          diff = adc_rd;
  59.  
  60.          }
  61.  
  62. }

Névtelen.jpg
    
(#) usane válasza janimester hozzászólására (») Jan 26, 2016 /
 
A videó alján levő linkben megtalálható a megoldás. Igaz az nem mikroc-ben van, de nem nehéz átvenni belőle a lényeget. 5 karaktert kell létrehoznod a legvékonyabb csíktól a tele karakterig, és azt kell kiírogatnod egymás után. A kijelző törlést meg úgy tudod elkerülni, hogy a törlendő karakter helyére kírod az újat, vagy ha törölni kell akkor SPACE-t .
(#) kissi válasza ativagyok hozzászólására (») Jan 26, 2016 /
 
Idézet:
„Ebben a formában lenyomott gomb esetén a program tovább fut, nem ragad be.”

Igaz, csak feleslegesen vizsgálod pl. a NY_A =1 && timerflag egyidejűségét, mert gondolom a timerflag csak akkor áll be, ha elég ideig nyomtad a gombot ! --> lassítja és "terjengőssé" teszi a kódodat ( persze, az hogy ez számottevő-e, az más kérdés!)!
Ugyanezt írtam szerintem, csak az újbóli vizsgálat nélkül !
(#) ativagyok válasza kissi hozzászólására (») Jan 27, 2016 /
 
A timerflag mindig be van állva, kivéve a dupla gombos üzemmód utáni 200ms-ot.
(#) zenetom hozzászólása Jan 31, 2016 /
 
Sziasztok!
Az alábbiakban van C18-as I2C írás függvénye ("gyári')

  1. unsigned char WriteI2C( unsigned char data_out )
  2. {
  3.   SSPBUF = data_out;           // write single byte to SSPBUF
  4.   if ( SSPCON1bits.WCOL )      // test if write collision occurred
  5.    return ( -1 );              // if WCOL bit is set return negative #
  6.   else
  7.   {
  8.         if( ((SSPCON1&0x0F)!=0x08) && ((SSPCON1&0x0F)!=0x0B) )  //Slave mode only
  9.         {
  10.               SSPCON1bits.CKP = 1;        // release clock line
  11.               while ( !PIR1bits.SSPIF );  // wait until ninth clock pulse received
  12.  
  13.               if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
  14.               {
  15.                 return ( -2 );           //return NACK
  16.               }
  17.                   else
  18.                   {
  19.                         return ( 0 );                           //return ACK
  20.                   }    
  21.         }
  22.         else if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) )     //master mode only
  23.         {
  24.             while( SSPSTATbits.BF );   // wait until write cycle is complete  
  25.             IdleI2C();                 // ensure module is idle
  26.             if ( SSPCON2bits.ACKSTAT ) // test for ACK condition received
  27.                  return ( -2 );                 // return NACK
  28.                 else return ( 0 );              //return ACK
  29.         }
  30.        
  31.   }
  32. }

Amikor elkészült a küldés, akkor azt a
Idézet:
„while ( !PIR1bits.SSPIF ); // wait until ninth clock pulse received”
sor figyeli. Azonban ezt a megszakítás flaget semmi sem törli itt. Tehát azt nekünk kell. Ez így normális? Kicsit furcsállom, hogy azt nem rakták bele...
(#) zenetom válasza zenetom hozzászólására (») Jan 31, 2016 /
 
Na, megint hamar írtam, hát ez evidens, nekünk kell törölni a megszakítás bitet. Csak ha egy kezdő programozó elkezdi ezt használni, akkor majd csodálkozni fog, hogy miért nem működik jól a program.. Jó, mondjuk tudnia kell a kezdő programozónak is hogy törölni kell a flagbitet.
Bár akkor minek a C ?
Következő: »»   119 / 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