Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   116 / 153
(#) killbill válasza don_peter hozzászólására (») Okt 31, 2015 /
 
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.
(#) killbill válasza foxi63 hozzászólására (») Okt 31, 2015 /
 
Idézet:
„talán az stdio.h-ban van sztringmásoló függvény strcpy(... ....)”
string.h-ban van, de az másolja a string végén levő nullát is.
A hozzászólás módosítva: Okt 31, 2015
(#) foxi63 válasza killbill hozzászólására (») 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.
(#) killbill válasza foxi63 hozzászólására (») Okt 31, 2015 /
 
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?
(#) don_peter válasza killbill hozzászólására (») Okt 31, 2015 /
 
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..
(#) killbill válasza don_peter hozzászólására (») Okt 31, 2015 /
 
Idézet:
„Köszi, utána néztem:”
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.
Idézet:
„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.”
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.

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:
„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.”
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ó.
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.
(#) don_peter válasza killbill hozzászólására (») Okt 31, 2015 /
 
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:
  1. void text_to_array(unsigned char *str)

Ennek így is kellene működnie, még sem működik.
(#) Hp41C válasza don_peter hozzászólására (») Okt 31, 2015 /
 
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.”
(#) killbill válasza don_peter hozzászólására (») Okt 31, 2015 /
 
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.
(#) don_peter válasza killbill hozzászólására (») Okt 31, 2015 /
 
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.
(#) benjami válasza don_peter hozzászólására (») Okt 31, 2015 /
 
Ha belenézel a könyvtári string.h -ba, ott külön függvényeket találsz a ROM és a RAM területről történő másoláshoz:
strcpy: RAM -> RAM
strcpypgm2ram: ROM->RAM
strcpyram2pgm: RAM->ROM
memcpy: RAM -> RAM
memcpypgm2ram: ROM->RAM
memcpyram2pgm: RAM->ROM
(#) icserny válasza don_peter hozzászólására (») Okt 31, 2015 /
 
Így működnie kellene:

  1. void text_to_array(rom unsigned char *p){
  2.     unsigned char i=0;
  3.     char c;
  4.     while(c=p++){
  5.        TextBuffer[i++] = c;
  6.     }
  7. }
A hozzászólás módosítva: Okt 31, 2015
(#) don_peter hozzászólása 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
(#) killbill válasza benjami hozzászólására (») Okt 31, 2015 /
 
Azért arra nagyon kiváncsi vagyok, hogy a xxx->ROM függvények mégis mit csinálnak.
(#) icserny válasza killbill hozzászólására (») Nov 1, 2015 /
 
Erről elég terjedelmes diszkussziók találhatók a Microchip fórumán. Mindenesetre a memcpyram2pgm mélyén van egy
  1. tblwt     *+                  ; write & increment
(#) killbill válasza icserny hozzászólására (») Nov 1, 2015 /
 
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...
(#) icserny válasza killbill hozzászólására (») Nov 1, 2015 /
 
Idézet:
„Írja a const területet?”

Vannak ilyen élethelyzetek. Például a bootloader is rákényszerül...
(#) killbill válasza icserny hozzászólására (») Nov 1, 2015 /
 
A bootloader az applikacios flash-t irja, nem pedig maga alatt a const-ot. De amugy ertelek.
(#) Wezuv válasza killbill hozzászólására (») Nov 2, 2015 /
 
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.
(#) killbill válasza Wezuv hozzászólására (») Nov 2, 2015 /
 
Ez könnyen megy mikrocsip környezetben...
(#) benjami válasza killbill hozzászólására (») Nov 2, 2015 /
 
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
(#) Wezuv válasza killbill hozzászólására (») Nov 3, 2015 /
 
Igen...
A hozzászólás módosítva: Nov 3, 2015
(#) icserny válasza benjami hozzászólására (») 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.
(#) ativagyok hozzászólása Nov 3, 2015 /
 
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ő:
  1. x = adcresult;
  2. x = x * 5000/4096;

Második:
  1. x= adcresult * (5000/4096);


A változók:
  1. unsigned int adcresult;
  2. float x;
(#) Wezuv válasza ativagyok hozzászólására (») Nov 3, 2015 /
 
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
  1. x=(float) adcresult  *(5000.0/4096.0)
(#) killbill válasza ativagyok hozzászólására (») Nov 3, 2015 / 1
 
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
(#) killbill válasza Wezuv hozzászólására (») Nov 3, 2015 / 1
 
Idézet:
„A második esetben a fordító a két literált unsigned int-nek veszi (mert amivel szorzod, az)”
Először is, nem unsigned int-nek, hanem int-nek veszi a két konstansot. De akkor is
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
(#) ativagyok válasza killbill hozzászólására (») Nov 4, 2015 1 /
 
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.
(#) ativagyok hozzászólása Nov 4, 2015 /
 
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?

  1. float alpha=0.003354016 , beta=0.000256985, gamma=2.62013E-06, tmpfloat, rntc;
  2.  
  3. tmpfloat=1/(alpha+beta*(log(rntc))+gamma*pow(log(rntc),3));
(#) Kovidivi válasza ativagyok hozzászólására (») Nov 4, 2015 / 1
 
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.
Következő: »»   116 / 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