Fórum témák
» Több friss téma |
Fórum » CCS PIC Compiler
Idézet: „A hiba az volt, hogy az összes sorosporton érkező utasítást egyetlen függvénnyel akartam lekezelni, és az kinőtte a szegmens lehetséges méretét.” Valoszinuleg linker scriptet kellene heggesztened ahhoz, hogy elkeruld a problemat - es ne megkeruld
Sziasztok!
30F4013-as dsPIC-cel szívok, azon belül is I2C-vel. Egy 24c04-es EEPROM a cél, amelynek lábai így vannak bekötve:1-GND,2-3-Vcc,4-GND,5-F2,6-F3,7-8-Vcc SDA és SCL 4.7kOhm-os ellenállással a Vcc-re felhúzva. Mindössze egy darab byte-ot akarok beírni és azt kiolvasni és kiküldeni RS232-re. #use rs232(UART2,baud=9600,parity=N,bits=8) #use i2c(Master, Slow, sda=PIN_F2, scl=PIN_F3, force_hw) . . while(1) { printf("OK!\n\t"); delay_ms(100); i2c_start(); i2c_write(0b10101100); // Device address i2c_write(1); // Byte address i2c_write(3); //data i2c_stop(); delay_ms(100); output_bit(PIN_D2,k); k=!k; i2c_start(); // Restart i2c_write(0b10101100); i2c_write(1); // Byte address i2c_start(); i2c_write(0b10101101); ertek=i2c_read(); // Now read from slave i2c_stop(); printf("ertek=%d ", ertek); ertek=99; } Ezek a sorok nem akarnak működni. Kétfajta hibajelenség van, attól függően hova adom meg az I2C lábait (gondolom, mikor HW-ben, vagy SW-ben használja az I2C-t). Az első, mikor leírtak szerint van minden, a soros porton -1 -et olvasok ki az ertek változóra. Mondjuk akkor is azt olvasok, ha lehúzom a buszról az EEPROM-ot. HW hiba lenne? Átnéztem már 100-szor legalább. Talán a 24c nincs jól bekötve? Szerintetek?
Lehet, hogy hülyeséget mondok, de ha így kötöd, be ?
PIC EEPROM --- A0 (1) GND --- A1 (2) GND --- A2 (3) GND --- VSS(4) GND PIN_F2 --- SDA(5) 2.2k +5V-ra PIN_F3 --- SCL(6) 2.2k +5V-ra --- WP (7) GND --- VCC(8) +5V A programrészletedben PIN_D2 a kimeneted, elöl viszont a PIN_F2-3-at adod meg...
Az adatlap szerint a 24c04 nem használja az a2,a1,a0 címvezetékeket. Viszont 512 bájtos, tehát legfelső címbitet az első bájban kell kiküldeni.
A cím első bájtja ennek megfelelően: Bináriasan: |1 | 0| 1 | 0 | 0 | 0 | b8 | r/w| ahol b8 a legmagasabb helyiértékű címbit, r/w pedig az olvasás/írás bit. Mintaprogramot is találsz hozzá a CCS-ben: PICC/Drivers/2404.c Idézet: „A programrészletedben PIN_D2 a kimeneted” Azzal szerintem csak jelezni próbálta a működést...
Szerintem:
ertek=i2c_read(0); kell a kiolvasásnál. A PICC/Drivers mappában vannak egyes eszközökre kezelő rutinok. (Ahogy azt icserny is írta )
Sziasztok!
Megvan mindkét hiba, azt hiszem. A HW-s I2C nem akar működni. Olyan szinten nem működik, hogy SDA vonal nem billeg (szókappal rámértem), ellentétben az SCL lábbal. Szerintem kipróbálok majd egy másik IC-t, mert valszeg elszállt az SDA láb. Viszont SW I2C szépen sikerült. Amit nem igazán értek benne, hogy beáll a program, ha nem kap visszajelzést a slave-től. Köszönöm a hozzászólásokat és a segítséget... Idézet: „Amit nem igazán értek benne, hogy beáll a program, ha nem kap visszajelzést a slave-től.” Valószínűleg a kész rutinban benne van, hogy várjon az ACK jelre. Aztán ha az nem jön, akkor bukott a dolog. Írd újra azt a rutint várakozás nélkül.
Hát arra most nem vállalkoznék. Egyébként én is arra gondolok, hogy nem kap visszajelzést, ACK-t. Bár szerintem azt is le kéne kezelni. Szerencse a HW-s I2C-vel nincs ilyen probléma.
Sziasztok!
Van-e valami ötletetek arra vonatkozóan, hogy hogyan lehet pontosan millisec-ben megmérni két esemény között eltelt időt külső óra IC használata nélkül? A feladat a következő: RF kommunikációban az adó kb 1500 ms-onként ad le egy karakter sorozatot. A vevő oldalán RDA megszakítással érzékeli, hogy érkezik jel az USART-ra, ha igen akkor ellenőrzi, hogy jó-e és a sorban beérkező jelekből összeállítja a karakter-sorozatot. Természetesen manchester kódolással dolgozom, de kíváncsi vagyok, hogy adott adásidő alatt hányszor jön be hiba nélkül a karakter sorozat. Ezért meg szereném mérni pontosan ms-ban, hogy két jó karakter sorozat kiírása között mennyi idő telik el. Így, ha pl. 10 percen keresztül figyelem a folyamatos adást, és feljegyzem egy változóban a min. és max. időértékeket, akkor már tudok arra következtetni, hogy milyen hibaaránnyal dolgozik a rendszer. Ezzel jó összehasonlítási alapom lesz, hogy ha pl. antennát módosítok, árnyékolom az elektronikát, stb. akkor rontottam, vagy javítottam a rendszeren. Tehát az alábbi programrészlet írja ki a hibátlan karakterkészletet és ebbe szeretném beépíteni az időmérést: while (TRUE) { restart_wdt(); if (data_avail) { data_avail = FALSE; printf(lcd_putc,"\fAz adat beerkezett!\n"); for (i = 0; i < 5; i++) { printf(lcd_putc,"%c",rx_buffer[i]); } } } Fontos, hogy a szükséges mérhető időhatár legalább 3000 ms legyen. Előre is köszi az ötleteket! >
Fogsz egy timert, és a megfelelő pillanatokban elindítod és megállítod. Ez utasításciklusokban megmondja neked, hogy mennyi idő telt el. Ha túl gyorsan lefut, akkor kapcsold be az előosztót hozzá.
Szerintem egyszerűbb megoldás az, ha állandóan fut egy timer (pl. 20 milliszekundumonként interruptot ad), s az interruptkor növelget egy (több bájtos) számlálót.
A program pedig minden érvényes adat beérkezésekor kiolvassa az időszámláló (mint stopper) értékét, és nullázza. Arra kell csak vigyázni, hogy a nullázás és a növelés ne gabalyodjon össze... (pl. a nullázás idejére le kell tiltani az interruptot)
Sziasztok!
Most egy eléggé kemény problémám van, legalább is már 2 napja kínlódok vele. Egy drót nélküli alkalmazásban a soros portról olvasok be adatokat egy INT_RDA megszakítási rutin segítségével. Több külső egységet kérdezek le egyiket a másik után, úgy, hogy megszólítom a külső egységet, és várom a visszajelzését a mért értékkel. Erre vár az RDA rutin amelyben megnézem, hogy a megfelelő külső egység válaszolt-e, és ha igaen akkor a lenti kódban látható data_avail változónak igaz értéket adok és ezzel térek vissza a megszakításból. Persze közben egy sztring-tömbben feljegyzem a többi adatát. Utána visszatérek az alábbi kódhoz: while(cikl<=3) { restart_wdt(); if (data_avail) { data_avail = FALSE; strncpy(szondakuld,rx_buffer,12); cikl++; } } A háromszori beolvasás az adatbiztonság miatt van. Eddig nincs is vele gondom, szépen csinálja. No, de mi van ha a hívott egység nem válaszol? akkor a végtelenségig várakoznom kell. Ezért úgy gondoltam, hogy a while ciklus kiértékelésbe berakok egy másik ciklusváltozót és szépen emelhgetem az értékét, ha nem jön adat és így egy idő után ki tudok lépni a ciklusból és hibajelzést tudok kiírni az illető egységhez. Valahogy így: while(cikl<=3 && timeout<5000) { restart_wdt(); if (data_avail) { data_avail = FALSE; strncpy(szondakuld,rx_buffer,12); cikl++; } else { timeout++; } } De sajnos ez a dolog nem működik, ugyanis a timeout változó valamiért a legelső pillanatban felveszi a max. értékét, tehát az 5000-et és már tovább is lépett a program, ki a ciklusból, tehát innentől kezdve akkor sem olvas be, ha egyébként lenne külső válasz. Mi lehet az oka, vagy mi módon leget ezt megcsinálni szerintetek? Már nem nagyon van ötletem, az az igazság... >>>
A timeout változódat megfelelő méretűre definiáltad (int16)?
Üdv!
Ahogyan én csináltam a timeout-os sorosporti vételt ccsben /konkrét kódot nem tudok mellékelni most/: 1) timer0 modult beállítottam, hogy meghatározott időközönként generáljon IT-t, emellett a megszakítások beállításai: global interrupt engedélyezve, timer0 tiltva. 2) A timer0-hoz tartozó IT rutin tartalma: timer0 visszaállítása, timeout változó növelése 3) a programban, ahol soros porti vételt kellett kezelni: enable_interrupts(int_rtcc); while(!sorosportiadatjott&&timeout timeout=0; azaz: első körben timer0 megszakítás engedélyezése, utána while ciklusban addig maradni, amíg nem jött soros porton adat, vagy el nem érte a timeout változó a timeout_value értéket, ezután timer0 megszakítás tiltása, majd timeout változó nullázása, hogy a következő hívásnál is megmaradjon az időzítés. A feltételt a while ciklusban remélem, hogy jól írtam most így fejből, nincs előttem a kód...ezzel a módszerrel nekem hibátlanul működött a timeout kezelés. Biztosan van ennél kevesebb hardvert használó megoldás is, vagy optimálisabb, nekem megfelelt így... Én a sorosporti kommunikációhoz általában az INT_RDA-n belül mindig egy állapotgépet definiálok, amivel a lehetséges üzeneteket detektálni tudom, nem kell letárolni az adatokat egy bufferben, így csak a lényegi adatokat ki lehet nyerni viszonylag minimális adatmemória felhasználásával /a szükséges adatok tárolásához szükséges, illetve 1-1 "állapotregiszter"/. üdv: GLaszlo>
Amit még megfigyeltem, hogy, ha nem rakom be a ciklusvizsgálathoz a timeout vizsgálatát, csak simán emelgetem belül az értékét, azt megcsinálja. Azonban, ha ott van a vizsgálatnál, akkor azonnal felveszi a vizsgálati határértéket. Ugyanez történik, ha az else ágban beleteszek egy értékvizsgálatot és ennek eredményeképpen a cikl változót beállítom 4-re, hogy a következő ciklus-kiértékeléskor lépjen tovább. Tehát
else { timeout++; if (timeout>5000) { cikl=4; } } ilyenkor az első ciklusban ráfut az else ágra, felveszi az 5000-es értéket, a cikl változót beállítja 4-re, és a következő while kiértékeléskor már ott is hagyta a ciklust és lép tovább...
Nem próbáltad valami másnak definiálni a timeout változót? Adjál neki pl. idolejart, mert lehetséges, hogy a timeout-ot valami más használja.
idolejar, lejar, varak... ezekkel mind kipróbáltam ugyanaz az eredmény
Nem fogjátok elhinni, mi volt a hiba!! Mindenki okulására, hogy milyen hisztis a CCS C... Amellett, hogy milyen jó compiler
Szóval a while feltétel szintaxisa while (varakozas<10000) { helyett while (varakozas < 10000) { hát ennyi... azóta megy rendesen. Ez került közel két napomba...
Na szép. Az ilyenek miatt útálom a CCS-t...
A while(1)-nél szerencsére nincs ilyen probléma.
Sőt,az IF-nél sem...
Azt hiszem, hozzá kell szoknunk, hogy minden ilyen feltételhez, műveleti jelhez, stb. kell tenni szóközt.
Potyo, véleményed és tapasztalatod szerint melyik a CCS-nél jobb C compiler? Mert, ha tutira jobb, akkor szívesen átszokom, a lényeg a minőség...
Ha 12F vagy 16F picről van szó, akkor szerintem a Hi-Tech C fordítóját érdemes használni. Írtam én is PS2-USB átalakítót CCS-ben, ma is az működik a billentyűzetemben, de emlékszem, hogy mennyi mindennel megszenvedtem, mire minden úgy működött, ahogy kellett. Nem azt mondom, hogy jobb vagy szebb a Hi-Tech fordítója, mert felhasználóbarátságban a CCS biztosan magasabb szinten van, de mi a fontos számunkra, a dizájnos felület, vagy a megbízhatóság, stabilitás? A Hi-Tech fordító sokkal közelebb van az ANSI C-hez, mint a CCS. Emellett nem próbálja elrejteni a hardvert, ami kezdetben ugyan jó dolognak tűnik, egy összetettebb feladatnál viszont akadállyá válik. A szabványhűség pedig akkor fontos, ha több fejlesztőeszközt használsz párhuzamosan, mert egyszerűen a hibalehetőségek számát csökkenti, ha valamely tipus mindegyikben ugyanazt jelenti, ugyanazok az alapértelmezett dolgok, stb.
Ha 18F-ről van szó, akkor egyértelműen a Microchip C18 fordítóját érdemes használni.
Én 18F-től felfele dolgozom, és megmondom őszintén a Microchip c18-al, ill. a többi Microchip fordítóval "szemeztem", de aztán leragadtam a CCS-nél. Minden esetre köszönöm, hogy megosztottad a tapasztalataidat, szerintem érdemes lesz - amint egy kis időm lesz kísérletezni - kipróbálnom a C18-at.
|
Bejelentkezés
Hirdetés |