textový string v XC8
Moderátor: Moderátoři
textový string v XC8
Ahoj, začínám s programováním PIC kontrolérů. Zkouším v MPLAB X v komp. XC8 napsat ovladač pro SPI display. Vše mi funguje do chvíle, kdy chci text uzavřený uvozovkami prohnat funkcí.
Pokud má kod tuto formu, vše funguje perfektně:
(uvádím pouze výsek kodu)
writetext (char text[])
{
...................
}
.
.
.
char text[];
text [0] = 'A';
text [1] = 'H';
text [2] = 'O';
text [3] = 'J';
text [4] = '/n';
writetext (text);
... ale jakmile to chci zjednodušit, abych nemusel jak trubka vypisovat každé písmenko takže takto:
writetext (char text[])
{
...................
}
.
.
.
char text[] = "AHOJ/n";
writetext (text);
tak mi kompilér nezahlásí žádnou chybu, ale po nahrátí hex do picu se pic kousne, tedy spíš vůbec nenastartuje...
Hledám už pár dní kde dělám chybu, ale marně.
Nemáte někdo zkušenost?
Díky moc...
Pokud má kod tuto formu, vše funguje perfektně:
(uvádím pouze výsek kodu)
writetext (char text[])
{
...................
}
.
.
.
char text[];
text [0] = 'A';
text [1] = 'H';
text [2] = 'O';
text [3] = 'J';
text [4] = '/n';
writetext (text);
... ale jakmile to chci zjednodušit, abych nemusel jak trubka vypisovat každé písmenko takže takto:
writetext (char text[])
{
...................
}
.
.
.
char text[] = "AHOJ/n";
writetext (text);
tak mi kompilér nezahlásí žádnou chybu, ale po nahrátí hex do picu se pic kousne, tedy spíš vůbec nenastartuje...
Hledám už pár dní kde dělám chybu, ale marně.
Nemáte někdo zkušenost?
Díky moc...
Ahoj Milo, dik za odpověď...
Funkce writetxt rozebira na jednotliva pismena text, pismena prevadi na pixely a posila prez spi do displeje. Ono mi to funguje, ale pouze pokud to zadam polopatě. Tu nulu jsem zkoušel a nefunguje to, ani když zadam přesný počet znaků. Kompiler nehlasi žádnou chybu ani warning, přeloží to do souboru hex, ale ten když nahraju do picu tak se vubec nespusti ani inicializace displeje, která je před samotným příkazem writetxt na začátku main(); No asi mi nezbude než to zadávat po jednom písmenku![Rolling Eyes :roll:](./images/smilies/icon_rolleyes.gif)
Funkce writetxt rozebira na jednotliva pismena text, pismena prevadi na pixely a posila prez spi do displeje. Ono mi to funguje, ale pouze pokud to zadam polopatě. Tu nulu jsem zkoušel a nefunguje to, ani když zadam přesný počet znaků. Kompiler nehlasi žádnou chybu ani warning, přeloží to do souboru hex, ale ten když nahraju do picu tak se vubec nespusti ani inicializace displeje, která je před samotným příkazem writetxt na začátku main(); No asi mi nezbude než to zadávat po jednom písmenku
![Rolling Eyes :roll:](./images/smilies/icon_rolleyes.gif)
Jj, přesně tak, pokud použiju text "takhle" v jakykoli podobě tak to nefunguje a pokud ho rozeberu 't' 'a' 'k' 'h' 'l' 'e' postupně tak to funguje...
Kód: Vybrat vše
void writetxt (char text[],char size, unsigned int x1,unsigned int y1){
colmod16();
switch (size){
case 1:
frame(x1,319,y1,y1+7);
break;
case 2:
frame(x1,319,y1,y1+15);
break;
case 3:
frame(x1,319,y1,y1+23);
break;
case 4:
frame(x1,319,y1,y1+31);
break;
case 10:
frame(x1,319,y1,y1+79);
break;
}
data();
unsigned char byte1; // prvni byte ze znaku (u "_" je to 00000001)
unsigned char byte2; // druhy byte ze znaku
unsigned char byte3; // treti byte ze znaku
unsigned char byte4; // ctvrty byte ze znaku
unsigned char byte5; // paty byte ze znaku
unsigned char b1;
unsigned char bit0;
unsigned char bit1;
unsigned char bit2;
unsigned char bit3;
unsigned char bit4;
unsigned char bit5;
unsigned char bit6;
unsigned char bit7;
for (long i2=0;i2 < strlen(text);i2++){
switch (text[i2]){
// CISLOVKY
case '0':
byte1 = 0x3E; byte2 = 0x51; byte3 = 0x49; byte4 = 0x45; byte5 = 0x3E;
break;
case '1':
byte1 = 0x00; byte2 = 0x42; byte3 = 0x7F; byte4 = 0x40; byte5 = 0x00; //0x00, 0x42, 0x7F, 0x40, 0x00
break;
case '2':
byte1 = 0x42; byte2 = 0x61; byte3 = 0x51; byte4 = 0x49; byte5 = 0x46; //0x42, 0x61, 0x51, 0x49, 0x46
break;
case '3':
byte1 = 0x21; byte2 = 0x41; byte3 = 0x45; byte4 = 0x4B; byte5 = 0x31; //0x21, 0x41, 0x45, 0x4B, 0x31
break;
case '4':
byte1 = 0x18; byte2 = 0x14; byte3 = 0x12; byte4 = 0x7F; byte5 = 0x10; //0x18, 0x14, 0x12, 0x7F, 0x10
break;
case '5':
byte1 = 0x27; byte2 = 0x45; byte3 = 0x45; byte4 = 0x45; byte5 = 0x39; //0x27, 0x45, 0x45, 0x45, 0x39
break;
case '6':
byte1 = 0x3C; byte2 = 0x4A; byte3 = 0x49; byte4 = 0x49; byte5 = 0x30; //0x3C, 0x4A, 0x49, 0x49, 0x30
break;
case '7':
byte1 = 0x01; byte2 = 0x71; byte3 = 0x09; byte4 = 0x05; byte5 = 0x03; //0x01, 0x71, 0x09, 0x05, 0x03
break;
case '8':
byte1 = 0x36; byte2 = 0x49; byte3 = 0x49; byte4 = 0x49; byte5 = 0x36; //0x36, 0x49, 0x49, 0x49, 0x36
break;
case '9':
byte1 = 0x06; byte2 = 0x49; byte3 = 0x49; byte4 = 0x29; byte5 = 0x1E; //0x06, 0x49, 0x49, 0x29, 0x1E
break;
// VELKA PISMENA
case 'A':
byte1 = 0x7E; byte2 = 0x09; byte3 = 0x09; byte4 = 0x09; byte5 = 0x7E; //0x7E, 0x09, 0x09, 0x09, 0x7E
break;
case 'B':
byte1 = 0x7F; byte2 = 0x49; byte3 = 0x49; byte4 = 0x49; byte5 = 0x36; //0x7F, 0x49, 0x49, 0x49, 0x36
break;
case 'C':
byte1 = 0x3E; byte2 = 0x41; byte3 = 0x41; byte4 = 0x41; byte5 = 0x22; //0x3E, 0x41, 0x41, 0x41, 0x22
break;
case 'D':
byte1 = 0x7F; byte2 = 0x41; byte3 = 0x41; byte4 = 0x41; byte5 = 0x3E; //0x7F, 0x41, 0x41, 0x41, 0x3E
break;
case 'E':
byte1 = 0x7F; byte2 = 0x49; byte3 = 0x49; byte4 = 0x41; byte5 = 0x41; //0x7F, 0x49, 0x49, 0x41, 0x41
break;
case 'F':
byte1 = 0x7F; byte2 = 0x09; byte3 = 0x09; byte4 = 0x01; byte5 = 0x01; //0x7F, 0x09, 0x09, 0x01, 0x01
break;
case 'G':
byte1 = 0x3E; byte2 = 0x41; byte3 = 0x49; byte4 = 0x49; byte5 = 0x3A; //0x3E, 0x41, 0x49, 0x49, 0x3A
break;
case 'H':
byte1 = 0x7F; byte2 = 0x08; byte3 = 0x08; byte4 = 0x08; byte5 = 0x7F; //0x7F, 0x08, 0x08, 0x08, 0x7F
break;
case 'I':
byte1 = 0x00; byte2 = 0x41; byte3 = 0x7F; byte4 = 0x41; byte5 = 0x00; //0x00, 0x41, 0x7F, 0x41, 0x00
break;
case 'J':
byte1 = 0x31; byte2 = 0x41; byte3 = 0x41; byte4 = 0x41; byte5 = 0x3F; //0x31, 0x41, 0x41, 0x41, 0x3F
break;
case 'K':
byte1 = 0x7F; byte2 = 0x08; byte3 = 0x14; byte4 = 0x22; byte5 = 0x41; //0x7F, 0x08, 0x14, 0x22, 0x41
break;
case 'L':
byte1 = 0x7F; byte2 = 0x40; byte3 = 0x40; byte4 = 0x40; byte5 = 0x40; //0x7F, 0x40, 0x40, 0x40, 0x40
break;
case 'M':
byte1 = 0x7F; byte2 = 0x02; byte3 = 0x04; byte4 = 0x02; byte5 = 0x7F; //0x7F, 0x02, 0x04, 0x02, 0x7F
break;
case 'N':
byte1 = 0x7F; byte2 = 0x04; byte3 = 0x08; byte4 = 0x10; byte5 = 0x7F; //0x7F, 0x04, 0x08, 0x10, 0x7F
break;
case 'O':
byte1 = 0x3E; byte2 = 0x41; byte3 = 0x41; byte4 = 0x41; byte5 = 0x3E; //0x3E, 0x41, 0x41, 0x41, 0x3E
break;
case 'P':
byte1 = 0x7F; byte2 = 0x09; byte3 = 0x09; byte4 = 0x09; byte5 = 0x06; //0x7F, 0x09, 0x09, 0x09, 0x06
break;
case 'Q':
byte1 = 0x3E; byte2 = 0x41; byte3 = 0x51; byte4 = 0x21; byte5 = 0x5E; //0x3E, 0x41, 0x51, 0x21, 0x5E
break;
case 'R':
byte1 = 0x7F; byte2 = 0x09; byte3 = 0x19; byte4 = 0x29; byte5 = 0x46; //0x7F, 0x09, 0x19, 0x29, 0x46
break;
case 'S':
byte1 = 0x26; byte2 = 0x49; byte3 = 0x49; byte4 = 0x49; byte5 = 0x32; //0x26, 0x49, 0x49, 0x49, 0x32
break;
case 'T':
byte1 = 0x01; byte2 = 0x01; byte3 = 0x7F; byte4 = 0x01; byte5 = 0x01; //0x01, 0x01, 0x7F, 0x01, 0x01
break;
case 'U':
byte1 = 0x3F; byte2 = 0x40; byte3 = 0x40; byte4 = 0x40; byte5 = 0x3F; //0x3F, 0x40, 0x40, 0x40, 0x3F
break;
case 'V':
byte1 = 0x1F; byte2 = 0x20; byte3 = 0x40; byte4 = 0x20; byte5 = 0x1F; //0x1F, 0x20, 0x40, 0x20, 0x1F
break;
case 'W':
byte1 = 0x3F; byte2 = 0x40; byte3 = 0x30; byte4 = 0x40; byte5 = 0x3F; //0x3F, 0x40, 0x30, 0x40, 0x3F
break;
case 'X':
byte1 = 0x63; byte2 = 0x14; byte3 = 0x08; byte4 = 0x14; byte5 = 0x63; //0x63, 0x14, 0x08, 0x14, 0x63
break;
case 'Y':
byte1 = 0x03; byte2 = 0x04; byte3 = 0x78; byte4 = 0x04; byte5 = 0x03; //0x03, 0x04, 0x78, 0x04, 0x03
break;
case 'Z':
byte1 = 0x61; byte2 = 0x51; byte3 = 0x49; byte4 = 0x45; byte5 = 0x43; //0x61, 0x51, 0x49, 0x45, 0x43
break;
case ' ':
byte1 = 0x00; byte2 = 0x00; byte3 = 0x00; byte4 = 0x00; byte5 = 0x00; //0x61, 0x51, 0x49, 0x45, 0x43
break;
case '°':
byte1 = 0x00; byte2 = 0x07; byte3 = 0x05; byte4 = 0x07; byte5 = 0x00; //0x61, 0x51, 0x49, 0x45, 0x43
break;
}
for (long i=0;i < 5;i++){
//b1 = byte[i];
switch (i){
case 0:
b1 = byte1;
break;
case 1:
b1 = byte2;
break;
case 2:
b1 = byte3;
break;
case 3:
b1 = byte4;
break;
case 4:
b1 = byte5;
break;
}
bit0 = (b1 & 0b00000001)*255; // & je AND .. 0 AND 1 = 0 a 1 AND 1 = 1
bit1 = ((b1 & 0b00000010)>>1)*255; // >>1 p?esune bity o 1 místo vpravo
bit2 = ((b1 & 0b00000100)>>2)*255;
bit3 = ((b1 & 0b00001000)>>3)*255;
bit4 = ((b1 & 0b00010000)>>4)*255;
bit5 = ((b1 & 0b00100000)>>5)*255;
bit6 = ((b1 & 0b01000000)>>6)*255;
bit7 = ((b1 & 0b10000000)>>7)*255; // >>7 p?esune bity o 7 míst vpravo
switch (size){
case 1:
putcSPI(bit0); putcSPI(bit0); putcSPI(bit1); putcSPI(bit1); putcSPI(bit2); putcSPI(bit2); putcSPI(bit3); putcSPI(bit3);
putcSPI(bit4); putcSPI(bit4); putcSPI(bit5); putcSPI(bit5); putcSPI(bit6); putcSPI(bit6); putcSPI(bit7); putcSPI(bit7);
break;
case 2:
for (char iii=0;iii<2;iii++){
for (char ii=0;ii < 4;ii++){putcSPI(bit0);}
for (char ii=0;ii < 4;ii++){putcSPI(bit1);}
for (char ii=0;ii < 4;ii++){putcSPI(bit2);}
for (char ii=0;ii < 4;ii++){putcSPI(bit3);}
for (char ii=0;ii < 4;ii++){putcSPI(bit4);}
for (char ii=0;ii < 4;ii++){putcSPI(bit5);}
for (char ii=0;ii < 4;ii++){putcSPI(bit6);}
for (char ii=0;ii < 4;ii++){putcSPI(bit7);}
}
break;
case 3:
for (char iii=0;iii<3;iii++){
for (char ii=0;ii < 6;ii++){putcSPI(bit0);}
for (char ii=0;ii < 6;ii++){putcSPI(bit1);}
for (char ii=0;ii < 6;ii++){putcSPI(bit2);}
for (char ii=0;ii < 6;ii++){putcSPI(bit3);}
for (char ii=0;ii < 6;ii++){putcSPI(bit4);}
for (char ii=0;ii < 6;ii++){putcSPI(bit5);}
for (char ii=0;ii < 6;ii++){putcSPI(bit6);}
for (char ii=0;ii < 6;ii++){putcSPI(bit7);}
}
break;
case 4:
for (char iii=0;iii<4;iii++){
for (char ii=0;ii < 8;ii++){putcSPI(bit0);}
for (char ii=0;ii < 8;ii++){putcSPI(bit1);}
for (char ii=0;ii < 8;ii++){putcSPI(bit2);}
for (char ii=0;ii < 8;ii++){putcSPI(bit3);}
for (char ii=0;ii < 8;ii++){putcSPI(bit4);}
for (char ii=0;ii < 8;ii++){putcSPI(bit5);}
for (char ii=0;ii < 8;ii++){putcSPI(bit6);}
for (char ii=0;ii < 8;ii++){putcSPI(bit7);}
}
break;
case 10:
for (char iii=0;iii<8;iii++){
for (char ii=0;ii < 20;ii++){putcSPI(bit0);}
for (char ii=0;ii < 20;ii++){putcSPI(bit1);}
for (char ii=0;ii < 20;ii++){putcSPI(bit2);}
for (char ii=0;ii < 20;ii++){putcSPI(bit3);}
for (char ii=0;ii < 20;ii++){putcSPI(bit4);}
for (char ii=0;ii < 20;ii++){putcSPI(bit5);}
for (char ii=0;ii < 20;ii++){putcSPI(bit6);}
for (char ii=0;ii < 20;ii++){putcSPI(bit7);}
}
break;
}
}
for (int i4=0; i4 < size; i4++){
for (int i3=0; i3 < 16*size; i3++){
putcSPI(0);
}
}
}
CS = 1;
}
Naposledy upravil(a) Ladin dne 08 dub 2015, 18:53, celkem upraveno 1 x.
docela ziiiram
to si napsal sam ? nebo nekde okopcil
to mas vlastni fonty?
nevidim tam nikde tu fci writetext (); , jen writetxt (char text[],char size, unsigned int x1,unsigned int y1), a pokud je to ona tak je divny ze ti to jde vubec prelozit protoze ti tam chybi pri volani velikost x1 a y1
pro jakej displej to je ?
a kod se dava do [ code ]
jinak se my nechce skoumat do detajlu co to vsechno dela ...[/code]
![Shocked 8O](./images/smilies/icon_eek.gif)
to si napsal sam ? nebo nekde okopcil
to mas vlastni fonty?
nevidim tam nikde tu fci writetext (); , jen writetxt (char text[],char size, unsigned int x1,unsigned int y1), a pokud je to ona tak je divny ze ti to jde vubec prelozit protoze ti tam chybi pri volani velikost x1 a y1
pro jakej displej to je ?
a kod se dava do [ code ]
jinak se my nechce skoumat do detajlu co to vsechno dela ...[/code]
- Jeejda_teda_puvodne
- Příspěvky: 142
- Registrován: 08 dub 2012, 02:00
Naposledy upravil(a) Jeejda_teda_puvodne dne 25 říj 2016, 19:41, celkem upraveno 1 x.
![Very Happy :D](./images/smilies/icon_biggrin.gif)
text [0] = 'A';
text [1] = 'H';
text [2] = 'O';
text [3] = 'J';
text [4] = '/n';
tak to běží normálně ať je tam ten můj paskvil ve funkci nebo ne... x1 a y1 jsou myslim definované velikostně unsigned int takže pokud se nepletu 0x0000 až 0xFFFF... nebo sem uplně mimo?
![Embarassed :oops:](./images/smilies/icon_redface.gif)
Pár poznámek.
1) Stringový literál je obvyklejší takto:
2) Escape znak je \, nikoliv /
3) Prototyp funkce:
4) Všechny řetězcové literály bych umístil do kódové paměti. Když to uděláte tak, jak to máte teď, tak se na začátku programu vygeneruje kód, který tím stringem naplní RAM. S nebezpečím, že se RAM přeplní a bez valného významu, pokud ten string nechcete za běhu měnit.
5) Namísto toho šíleného switche pro číslovky a písmena bych použil dvourozměrné pole umístěné v kódové paměti.
6) Také další switch je zbytečný, pokud se byte1 až byte5 umístí do pole. navíc celý ten cyklus se mi zdá být nic nedělající, než že do bl umístí byte5.
7) Pokud je to možné, používejte ++x namísto x++, je to většinou rychlejší. Operátor x++ musí vytvářet kopii x, pak x inkrementuje a kopii odevzdá jako svoji výslednou hodnotu.
1) Stringový literál je obvyklejší takto:
Kód: Vybrat vše
char* text = "Ahoj\n";
3) Prototyp funkce:
Kód: Vybrat vše
void writetxt(char* text, size_t size, unsigned int x1,unsigned int y1);
5) Namísto toho šíleného switche pro číslovky a písmena bych použil dvourozměrné pole umístěné v kódové paměti.
6) Také další switch je zbytečný, pokud se byte1 až byte5 umístí do pole. navíc celý ten cyklus
Kód: Vybrat vše
for (long i=0;i < 5;i++){
7) Pokud je to možné, používejte ++x namísto x++, je to většinou rychlejší. Operátor x++ musí vytvářet kopii x, pak x inkrementuje a kopii odevzdá jako svoji výslednou hodnotu.
Pravdou je, že mi dělá celkem problém pochopit funkci ukazatele. Předtím jsem dělal v basicu picaxe a tam je to takové jasné... tohle je rom a takhle to zkopiruj do ram a takhle dlouho to tam nech a pak to zase použij.
Za poznámky mnohokrát díky, takhle na konkrétním a vlastním příkladu je to snazší pochopit.
K bodu 1: vyzkouším... (zatím nerozumím)
2: jj pravda, napsal jsem to blbě, originál mám dobře
3: vyzkouším
4: pomohlo by mi pochopit pojem kodová paměť, to je zřejmě funkce ukazatele? já právě nevím jestli to vůbec chápu alespoň částečně, že hvězdička(ukazatel) ukazuje na místo v paměti programu, v paměti rom? je mi jasné, že to bude základ C, ale ať to čtu kde chci, jako uživatel basicu to nemůžu vstřebat...![Embarassed :oops:](./images/smilies/icon_redface.gif)
5: dvourozměrné pole v kodove pameti... takže např. takto?
a jak pozná kdy jaké písmeno použit v tu pravou chvíly?
6: myslím, že je to špatně vidět, zbytečné to není, funguje to, každé písmeno je složené z 5ti bajtů, display ho vykresluje odleva a ten for i dělá to, že proměnné b1 nejprve přiřadí bajt0 písmene potom vykreslí a dále v dalším cyklu b1 přiřadí bajt1 a vykreslí dokud nevykreslí celé písmeno, ať se to zdá šílené tak to funguje, věřím, že to jde napsat lépe, ale zatím neumím.. původně jsem to psal do pole byte, ale to mi nefungovalo, kreslilo to bludy tak sem to natvrdo rozdelil na bite1,2,3,4,5
7: dobrý tip, to mě nenapadlo!
Ani jsem nepočítal s tím, že by to někdo takhle louskal takže za tu trpělivost díky, předpokládám, že tady bude trpělivost končit
ale i tak a ještě jednou díky ![Embarassed :oops:](./images/smilies/icon_redface.gif)
Za poznámky mnohokrát díky, takhle na konkrétním a vlastním příkladu je to snazší pochopit.
K bodu 1: vyzkouším... (zatím nerozumím)
2: jj pravda, napsal jsem to blbě, originál mám dobře
3: vyzkouším
![Smile :)](./images/smilies/icon_smile.gif)
4: pomohlo by mi pochopit pojem kodová paměť, to je zřejmě funkce ukazatele? já právě nevím jestli to vůbec chápu alespoň částečně, že hvězdička(ukazatel) ukazuje na místo v paměti programu, v paměti rom? je mi jasné, že to bude základ C, ale ať to čtu kde chci, jako uživatel basicu to nemůžu vstřebat...
![Embarassed :oops:](./images/smilies/icon_redface.gif)
5: dvourozměrné pole v kodove pameti... takže např. takto?
Kód: Vybrat vše
char* ascii [5] [50];
6: myslím, že je to špatně vidět, zbytečné to není, funguje to, každé písmeno je složené z 5ti bajtů, display ho vykresluje odleva a ten for i dělá to, že proměnné b1 nejprve přiřadí bajt0 písmene potom vykreslí a dále v dalším cyklu b1 přiřadí bajt1 a vykreslí dokud nevykreslí celé písmeno, ať se to zdá šílené tak to funguje, věřím, že to jde napsat lépe, ale zatím neumím.. původně jsem to psal do pole byte, ale to mi nefungovalo, kreslilo to bludy tak sem to natvrdo rozdelil na bite1,2,3,4,5
7: dobrý tip, to mě nenapadlo!
![Smile :)](./images/smilies/icon_smile.gif)
Ani jsem nepočítal s tím, že by to někdo takhle louskal takže za tu trpělivost díky, předpokládám, že tady bude trpělivost končit
![Laughing :lol:](./images/smilies/icon_lol.gif)
![Embarassed :oops:](./images/smilies/icon_redface.gif)
Ad1) Je to obvyklejší, na řetězcový literál přímo ukazuje pointer typu char*.
Ad4) Tyhle mikrokontroléry mají Harwardskou architekturu, to znamená, že mají oddělenou paměť typu RAM pro data a paměť pro instrukce programu, bývá to FLASH, EEPROM, ROM. To neznamená, že by paměť na program nemohla obsahovat nic jiného, než instrukce. Může obsahovat cokoliv, co se považuje za konstantní, to znamená i nějaké pevné řetězce pro menu na LCD a podobně. Dotyčný překladač musí obsahovat příslušné rozšíření, které umožní říci, že se data mají nacházet v kódové paměti (jinak je bude alokovat do RAM). Mělo by to být v dokumentaci pro překladač. Jako příklad uvedu fragment zpracování AT povelů napsaný pro gcc pro AVR:
kde řetězce cmdXXX jsou vzory pro AT povely, at_cmd[] je tabulka pointerů na ně a at_service_tab je tabulka pointerů na funkce, které AT povely zpracovávají. Všechno leží v paměti FLASH spolu s programem. Přístup na tyto hodnoty je také poněkud jiný:
Funkce findATFunction() prohledává tabulku AT povelů pomocí pgm_read_word(at_cmd + i) a srovnává řetězce pomocí strcasecmp_P(). Podle nalezeného indexu se pak načte pointer na funkci pomocí pgm_read_word_near(). Takto je všechno konstantní v kódové paměti a ušetří se RAM.
Ad5) Ano, všechny ty hodnoty do 2D pole. Řádek odvozovat od číslice (písmene) namísto toho case, byte1 - byte5 načíst pak v cyklu z řádku do pole 5 byte.
Ad6) Máte pravdu, špatně jsem spároval závorky.
Ad4) Tyhle mikrokontroléry mají Harwardskou architekturu, to znamená, že mají oddělenou paměť typu RAM pro data a paměť pro instrukce programu, bývá to FLASH, EEPROM, ROM. To neznamená, že by paměť na program nemohla obsahovat nic jiného, než instrukce. Může obsahovat cokoliv, co se považuje za konstantní, to znamená i nějaké pevné řetězce pro menu na LCD a podobně. Dotyčný překladač musí obsahovat příslušné rozšíření, které umožní říci, že se data mají nacházet v kódové paměti (jinak je bude alokovat do RAM). Mělo by to být v dokumentaci pro překladač. Jako příklad uvedu fragment zpracování AT povelů napsaný pro gcc pro AVR:
Kód: Vybrat vše
...
typedef s08 (*AT_SERVICE)(const char* prm);
...
static char cmdReset[] PROGMEM = "Z";
static char cmdVersion[] PROGMEM = "+GMM";
static char cmdFactory[] PROGMEM = "&F";
static char cmdStoreCfg[] PROGMEM = "&W";
static char cmdRestoreCfg[] PROGMEM = "&V";
static char cmdMode[] PROGMEM = "\\N";
static char cmdFrequency[] PROGMEM = "&G";
static char cmdModulation[] PROGMEM = "+MS";
static char cmdMarker[] PROGMEM = "+CUR";
static char cmdSweep[] PROGMEM = "+SWR";
static char cmdMrkStep[] PROGMEM = "+CST";
static prog_char* at_cmd[] PROGMEM =
{
cmdReset, cmdVersion, cmdFactory,
cmdStoreCfg, cmdRestoreCfg, cmdMode,
cmdFrequency, cmdModulation, cmdMarker,
cmdSweep, cmdMrkStep
};
static s08 (*at_service_tab[]) (const char* prm) PROGMEM =
{
ATReset, ATVersion, ATFactory,
ATStoreCfg, ATRestoreCfg, ATMode,
ATFrequency, ATModulation, ATMarker,
ATSweep, ATMrkStep
};
Kód: Vybrat vše
// --------------------- AT command processing ------------
s08 findATFunction(const char* cmd)
{
for(u08 i = (u08)0; i < (u08)(sizeof(at_cmd)/sizeof(char*)); ++i)
{
PGM_P cmd_P = (PGM_P)pgm_read_word(at_cmd + i);
if(strcasecmp_P(cmd, cmd_P) == 0)
{
return (s08)i;
}
}
return (s08)-1;
}
...
AT_SERVICE at_service; // pointer to service function
index = findATFunction(cmd);
if(index != (s08)-1)
{
at_service = (AT_SERVICE)pgm_read_word_near(&at_service_tab[(u08)index]);
u08 ret = at_service(prm); // find and run service function
}
Ad5) Ano, všechny ty hodnoty do 2D pole. Řádek odvozovat od číslice (písmene) namísto toho case, byte1 - byte5 načíst pak v cyklu z řádku do pole 5 byte.
Ad6) Máte pravdu, špatně jsem spároval závorky.
Naposledy upravil(a) mtajovsky dne 09 dub 2015, 09:22, celkem upraveno 1 x.
![Shocked 8O](./images/smilies/icon_eek.gif)
Takže jestli jsem to alespoň trochu pochopil, v prvním příkladu mcu určíte pomocí ukazatelů "sadu" příkazů, tedy zřejmě vždy číslo registru paměti programu kde se ten řetězec nachází? ... a podobně pak určíte funkce.. ve finále pak jde volat a různě kombinovat příkazy a funkce... už možná začínám tušit, v basicu je to rozděleno na šest různých příkazů, pokud chci zapisovat do ram tak je to poke, číst z ram peek, zapisovat do eeprom DATA, číst READ, zapisovat do programové paměti TABLE, číst READTABLE.. a tady je to tedy rozlišeno pomocí ukazatelů *, je to tak?
Jdu si to ještě přečíst
![Idea :idea:](./images/smilies/icon_idea.gif)
Podstatné je to PROGMEM. To určuje, že je proměnná situována do kódové paměti. Čtení z kódové paměti je pomocí pgm_read_word() a podobně.
PGM_P a prog_char* jsou ukázky, jak vypadá deklarátor pointeru na char v kódové paměti.
Možná je pro vás trochu nezvyklá syntaxe definice typu "pointer na funkci".
PGM_P a prog_char* jsou ukázky, jak vypadá deklarátor pointeru na char v kódové paměti.
Možná je pro vás trochu nezvyklá syntaxe definice typu "pointer na funkci".
To není rutina z nějaké knihovny, to je rozšířená syntaxe kompilátoru C pro tyto účely. Uvedl jsem příklad pro AVR gcc a WinAVR. Bohužel, s PIC nemám zkušenosti. PROGMEM atd. jsou makra a typy specifikovaná v hlavičkovém souboru <avr/pgmspace.h>, který je součástí balíku WinAVR:
#define PROGMEM __ATTR_PROGMEM__
a
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
kde atribut __attribute__((__progmem__)) již rozeznává rovnou kompilátor (zobecněné atributy C++11).
#define PGM_P const char *
typedef char PROGMEM prog_char;
a další. Pokud kompilátor nalezne tuto syntaxi, tak umístí takto definovaná data do paměťového segmentu pro kód.
Pro vaše prostředí MPLABU budete muset najít v v dokumentaci, jaká je syntaxe příslušného atributu rozeznávaného kompilátorem a jestli hlavičkové soubory dodávané ke kompilátoru nebo k prostředí obsahují příslušná makra a definice typů (nebo si to napsat sám). Mohly by tam být i nějaké příklady. Podle toho pak musíte napsat do kódu potřebné atributy a typy v místech, kde jsem pro AVR použil PROGMEM a další. Předpokládám, že C kompilátor pro PIC to umí. Hledejte v dokumentaci něco jako "Data in Program Space".
http://www.microchip.com/forums/m166493.aspx
#define PROGMEM __ATTR_PROGMEM__
a
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
kde atribut __attribute__((__progmem__)) již rozeznává rovnou kompilátor (zobecněné atributy C++11).
#define PGM_P const char *
typedef char PROGMEM prog_char;
a další. Pokud kompilátor nalezne tuto syntaxi, tak umístí takto definovaná data do paměťového segmentu pro kód.
Pro vaše prostředí MPLABU budete muset najít v v dokumentaci, jaká je syntaxe příslušného atributu rozeznávaného kompilátorem a jestli hlavičkové soubory dodávané ke kompilátoru nebo k prostředí obsahují příslušná makra a definice typů (nebo si to napsat sám). Mohly by tam být i nějaké příklady. Podle toho pak musíte napsat do kódu potřebné atributy a typy v místech, kde jsem pro AVR použil PROGMEM a další. Předpokládám, že C kompilátor pro PIC to umí. Hledejte v dokumentaci něco jako "Data in Program Space".
http://www.microchip.com/forums/m166493.aspx