textový string v XC8

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

textový string v XC8

#1 Příspěvek od Ladin »

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...

Uživatelský avatar
MiloPS3
Příspěvky: 259
Registrován: 07 srp 2010, 02:00

#2 Příspěvek od MiloPS3 »

cau, nevim jak je to presne v CX8 ale:
pokud chcces vypsat string tak takle writetext (text);
ale musis mit pres ne danou velikost treba char text[10]; nebo musis na konec zapsat 0
text [4] = '/n';
text [5] = 0;

a pak samozrejme zalezi co dela ta fce writetext ();

Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

#3 Příspěvek od Ladin »

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 :roll:

Uživatelský avatar
MiloPS3
Příspěvky: 259
Registrován: 07 srp 2010, 02:00

#4 Příspěvek od MiloPS3 »

takze kdyz das do kodu writetext (text); tak se ani neinicializuje lcd ?

dej sem tu fci writetext ();

nebo radsi cely ..

Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

#5 Příspěvek od Ladin »

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.

Uživatelský avatar
MiloPS3
Příspěvky: 259
Registrován: 07 srp 2010, 02:00

#6 Příspěvek od MiloPS3 »

docela ziiiram 8O
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]

Uživatelský avatar
Jeejda_teda_puvodne
Příspěvky: 142
Registrován: 08 dub 2012, 02:00

#7 Příspěvek od Jeejda_teda_puvodne »

Naposledy upravil(a) Jeejda_teda_puvodne dne 25 říj 2016, 19:41, celkem upraveno 1 x.

Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

#8 Příspěvek od Ladin »

:D Milo tak to buď rád, že jsem tam dal jenom kod te funkce writetxt a ne celej kod, to by si asi koukal víc... jo psal jsem to sám... Jsem tu novej a s picem začínám takže se omlouvám jesi jsem to zadal špatně. Je to pro displej s řadičem ILI9341, ale to není podstatný, ptže otázka se týkala spíš formy zadávání textových řetězců. Já když tu funkci napíšu prázdnou: writetxt (char text[]) {} a pošlu do ní ten text definovanej takto: char text[] = "AHOJ/n"; tak se pic kousne taky. Když text zadam takto: char text[];
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? :oops:

Uživatelský avatar
mtajovsky
Příspěvky: 3694
Registrován: 19 zář 2007, 02:00
Bydliště: Praha

#9 Příspěvek od mtajovsky »

Pár poznámek.

1) Stringový literál je obvyklejší takto:

Kód: Vybrat vše

char* text = "Ahoj\n";
2) Escape znak je \, nikoliv /

3) Prototyp funkce:

Kód: Vybrat vše

void writetxt(char* text, size_t size, unsigned int x1,unsigned int y1);
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

Kód: Vybrat vše

 for (long i=0;i < 5;i++){ 
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.

Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

#10 Příspěvek od Ladin »

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... :oops:
5: dvourozměrné pole v kodove pameti... takže např. takto?

Kód: Vybrat vše

char* ascii [5] [50];
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 :lol: ale i tak a ještě jednou díky :oops:

Uživatelský avatar
mtajovsky
Příspěvky: 3694
Registrován: 19 zář 2007, 02:00
Bydliště: Praha

#11 Příspěvek od mtajovsky »

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:

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   
};
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ý:

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
         }

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.
Naposledy upravil(a) mtajovsky dne 09 dub 2015, 09:22, celkem upraveno 1 x.

Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

#12 Příspěvek od Ladin »

8O no pane jo, přečetl jsem to asi dvacetkrát a mám pocit, že když si teď kejchnu, rozletí se mě hlava a z krku vyteče písmenková polívka...

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:

Uživatelský avatar
mtajovsky
Příspěvky: 3694
Registrován: 19 zář 2007, 02:00
Bydliště: Praha

#13 Příspěvek od mtajovsky »

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".

Uživatelský avatar
Ladin
Příspěvky: 32
Registrován: 07 dub 2015, 02:00

#14 Příspěvek od Ladin »

V MPLABU X IDE mi PROGMEM nejde(unexpected token), nevíte v jaké knihovně by to mohlo být?

Uživatelský avatar
mtajovsky
Příspěvky: 3694
Registrován: 19 zář 2007, 02:00
Bydliště: Praha

#15 Příspěvek od mtajovsky »

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

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“