Fórum témák
» Több friss téma |
Sajnos itt az én tudományom véget is ér, ugyanis a C nyelvben nem létezik olyan kulcsszó, hogy "rom". Ez valami mikrocsip sajátosság. Az általam írt for()-os példában is csak lemásoltam tőled az "auto rom" részt, gondoltam, te tudod, hogy az mit jelent...
Ettől függetlenül a fenti függvényed teljesen hibátlan, pontosan ugyanazt kell csinálnia, akárhámnyszor is hívod meg. Ha egy függvényt meghívsz és az vissza is tért, akkor a stack rendben van. Javaslom, nézz utána, hogy mi is az a stack. Idézet: string.h-ban van, de az másolja a string végén levő nullát is. „talán az stdio.h-ban van sztringmásoló függvény strcpy(... ....)” A hozzászólás módosítva: Okt 31, 2015
A flashprogram területre elhelyezett adatokat kell érteni ROM alatt.
ezért "egyedi mikrochip" a kiolvasása is egész máshogy megy, mint a ram kiolvasás, nem kompatibilis egymással.
Gondoltam, hogy erre való. Viszont ha nem kompatibils egymással a kettő, akkor felmerül a kérdés, hogy pl. az strcpy() honnan tudja, hogy a forrás az rom vagy ram?
Köszi, utána néztem:
Idézet: „A mikroprocesszoros rendszerek ún. stackmemóriát használnak a szubrutin-hívásoknál, megszakításoknál a programmemória visszatérési értékeinek tárolására. A verem-memória sok esetben nem független memóriaterület, hanem csak a belső memóriában lefoglalt terület. A hatékony működés érdekében azonban hasznos, ha a memóriától független hardveres stacket alakítanak ki. Ekkor azonban figyelembe kell vennünk azt a hátrányos következményt, hogy a stackmemória mélysége véges lesz! A külső memóriával rendelkező mikrovezérlőknél a külső és belső memóriában is elhelyezkedhet a stackterület.” De sajnos még ha jó is a rutinom, akkor sem működik rendesen. 3. meghívásnál elszáll az egész, mint ha beragadna a futás. A ROM utasítást akkor, használom amikor a egy tömb túl nagy, illetve ha az abban előre megadott adatokat nem akarom változtatni. Ezeknél általában nem fér bele a PIC adatmemóriájába, vagy ha bele is férne a nagy mérete miatt lefoglalná a nagy részét. Ekkor jön a ROM utasítás a maga elöljáróival: const rom static unsigned char ..., ezzel a programmemóriába tárolja le az adatokat, amelyeket utána ki lehet olvasni, de változtatni rajtuk nem lehet. Nekem amúgy egy sima char is megtenné, de azzal nem működik a dolog akár hogy kényszerítem.. Idézet: Az idézett szövegben a hardveres stackről szóló rész csak kábítás, a világon senki nem használ HW stack-et a low end mikrocsip mikrokontrollereken kívül. Egyébként pedig a kifejezések helyesen: stack (memória nélkül) vagy magyarított változatban verem, esetleg veremtár.„Köszi, utána néztem:” Idézet: A const eleve erre való, rom nélkül is. Csak PIC-en (és AVR-en) nem elegendő, mert nem tudja ugyanúgy (ugyanolyan utasítással) olvasni a RAM-ot és a ROM-ot a processzor. Ezért egy rom mutató és egy ram mutató által mutatott adat felolvasásához más assembly utasítást kell. Ez viszont azt jelenti, hogy tudnia kell a fordítónak, hogy az adott művelet rom vagy ram mutatóval történik. Tehát meg kell határozni előre. De ez elég komoly megkötés programozás közben.„A ROM utasítást akkor, használom amikor a egy tömb túl nagy, illetve ha az abban előre megadott adatokat nem akarom változtatni.” Például annak, hogy "szoveg" a típusa const char *. És valószínüleg a RAM-ban is megvan a "szoveg", nem csak a flash-ban. Ez egy sajátossága a Harvard arhitektúrás processzoroknak, ami kevés RAM-mal párosítva nem igazan C barát dolog. Ennek orvoslására születnek a rom és társai, szabványoktól eltérő dolgok, de igazából jó megoldás nincs. Idézet: A kérdés az, hogy hogyan lehet kiolvasni őket. Kell-e tudnia egy meghívott függvénynek, hogy egy pointer rom vagy nem rom? Valószínüleg kell, mert különben nem is létezne ez a kulcsszó.„Ekkor jön a ROM utasítás a maga elöljáróival: const rom static unsigned char ..., ezzel a programmemóriába tárolja le az adatokat, amelyeket utána ki lehet olvasni, de változtatni rajtuk nem lehet.” Gondoltál már arra, hogy elolvasd a C fordítód leírását ezzel kapcsolatban? Biztosan le van ez írva valahol. Sokkal egyszerübb ott megnézni, mint találgatni, kisérletezni.
Igen nézegettem és meg is van a leírás, de angolból nem vagyok erős, így az értése és az elolvasása számomra közt nagy a különbség.
Ha valamit ROM-ban tárolok akkor a meghívásnál fel kell tüntetnem honnak akarom az adatot kiolvasni. Tehát a rutinomba is úgy kell hivatkoznom rá. Amit nem értek, az az, hogy ha semmi mást nem adok meg csak azt, hogy unsigned char, miért nem másolja át az adatokat a tömbbe. Tehát így:
Ennek így is kellene működnie, még sem működik.
Olvasgasd a C10 felhasználói kézikönyvét (hlpC18ug.chm):
Idézet: „String Constants The primary use of data located in program memory is for static strings. In keeping with this, MPLAB C18 automatically places all string constants in program memory. This type of a string constant is "array of char located in program memory", (const rom char []). The .stringtable section is a romdata (see "#pragma sectiontype") section that contains all constant strings. For example, the string "hello" in the following would be located in the .stringtable section: strcmppgm2ram (Foo, "hello"); Due to the fact that constant strings are kept in program memory, there are multiple versions of the standard functions that deal with strings. For example, the strcpy function has four variants, allowing the copying of a string to and from data and program memory: /* * Copy string s2 in data memory to string s1 in data memory */ char *strcpy (auto char *s1, auto const char *s2); /* * Copy string s2 in program memory to string s1 in data * memory */ char *strcpypgm2ram (auto char *s1, auto const rom char *s2); /* * Copy string s2 in data memory to string s1 in program * memory */ rom char *strcpyram2pgm (auto rom char *s1, auto const char *s2); /* * Copy string s2 in program memory to string s1 in program * memory */ rom char *strcpypgm2pgm (auto rom char *s1, auto const rom char *s2); When using MPLAB C18, a string table in program memory can be declared as: rom const char table[][20] = { "string 1", "string 2", "string 3", "string 4" }; rom const char *rom table2[] = { "string 1", "string 2", "string 3", "string 4" }; The declaration of table declares an array of four strings that are each 20 characters long, and so takes 80 bytes of program memory. table2 is declared as an array of pointers to program memory. The rom qualifier after the * places the array of pointers in program memory as well. All of the strings in table2 are 9 bytes long, and the array is four elements long, so table2 takes (9*4+4*2) = 44 bytes of program memory. Accesses to table2 may be less efficient than accesses to table, however, because of the additional level of indirection required by the pointer. An important consequence of the separate address spaces for MPLAB C18 is that pointers to data in program memory and pointers to data in data memory are not compatible. Two pointer types are not compatible unless they point to objects of compatible types and the objects they point to are located in the same address space. For example, a pointer to a string in program memory and a pointer to a string in data memory are not compatible because they refer to different address spaces.”
Pontosan mit nem másol? A fenti példádban csak olyan stringet adhatsz át a text_to_array függvénynek, ami nem rom-nak van deklarálva. Mivel a sima "szoveg" a C18 esetében const rom char *-ként keletkezik, ezért a függvényed nem tud vele mit csinalni.
Igen, pont ez a bajom.
Idézet: „Mivel a sima "szoveg" a C18 esetében const rom char *-ként keletkezik, ezért a függvényed nem tud vele mit csinalni.” Majd megnézem azt amit Hp41C idézett. Hátha azzal jutok valahová.. Egyelőre a sprintf(valtozo, "szoveg") teszi a dolgát rendesen.
Így működnie kellene:
A hozzászólás módosítva: Okt 31, 2015
Köszi srácok.
Úgy fest nem a programom volt rossz, hanem a kijelző memóriájával volt gondom. Kiírásnál valami szemét került ugyan abba a sorba, és ezért volt hibás a kiirás. Ezt javítva szépen kiírja a szöveget a kijelzőre, és 2kb-ot spórolok vele. Viszont az sprintf()-nél a különböző adattípusokat könnyedén lehet vegyíteni, míg a saját rutinom lehet gyorsabb, de sokkal több lépésből kell megoldanom ugyan ezt. Egyelőre maradok a sprintf()-nél és majd meglátom, mi lesz, bár a float-nál úgy is konvertálnom kell, szóval szívás mindenképp ![]()
Azért arra nagyon kiváncsi vagyok, hogy a xxx->ROM függvények mégis mit csinálnak.
Erről elég terjedelmes diszkussziók találhatók a Microchip fórumán. Mindenesetre a memcpyram2pgm mélyén van egy
Ok, de ez mire jó? Írja a const területet? Nem igazán C szemlélet. Ez jellemzően mikrocsip, Read Only Memory írása a standard C könyvtári függvények módosított változataival...
Idézet: „Írja a const területet?” Vannak ilyen élethelyzetek. Például a bootloader is rákényszerül...
A bootloader az applikacios flash-t irja, nem pedig maga alatt a const-ot. De amugy ertelek.
Idézet: „Nem igazán C szemlélet” Ilyenkor jön jól, ha valaki nem ismeri, vagy szándékosan nem használja a szemléletet. ![]()
Ez könnyen megy mikrocsip környezetben...
Azért a bootloader mellett még el tudom képzelni pl. grafikus kijelzőt használó program esetén grafika cserére, ahol fix kerek memóriacímen van a grafikus adat. A másik, hogy a másoló függvényben csak a tblwt *+ utasítás van benne, a flash törlést és írást már neked kell hozzábiggyeszteni. A PIC-ekben legtöbbször egyébként is inkább kényszerből a RAM szűkössége miatt használjuk a const illetve a ROM szavakat, nem pedig azért mert ki akarjuk zárni a módosítását.
Azt azért hozzáteszem, hogy még sosem használtam ezt. A hozzászólás módosítva: Nov 2, 2015
Igen...
A hozzászólás módosítva: Nov 3, 2015
Egy régi hozzászólásomban említettem már a FlashForth interpretert PIC18-hoz. Ez is tartalmaz futás közbeni flash módosítást, mert a felhasználó által beírt programsorokat itt tárolja.
Sziasztok!
Egy kezdő kérdés: Mi a különbség a kettő műveletsor között? A második módszerrel helytelen értéket kapok. Első:
Második:
A változók:
A második esetben a fordító a két literált unsigned int-nek veszi (mert amivel szorzod, az)
Ellenben az első esetben floatnak, mert átkonvertálod azzal, hogy egy float változóba töltöd és utána floattal végzed velük a műveletet. Azaz 5000/4096 = 1,220703125 (float), illetve =1 (unsigned int) Ha biztosra akarsz menni, így jó lesz
Több különbség is van. Az egyik, hogy az első esetben először szorzod x-et ötezerrel, majd az eredmenyt osztod 4096-tal. A második esetben előbb elosztod az ötezret 4096-tal, aminek az eredménye pontosan 1 lesz, és azzal szorzod adcresultot.
A hozzászólás módosítva: Nov 3, 2015
Idézet: Először is, nem unsigned int-nek, hanem int-nek veszi a két konstansot. De akkor is„A második esetben a fordító a két literált unsigned int-nek veszi (mert amivel szorzod, az)” int-nek venné, ha az adcresult float lenne, mert be van zárójelezve az osztás. Előbb számolja ki az (int 5000 / int 4096)-ot, és csak az eredményt (az 1-et) konvertálja float-ra. A te példádban a float cast-olas teljesen felesleges, mert a float konstansok miatt a szorzás float lesz, így az adcresult-ot automatikusan float-ra konvertálja. A hozzászólás módosítva: Nov 3, 2015
Köszönöm a segítséget, így már érthető, hogy a második esetben miért nem változott az eredmény.
![]()
Lenne egy újabb kérdésem:
Egy 10k-s NTC-vel szeretnék hőmérsékletet mérni a Steinhart-Hart függvénnyel. Az NTC feszültségét és ellenállását sikerült kiszámolni, de a hőmérséklet nem igazán akar kijönni. Az rntc eredménye 8.9E+03, ami helyesnek tűnik (8900 ohm). Elvileg a függvény eredménye a hőmérsékletet adná Kelvinben, esetemben viszont ennyi: 1.305102E+002. Mi lehet a gond? ![]()
Egyszerűbb, ha az NTC-t pontosan 100fokra melegíted, ellenállásosztóba bekötve feszültséget mérsz rajta, majd lehűtöd 0fokra, ismét mérsz, majd e két ponthoz arányosan kiszámítod a jelenlegi hőmérsékletet.
|
Bejelentkezés
Hirdetés |