Fórum témák
» Több friss téma |
Vagy lebegőpontos konstansokkal, és akkor automatikus a castolás:
tps_value = tps_ad_value * 100.0 / 1024.0;
Azt gyanitom, hogy az optimalizalas viccel meg Teged, ugyanis a szorzas es osztas azonos precedenciaval rendelkezik, annak (ill annak a resznek) jonak kell lennie!
Itt egy pelda, leforditottam gcc-vel a peldadat O3 -as optimalizacioval. Ha jol megnezed, akkor a printf jol irja ki az eredmenyt, megis 0 a tmp_float valtozod erteke -- A fordito ugy dontott nem kell az erteket a valtozoba vissza irnia mivel ugyis csak egy helyen hasznalom fel...
Megjegyzes: a tps_value-t elobb float-ta castolom, hogy utana az osztasnal a maradekot mar ne veszitse el... Amugy 5.0000-t irna ki, de az sem nulla! UI: PIC32 is gcc alapu forditot hasznal, ugyhogy ezert mertem sima gcc-vel tesztelni a problemat amit felvetettel... UI2: Azt elfelejtettem irni, hogy termeszetesen -O0 -val, azaz optimalizacio nelkul a valtozo erteket nyomon tudom kovetni a debuggerrel... Idézet: „Azt gyanitom, hogy az optimalizalas viccel meg Teged, ugyanis a szorzas es osztas azonos precedenciaval rendelkezik, annak (ill annak a resznek) jonak kell lennie!” Ez így van. A konstans kifejezéseket fordítási időben kiértékeli akkor is ha egyébként ki van kapcsolva az optimalizáció. Továbbá az azonos precedenciájú műveletek esetén a konkrét kiértékelési sorrend implementáció függő, az AnsiC kompatibilis fordítók átrendezhetik ezeket, ezért soha ne bizzunk abban hogy az a = b*c*d; kifejezésből b*c -t értékeli ki először. Ha konkrét kiértékelési sorrendet akarunk előírni bontsuk szét a kifejezést több utasításra, (lsd. fenti hozzászólások).
A fentiekhez hasonló csapdák elkerülése érdekében érdemes ebbe beleolvasni:
BME C referencia
Részben igazad van, részben nincs.
Az igaz, hogy a kiértékelés sorrendjét szabadon választhatja meg a fordító, de ez csak függényeknél, a ++/-- operátoroknál, valamint az értékadás operátor, mint kifejezés használatakor lényeges, mivel ezeknek műveleteknek vannak "mellékhatásaik". Annyi a következmény, hogy a mellékhatások egymáshoz képesti, ill. az egész kifejezés kiértékeléséhez képesti sorrendje nem definiált. Abban viszont nincs igazad, hogy az a = b*c*d kifejezést a fordító szabadon "átrajzolhatja" úgy optimalizálás címén, hogy ezzel a kifejezés valódi értéktartományát lecsökkentse. Jelen esetben pl. a *600/1024-at nem helyettesítheti *0-val, mondván hogy előbb az 600/1024-et értékeljük ki integerként, és az nullát ad... Ilyet semelyik fordító nem tesz.
Igazam van, olvasd át légyszíves a mellékelt linkben az 1. megjegyzést.
De be is másolom. Idézet: „1. Megjegyzés: a kétoperandusú *, +, &, ^ és az | operátorok asszociatívak. Ha egy kifejezésben azonos szinten több azonos asszociatív operátor szerepel, akkor a fordítónak jogában áll a kiértékelési sorrendet tetszőlegesen megválasztani. Ez - a részkifejezések mellékhatásai miatt - kihathat az eredmény értékére is, ezért kerülendők az olyan kifejezések, amelyek nem definit kiértékelési sorrendtől függenek. Például az a++ + b[a] kifejezésben a b tömb indexe attól függ, hogy az első vagy a második tag kiértékelése történik előbb, azaz az indexeléshez az eredeti vagy a megnövelt a-t használjuk. Ugyanez a helyzet áll fenn a függvényhívások paramétereinél, ugyanis ezek kiértékelése sem kötött sorrendű. Például a fugg(i++, a[i]) gépfüggően választja meg adott i érték mellett az átadandó tömbelemet.”
Ami pedig a konstans kifejezések kiértékelését illeti, csak ismételni tudom magam, az a preprocesszor dolga, fordítási időben. Legalábbis C, C++ esetén.
Bocs, de nem értem a kérdést.
Gondolom akor az asszociativitás buktatóit már tisztáztuk, ha nekem nem hiszel ott a BME jegyzet, erről nem érdemes tovább vitázni.
Azt hiszem értem mire gondolsz.
A felvetett konkrét esetben, tényleg nem a prepocesszor optimalizál, mert kifejezés belsejében van. Ezt a compiler értékeli ki, és ha észreveszi hogyez egy konstans részkifejezés amit az asszociativitási szabályok alapján kiértékelhet, megteszi. Ez elképzelhető hogy compiler függő. Arra akartam rávilágítani, hogy nem érdemes olyan kódot írni ahol ez a fordítóra van bizva. Ennek elkerülésére az előzőekben több tippet is adtunk.
A kérdés arra irányult, hogy honnan veszed, hogy a preprocesszor bármiféle számot/konstans értéket próbálna kiértékelni. Merthogy a preprocesszor kimenetében az összes konstanst meg fogod találni, azokon semmiféle műveletet nem végez. A preprocesszor string behelyettesítést végez csak, nem értelmezi és nem olvasgatja a C kódot. Simán lehet pl. Pascal vagy Basic forrásra is használni...
A BME-s jegyzet ugyan nem fogalmaz elég pontosan, de abból sem jön le az az értelmezés, amit Te bele próbálsz érteni. Más dolog a részkifejezések kiértékelésének, előállításának sorrendje (ez a mellékhatások miatt lényeges), és más dolog a végeredmény kiszámolása. A C szabvány asszociatív műveleteknél annyiban engedi meg a végeredmény számolása szempontjából a sorrend felcserélését, amennyiben az nem változtatja meg az eredményt. Ez integer összeadás, kivonás, szorzás esetén gyakorlatilag bármikor igaz, viszont az integer osztásnál már nem. A dologhoz hozzátartozik, hogy a K&R-féle kváziszabvány elméletileg ezt is megengedte.
A prepocesszor kérdését közben megválaszoltam, a konkrét példára valóban nem vonatkozik.
Igazad van, ez a / operátorra nem vonatkozik, elnéztem a kifejezést, akkor ez mégis csak valami optimalizálási probléma lehet. Én is a K&R könyvre emlékeztem. Kipróbáltam, a Microchip C30 (v3_31) fordító például jól kezeli, tiéd a pont.
Na sikerült a problémát megoldani.
Köszönöm mindenkinek. Most már jól számol. Van valakinek valamilyen képlete a lineáris interpolációra? Az én változatom egy egy dimenziós tömbnél jól működik, viszont egy 2 dimenziósnál már nem.
Például: Szeretnék visszatérni a tömb x irányban 0,3 és y irányban a 0,6-es értékével. Egy dimenziósnál így csinálom (x irányban): 0,3 * 30 = 9 (1-0,3) * 10 = 7 Az interpolációs eredményem: 9+7 = 16
PIC32-nél hogyan működnek a megszakítások?
IFSx regiszterben pl. melyik a timer1 flagje? Valaki le tudná írni a lényegét, mert nekem nagyon zavaros?
Ez a PIC32 sem olyan már, mint a régi 8 bitesek.
Letöltöttem a megszakítás fejezetet is, mert az adott PIC adatlapjában csak megemlítik a megszakítást. Azt tanulmányozva nem találtam meg a kérdésemre a választ. Ezután újra megnyitottam a PIC32 adatlapját, és ott benne volt, hogy melyik bit is a megszakítás flag. Ennek ellenére még mindig nem látom át, hogyan is működik a megszakítás. Még egy egyszerű kérdés. Hogyan kell ellenőrizni egy adot bitet c-ben? if(IFS0.4) nem működik.
A header file-t ha megnézed,
Akkor látod, hogy IFS0bits.T1IF = 0; például.
Közben egy csomó dologra rájöttem.
Végre működik a timer megszakítás. Kipróbáltam együtt a timer megszakítást és a portváltozás megszakítást. Nem mindig úgy működött, ahogyan szerettem volna. Ezután visszatöltöttem a gyári mintaprogramot, ami 2 LED-et villogtat, az egyiket a főprogramban nyomógombra, a másikat pedig megszakításból a másik nyomógombra. Az érdekes az az, hogy a gyári program is minden 10. gombnyomásnál meghülyül, nem vált át a LED, vagy világítva marad, ha már a gomb nincs is nyomva. Kipróbáltam egy másik nyomógombon is, ugyan az a jelenség Ez azért gáz, hogy a gyári programmal sem működik rendesen én meg már mindent átnyálaztam a saját progimban. Mi lehet az oka annak, hogy nem mindig lép be a megszakításba (a gyári program sem)?
Nem a nyomógombok pergése zavar meg téged?
Kipróbálom, hogy várok 100ms-ot a megszakításban.
Ennek ellenére akkor is működnie kellene, max a gombnyomásra többször kellene belépnie a megszakításba, szerintem. Idézet: „ogy várok 100ms-ot a megszakításban.” Ne próbáld ki. Megszakításban nem várunk, pláne nem 0.1 másodpercet. Pergésmentesíteni nem így kell. Kell csinálni egy 1ms-os timert, és nézni minden megszakításnál a gomb állapotát. Ha legalább x alkalommal ugyanaz volt a gomb állása, akkor a gomb beállt. Az x-nek olyan 5-8-at érdemes választani.
Most már hülyét kapok.
A prellegés csak egy dolog. Az miért van, hogy megnyomom a gombot, és a 32bites timer megáll. Megnyomom a pic32 starterkit-en az SW1-et. A hozzá tartozó LED1 bekapcsol, és bekapcsolva marad azután is, hogy elengedem a nyomógombot. A LED2 villogása ilyenkor megáll. Ennek nem szabadna bekövetkezni, mert a timer megszakításból megy. Ha megnyomom újra a gombot, akkor a LED1 kialszik, és a LED2 újra elkezd villogni. Olyan, mintha megállna a program futása, amikor a SW1-et megnyomom.
En nem ertek a 32 biteshez, de miert kulonbozokeppen billegteted a ket LED-edet? Az egyik esetben az INV-el, a masikban meg manualisan port firkalasokkal. Nyilvan akorul tortenik valami gubanc aminek a mellekhatasa, pl hogy a LAT-bol nem kerulnek at a modositasok a port-ba...
Az probléma lehet, hogy a main függvény a LAT regisztert tekergeti, eközben az interrupt megérkezik, és az ISR-ben ugyanazt a regisztert tekergetjük.
A LATxbits használata ugyanis a következő kódot fogja generálni: LATx = LATx | konstans vagy LATx = LATx & ~konstans. Ha a LATx kiolvasása és az eredmény visszaírása között jön az interrupt, akkor minden változtatás el fog veszni a visszaíráskor, amit az interrupt rutin csinált. LATxSET, LATxCLR regisztereket kéne használni a main-ben.
Érdekes, hogy ma már nem csinálta, azaz a program úgy futott, ahogy kell.
Szerintem a KIT + MplabX + Windows páros meghülyült. Ma elindítottam a gépet és a tegnapi program gond nélkül működik. Fura volt, hogy tegnap a debug LED is világított, holott a debug funkció nem volt bekapcsolva. Ma már a debug LED sem ment, most már az is csak akkor világít, ha debugolok. Azért köszönöm. Idézet: „Érdekes, hogy ma már nem csinálta, azaz a program úgy futott, ahogy kell.” Ebben semmi érdekes nincs. Kritikus versenyhelyzet a fogalom neve. Attól függ az eredmény, hogy éppen sikerül-e a interrupt-nak pont a LAT művelet közben érkeznie = totál véletlenszerű lesz a kimenetel. A programod nem javult meg, csak most éppen nem érzékeled, hogy rossz. Nem kell félni, majd a legváratlanabb időpontokban pont nem fog jól működni.
Kicsit olvasgattam utana, igazad lehet! Nem tudtam, hogy ezek a PIC32-ben mar nem atomikus muveletek. Valoban a SET es CLR hasznalata lenne celszeru es egy jo megoldas ide.
Egy olyan kérdésem van még:
Mi a szintaktikája C nyelvben, ha van több tömböm és írok egy általános függvényt, akkor hogyan tudom neki a tömböt átadni. Itt egy egyszerű példa: Szeretném, ha a függvénynek azt is megmondhatnám, hogy melyik tömbből vegye az adatot.
|
Bejelentkezés
Hirdetés |