Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   110 / 153
(#) kissi válasza usane hozzászólására (») Ápr 1, 2015 /
 
2 még jó, akkor még ott van, utána veszteség !
A hozzászólás módosítva: Ápr 1, 2015
(#) usane válasza kissi hozzászólására (») Ápr 1, 2015 /
 
2 sem jó. mindkettő 2 ciklus. Nekem a sebesség a fontos most. Inkább nekiállok megírom én ASMben minthogy mindig átnézzem milyen szemetet fordított.
(#) Hp41C válasza usane hozzászólására (») Ápr 1, 2015 /
 
Sokáig mérgelődtem, majd ugyan erre a következtetésre jutottam...
(#) mark.budai válasza don_peter hozzászólására (») Ápr 3, 2015 /
 
Ez egy 16F1705.
Küldöm az egész programot. Egy állítható időzítő lenne, nagyon egyszerűen megoldva, maga a program sem tökéletes, de ez nem baj, csak az ADC-t kéne helyrehozni.
A hozzászólás módosítva: Ápr 3, 2015

main.c
    
(#) don_peter válasza mark.budai hozzászólására (») Ápr 3, 2015 /
 
Így elsőre a "kikapcs" értéke lehet lebegőpontos is, bár ez elvileg nem lehet gond, de nem árt ott a típusokkal variálni.
És azt sem tudom miért kellene long típusokat használnod, szerintem oda short is elég lenne.
PIC, hogy van bekötve?
(#) don_peter hozzászólása Ápr 3, 2015 /
 
Srácok, nekem is szükségem lenne egy kis segítségre vagy legalább kis lökésre, mert leakadtam.
Van egy függvényem ami nem azt csinálja amit kellene neki:
  1. void homero_szal(unsigned short fok){
  2.         unsigned float oszto;
  3.         unsigned short hofok, i;
  4.         unsigned char result;
  5.         oszto = 31/400; //0,0775
  6.         hofok = fok > 100 ? (fok-100) : 0;
  7.         result = hofok*oszto;
  8.  
  9.         glcd_gotoxy(2,2,1); // Kijelző pozicionálása
  10.         printf("%i", (int)result); // Kiíratjuk az eredményt
  11. }
  12. homero_szal(500); // példa

Ha a példát le akarjuk követni a következőket kellene csinálnia.
fok változó értéke 500 lesz, oszto változó értéke 0,0775 vagy is lebegőpontos szám lesz, hofok változó értéke a feltétel lefutása után megkapja fok változó -100 értékét vagy is 400 lesz.
result változónk értéke hofok*oszto vagy is 400*0,0775 azaz 31.
Jelenleg az eredmény nulla lesz.
Arra rájöttem, hogy a típusokkal lesz valami gubanc, de eddig sikertelenül kísérletezgettem.
C18, MPLAB
A hozzászólás módosítva: Ápr 3, 2015
(#) killbill válasza don_peter hozzászólására (») Ápr 3, 2015 / 2
 
Tobb hiba is van. Eloszor is nincs olyan, hogy unsigned float. Furcsa, hogy a fordito nem szol erte.
De a fo hiba az osztoban van. az, hogy 31/400 az nem lebegobontos szamitas, hanem egesz, igy annak az erteke 0 lesz. Ha azt irod, hogy oszto = 31 / 400.0; akkor mar jo lesz.
De ezt az egeszet meg lehet csinalni float nelkul is. result = (fok * 31) / 400;
A hozzászólás módosítva: Ápr 3, 2015
(#) tomi52 hozzászólása Ápr 4, 2015 /
 
Réges-rég, még PC-n használtam valamennyit a C nyelvet, nem vagyok benne - sajnos - profi. Azt szeretném kérdezni, ha az alábbi mintában egy regiszter bitet, vagy egy regisztert szeretnék paraméterként megadni, azt milyen típusnak kell megadni a hívott eljárás paramétereként, illetve hogyan tudok rá hivatkozni az eljárásban?
(Mivel linuxon nyomulok, MPLAB-X-et és XC8-at használgatom.)
  1. void abcd(???)
  2. {
  3.   .....
  4. }
  5.  
  6. void main(void)
  7. ......
  8.   abcd(RB0);
  9. .........
(#) killbill válasza tomi52 hozzászólására (») Ápr 4, 2015 / 1
 
Ha a hivott fuggvenyben a regiszter erteket valtoztatni is akarod, akkor a cimet kell atadnod.
Szerintem regiszter bitjere (bit field) ilyen modon nem tudsz hivatkozni, csak egesz regiszterre. A PIC regiszterek tobbnyire "volatile unsigned char" tipusuak.
  1. void abcd(volatile unsigned char *reg)
  2. {
  3.   *reg = 0;  // torli a regisztert
  4.   *reg |= 1<<3;  // a harmas bitet egybe allitja
  5.   *reg &= ~(1<<7); // a legfelso bitet torli
  6. }
  7.  
  8. void main(void)
  9. {
  10.    abcd(&PORTB);
  11. }


Ha nem akarod modisitani a regiszter erteket, akkor sima unsigned char vagy int-nek deklaralod:
  1. abcd(unsigned char reg)
  2. {
  3.   if(reg & 8)
  4.      printf("Egyben van a harmas bit!\n");
  5. }
  6.  
  7.  
  8. void main(void)
  9. {
  10.   abcd(PORTB);
  11. }
A hozzászólás módosítva: Ápr 4, 2015
(#) don_peter válasza killbill hozzászólására (») Ápr 4, 2015 /
 
Köszi, a második volt a jó irány.
(#) killbill válasza don_peter hozzászólására (») Ápr 4, 2015 /
 
'csmit. Azert erdemes az elsot is megerteni, mert ez a C alapjaihoz tartozk. Tipusok es implicit konverziok.
(#) don_peter válasza killbill hozzászólására (») Ápr 4, 2015 /
 
Azért nem írtam rá mert az véletlen került oda és maradt ott (float)
Ha erre gondolsz: "oszto = 31/400; //0,0775"
Akkor viszont tényleg nem értem.
Az oszto változó egy lebegőpontos változó, úgy tudtam ezek szerint rosszul, hogy az eredmény lesz majd lebegőpontos.
Ezek szerint csak, akkor lesz valami lebegőpontos, ha a benne elvégzett műveleti értékek is lebegőpontosok, vagy legalább is az egyik? Ha azok viszont egészek akkor a művelet eredménye is egész marad. Bár ezt leírni is fura...
A hozzászólás módosítva: Ápr 4, 2015
(#) mark.budai válasza don_peter hozzászólására (») Ápr 4, 2015 /
 
A short szerintem semmiképp nem elég, az adc_val 1023-ig mehet, oda kell a long, az i változónak 600-ig kell tudni számolni, a kikapcs pedig az (adc_val+120)/2 értéket vehetni fel, ez maximum 571. (Talán nem is kéne külön felvenni a kikapcs változót, de bőven van hely, most nem kell spórolni vele.)
Kapcsolás a mellékletben.
A hozzászólás módosítva: Ápr 4, 2015

idozito.png
    
(#) killbill válasza don_peter hozzászólására (») Ápr 4, 2015 / 3
 
Ha az osztas mindket operandusa egesz, akkor egesz osztast fog vegezni, es az eredmeny is egesz lesz. Ha a ket operandus nem azonos tipusu, akkor szigoru szabalyok szerint egyforma tipusuakra lesznek konvertalva a muvelet elott, es a muvelet is olyan tipusu lesz. A tipuskonverzio lenyege nagyjabol, hogy a kevesebb bitbol allo valtozot konvertalja a nagyobbra. Ha azonos szelessegu unsigned es signed keveredne, akkor unsigned lesz a signed-bol. Az osszes char-t es short-ot automatikusan int-re konvertalja, az osszes float-ot double-ra. Ez mindig megtortenik, minden muvelet elott.

Ha pl. egy int es egy long van, akkor az int-et long-ra alakitja, es long osztas lesz. Ha az egyik float, a masik int, akkor mindkettot double-ra alakitja, es double osztast csinal.


pont azt csinalja, mintha ezt irnad le:
int a;
long b, c;

c = (long)a + b;

De neked nem kell odairnod a (long)-ot, mert a C fordito automatikusan beleteszi.

ha azt irod, hogy:

double oszto;
oszto = 31 / 400;

abbol ez lesz:
oszto = (double) (31 / 400);
(#) killbill válasza mark.budai hozzászólására (») Ápr 4, 2015 / 2
 
Sokkal egyertelmubb a dolog, ha az stdint.h-t include-olod, es onnantol kezdve a int8_t uint8_t, int16_t, stb tipusokat hasznalod. A short, long, int annyi bites, amennyit az adott 'C' fordito jonak lat. Viszont az int16_t az garantaltan 16 bites int.
(#) mark.budai válasza killbill hozzászólására (») Ápr 4, 2015 /
 
Mindig megnézem a program súgójában, hogy milyen nevű változót írok a programba, melyikbe "fér bele", amit szeretnék.
Beírtam így, amit ajánlottál, de ugyan azt csinálja, mint eddig, nem regál a potira, akármerre tekerem. Már kipróbáltam úgy is, hogy a pic bemenetét közvetlenül tápra, vagy gnd-re kötöttem, kizárva a poti hibáját, és úgy is ugyan ez van.
(#) killbill válasza mark.budai hozzászólására (») Ápr 4, 2015 / 1
 
Felreertesz. Azt nem tudom, hogy az AD miert nem mukodik, nem ezert irtam, amit irtam. Altalanos jotanacs, hogy ha ezeket a tipusokat hasznalod, akkor az mindig, minden forditon, minden processzoron ugyanzt jelenti. A programod elvileg jo kellene legyen, nem talalok benne semmi elmeleti hibat. (Amig a kapcsolo nyitva van, addig a kimeneti LED vilagit. Amikor a kapcsolo zarva van, akkor a masik LED villog, es a kimenet lekapcsol egy az AD ertektol fuggo ido utan.) Az AD inicializalas, esetleg nem lehet rossz? Nem tudom, hogy kell-e kulon analogra allitani a RA4-es labat.
(#) mark.budai válasza killbill hozzászólására (») Ápr 4, 2015 /
 
A lényeg, hogy átírtam, de köszi, hogy megosztottad ezt velem, így legalább nem kell mindig megnéznem, milyen változót kell beírnom.
Igen, pont ezt akartam elérni a programmal, és szépen működik az AD-t kivéve.
Biztosan az inicializálás lehet rossz, mert próbáltam több porton is, egyikkel sem működik. Csak nem tudom, hogy kéne inicializálni, hogy jó legyen.
(#) killbill válasza mark.budai hozzászólására (») Ápr 4, 2015 /
 
Az egyik jo modszer az inicializalasra, hogy elolvasod az adott PIC adatlapjat, es annak megfeleloen inicializalod a regisztereket. Igy nem fuggsz a gyari vagy gagyi vagy akarmilyen fuggvenykonyvtaraktol.

A read_adc() fuggvenynek nem kell atadni, hogy melyik bemeneten olvasson?
(#) mark.budai válasza killbill hozzászólására (») Ápr 4, 2015 /
 
Az a baj, hogy az adatlap assembler-ben adja meg a dolgokat, én ahhoz meg nagyon nem értek. De nem is lenne mit másképp inicializálni, mint ahogy a programban van.
Nem tudom, lehet, hogy valamit itt kéne megadni, de akárhogy írom be a zárójelbe a 3-at, nem akarja elfogadni a fordító.
(#) killbill válasza mark.budai hozzászólására (») Ápr 4, 2015 /
 
Az adatlap azt adja meg, hogy a regiszterek egyes bitjei mit jelentenek. Ez se nem assembly, se nem C. Mindegy, hogy egy regiszterbe hogyan irsz be egy erteket, az a fontos, hogy mit irsz bele. Ez van leirva az adatlapban.
A programod meghiv tobb konyvtari fuggvenyt, ami inicializalja az AD-t. Ezteket a fuggvenyeket valaki megirta, es gondolom, azt is leirta, hogy mik a parameterei. Ez igaz kell legyen az adc_read() fuggvenyre is. Milyen fordito ez, milyen konyvtarral?
(#) mark.budai válasza killbill hozzászólására (») Ápr 4, 2015 /
 
Ja, így már értem mit írsz. De honnan tudom, hogy az én fordítóm jó regisztereket használ-e?
CCS C Compiler 5.037-et használok, a könyvtárról semmit nem tudok, feltelepítettem a programot, én azóta nem bántottam.
(#) killbill válasza mark.budai hozzászólására (») Ápr 4, 2015 / 1
 
itt egy reszlet a CCS fordito leirasabol:

set_adc_channel(2);
delay_us(10);
value = read_adc();

Ezt te is elolvashatod, ebben le van irva, hogy melyik fuggveny mit csinal.
(#) mark.budai válasza killbill hozzászólására (») Ápr 4, 2015 /
 
Nagyon jó, végre működik, nem írtam be a set_adc_channel sort, és a 10us késleltetést. Pontosabban próbáltam beírni, de nem jó helyre tettem, mert bár a main függvényben, de a while cikluson kívül volt, a setup_adc soroknál.
Köszönöm szépen a segítséget!
(#) benjami hozzászólása Ápr 5, 2015 /
 
Sziasztok. Hi-Tech PICC-18 vagy XC8 adat EEPROM kezelésével lenne egy kis gondom. Lenne néhány változó amit abban tárolnék. Az adatok kezdőértékkel való ellátását a fordító programmal végezném.
Ehhez kicsit módosítottam a beépített __EEPROM_DATA(a, b, c, d, e, f, g, h); makrót, hogy ne csak 8db 8bites, hanem 16 vagy 32 bites értékekeket is el tudjak tárolni.
  1. #define EEDATA_CHAR1(a) asm("\tpsect eeprom_data,class=EEDATA"); asm("\tdb\t" ___mkstr(a))
  2. #define EEDATA_CHAR2(a, b) asm("\tpsect eeprom_data,class=EEDATA"); asm("\tdb\t" ___mkstr(a) "," ___mkstr(b))
  3. #define EEDATA_WORD1(a) asm("\tpsect eeprom_data,class=EEDATA"); asm("\tdw\t" ___mkstr(a))
  4. #define EEDATA_WORD2(a, b) asm("\tpsect eeprom_data,class=EEDATA"); asm("\tdw\t" ___mkstr(a) "," ___mkstr(b))
  5. #define EEDATA_DWORD1(a) asm("\tpsect eeprom_data,class=EEDATA"); asm("\tdw\t" ___mkstr(a) "," ___mkstr((a) >> 16))
  6. #define EEDATA_DWORD2(a, b) asm("\tpsect eeprom_data,class=EEDATA"); asm("\tdw\t" ___mkstr(a) "," ___mkstr((a) >> 16) "," ___mkstr(b) "," ___mkstr((b) >> 16))
  7.  
  8. EEDATA_DWORD1(0x12345678);
  9. EEDATA_CHAR1(0);
  10. EEDATA_WORD2(0x1234, 0x2345);

A fenti kóddal szépen bele is teszi az adatokat az EEPROM-ba, de hogyan tudnám kinyerni az így betett változók EEPROM-beli címeit, mert semmilyen név, cimke nem tartozik az egyes értékekhez?
(#) pipi válasza benjami hozzászólására (») Ápr 5, 2015 / 1
 
Hali!
nem tudok róla hogy lehetne automatikusan cimkézni az eeprom területen, én igy csinálom, úgyis tudom mit hová teszek az eepromban:

static enum //eeprom kiosztás
{
EEaddr_nyit_tanit_veg1L = 0x10, // kezdőcím 0x10
EEaddr_nyit_tanit_veg1H, //11
EEaddr_nyit_start_tim1L, //12
EEaddr_nyit_start_tim1H, //13
EEaddr_nyit_tanit_veg2L, //14
EEaddr_nyit_tanit_veg2H, //15
EEaddr_nyit_start_tim2L, //16
EEaddr_nyit_start_tim2H, //17
EEaddr_autcsuk, //18 //byte
EEaddr_SETUP, //19
EEaddr_DIP //1a
};

....
EE_nyit_start_tim1 = ee_read(EEaddr_nyit_start_tim1L) + ee_read(EEaddr_nyit_start_tim1H) << 8);

...
//org 0
__EEPROM_DATA(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
__EEPROM_DATA(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
//org 0x10
__EEPROM_DATA(0x72, 9, 0x2c, 01, 0x51, 0x0c, 0x84, 0x03);
...
(#) benjami válasza pipi hozzászólására (») Ápr 6, 2015 /
 
Köszi, akkor marad az általad felvázolt mechanikus materialista módszer.
(#) tomi52 válasza killbill hozzászólására (») Ápr 12, 2015 /
 
Múltkor azt hiszem, nem fogalmaztam meg jól a kérdésem. Az XC8-ban szeretném azt elérni, hogy paraméterként át tudjam adni bármelyik regisztert, vagy annak csak egy bitjét. A bitenkénti elérést ismeri az XC8, csak nem tudom, hogyan kéne ezt paraméterként átvenni az eljárásban. (Mint említettem, nem vagyok kellőképpen otthon a C-ben.)
  1. void abcd(??? REGxxx)
  2. {
  3.   REGxxx = 0; // milyen típust kellene megadnom,
  4.               // hogy ez is arra forduljon: TRISBbits.TRISB0 = 0;
  5.               // egyáltalán, van-e erre mód?
  6. }
  7.  
  8. void main(void)
  9. ......
  10.   TRISBbits.TRISB0 = 0; // ez működik, próbáltam
  11. ......
  12.   abcd(TRISBbits.TRISB0); // ezt is elfogadja
  13. .........
(#) foxi63 válasza tomi52 hozzászólására (») Ápr 12, 2015 /
 
Szia!
Baj van, mert van 8 bites regiszter és van 16 bites is.
Ha 8 bitessel akarsz foglalkozni, akkor egy unsigned char* tipusú mutatóval kell átadni a konkrét regisztert, ha 16 bitessel akkor unsigned int* tipusúval.
  1. void abcd(unsigned char* reg)
  2. {
  3.         *reg=0x55;
  4. }
  5.  
  6. void main()
  7. {
  8.         abcd((unsigned char*)TRISB);
  9. }
(#) killbill válasza tomi52 hozzászólására (») Ápr 12, 2015 /
 
A C-ben a legkisebb megcimezheto egyseg a char, ezert egy regiszter 1 bitjenek a cimet kozvetlenul nem tudod atadni egy fuggvenynek.
Ezt csak ugy tudod megoldani, hogy atadod a regiszter cimet es atadsz melle egy maszkot vagy bitpoziciot:
  1. // a reg_addr-ban megadott regiszter valamely bitjet 1-be allitja
  2. void abcd(volatile unsigned char *reg_addr, unsigned char bitpos)
  3. {
  4.   *reg_addr |= 1 << bitpos;
  5. }
  6.  
  7. void main(void)
  8. {
  9.   TRISBbits.TRISB3 = 1;  // helyett
  10.   abcd(&TRISB, 3);       // irhatod ezt is
  11. }

Ehhez hozzatartozik az is, hogy a fenti megoldas hasznalataval a forditott assembly kod nem egy egyutasitasos bitset vagy bitclr utasitast fog eredmenyezni, hanem tobb utasitasbol fog allni a muvelet, amit ha kozben megszakit egy interrupt es az is akarja modositani az eppen modositott regisztert, akkor abbol baj lehet.
Következő: »»   110 / 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