Programování PICů v C (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
forbidden
Příspěvky: 8808
Registrován: 14 úno 2005, 01:00
Bydliště: Brno (JN89GF)
Kontaktovat uživatele:

Programování PICů v C (XC8)

#1 Příspěvek od forbidden »

Protože mě už nebaví matlat se s assemblerem, začal jsem se učit Cčko. Problémky průběžně řeším hlavně s Googlem. :D Ale teď jsem narazil na zajímavost, kterou nechápu.
Mám jednoduchej kód pro výpis textů na LCD:

Kód: Vybrat vše

void main ()
{
    LCDinit ();
    printf ("Test HD44780");
    LCDctrl (0xC0);                 // druhy radek prvni znak
    
    //LCDcursor (1);
    
    char a=8, b=9, c=255, d=19;
    printf ("%u", a);
    printf ("%u", b);
    printf ("%X", c);
    printf ("%u", d);
    
    while (1);
}
Pokud vypisuju jen texty v ASCII ("Test HD44780") tak má program zabráno 9 % programové a 8 % datové paměti. Jakmile chci použít formátování, tak s každým dalším použitým formátem (%u, %X drasticky narůstá zabraná paměť. V tomto případě 29 % programové a 16 % datové. Čím to sakra je?
8O
Mám to jen v PIC16F628A s 2 "kB", je to jen zkoušení. XC8 je free verze, je možný, že je to tím?
Dík.

Uživatelský avatar
mikollar
Příspěvky: 1406
Registrován: 26 pro 2004, 01:00
Bydliště: Košice - okolie

#2 Příspěvek od mikollar »

printf a podobne fcie ako sprintf zaberaju samotne vela miesta. Pre male picky resp ak chyba miesto, je lepsie si napisat vlastnu kniznicu pre konverziu.

Edit: Pri tejto picke to bude este vyraznejsie aj preto, ze je to len 8bit s minimom instrukcii.

Osobne som uz prestal pouzivat radu 16F a 18F a pouzivam len 24F..., cena je tam porovnatelna mozno trosku vyssia, ale zato vykon a funkcnost nasobne vacsia

Uživatelský avatar
forbidden
Příspěvky: 8808
Registrován: 14 úno 2005, 01:00
Bydliště: Brno (JN89GF)
Kontaktovat uživatele:

#3 Příspěvek od forbidden »

Hmm, to jsou teda pěkně neefektivní konverze. Jinak tu mám i výkonnější typy ale jen tu řadu 18F. Mě to zatím na ty moje hlouposti stačí. Uvidíme časem.
Díky.

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#4 Příspěvek od Atlan »

A este si odsimuluj kolko trva ten tvoj fprint s konverziou aby si sa nedivil.

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

#5 Příspěvek od mtajovsky »

Pro jednoduché konverze je lepší si napsat nějaké rutiny sám. Například:

Kód: Vybrat vše

void word2dec(u16 val, char *s)  
{
  s[0] = '0' + (val / 10000);
  s[1] = '0' + (val % 10000) / 1000;
  s[2] = '0' + (val % 1000) / 100;
  s[3] = '0' + (val % 100) / 10;
  s[4] = '0' + (val % 10);
  s[5]=0;
}
Další příklady lze nalézt v adresáří conv v projektu generátoru s AD9851 - odkaz v sekci součástky.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#6 Příspěvek od rnbw »

Funkcia printf je velky moloch, ktory ma vela moznosti. Na PC to je jedno, pretoze je v standardnej kniznici, takze je v pamati iba raz aj ked ju pouziva mnoho programov. Ale na vypisovanie neformatovanych textov alebo jednoduchych cisiel v malom MCU je to overkill.

BTW. Je dolezite pochopit, ze C nepozna retazce - uz aj pre spravne pouzitie funkcie word2dec() od mtajovskeho.

Uživatelský avatar
forbidden
Příspěvky: 8808
Registrován: 14 úno 2005, 01:00
Bydliště: Brno (JN89GF)
Kontaktovat uživatele:

#7 Příspěvek od forbidden »

Však uvidíme, jak to půjde časem, zatím se bavím psaním knihoven pro obsluhu všeho možnýho. Mám hotový to HD44780 a teď jsem dopsal sw implementaci 1-Wire.
rnbw píše: BTW. Je dolezite pochopit, ze C nepozna retazce - uz aj pre spravne pouzitie funkcie word2dec() od mtajovskeho.
Tomu nerozumím, jak mám chápat, že nezná řetězce?

Kód: Vybrat vše

char *s = "hello world";
Je řetězec ne?

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

#8 Příspěvek od mtajovsky »

To se myslí tak, že v C není syntakticky nic, co by popisovalo řetězec. C má jen pointer na začátek úseku paměti, kde se předpokládá obsah řetězce znaků ukončený nulou. Samotný pointer nic neříká o délce řetězce a ukončení nulou je jen konvence z nouze.

Na rozdíl od možností C++, kde máme standardní knihovní šablonu pro řetězce (obecně jakýchkoliv objektů, ne jen znaků) std::basic_string a její specializaci pro znaky - typedef std::basic_string<char> string;

Nebo C#, kde je přímo třída String. Tyto záležitosti pak samy o sobě obsahují vše - datový obsah, jeho velikost a potřebné operace nad daty.
Naposledy upravil(a) mtajovsky dne 07 pro 2016, 23:14, celkem upraveno 1 x.

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#9 Příspěvek od rnbw »

forbidden píše:Tomu nerozumím, jak mám chápat, že nezná øetìzce?

Kód: Vybrat vše

char *s = "hello world";
Je øetìzec ne?
s je pointer typu char, ktory ukazuje na adresu, kde sa nachadza danych 11 znakov textu a za nimi nulovy byte. Mozes na to pouzit rozne retazcove funkcie z kniznice, ale je to len obycajny pointer.

Cize keby si tam mal este

Kód: Vybrat vše

char *s2 = "test";
a nasledne urobil:

Kód: Vybrat vše

s = s2;
tak pointer s bude ukazovat na rovnaku adresu ako s2. Takze printf(s) aj printf(s2) vypise "test" - rovnako ako keby to boli v inom jazyku retazce a urobil si priradenie. Ale ked teraz urobis

Kód: Vybrat vše

s[0] = 'x';
tak oba vypisu "xest", pretoze si nezmenil prvy znak retazca s, ale byte na adrese s, na ktoru ukazuje aj s2.

Wolfik
Příspěvky: 1076
Registrován: 28 črc 2009, 02:00

#10 Příspěvek od Wolfik »

forbidden - nepoužívej io funkce standartní knihovny (stdio), ale odlehčené funkce kompilátoru pro mcu. Většina moderních křížových kompilátorů by něco takového měla mít, při nejhorším pogoogli po nějakých implementacích a naportuj to na toho PICe...

nebo jak tu někdo poznamenal - napiš si vlasní. Takhle se hodně naučíš.

Uživatelský avatar
forbidden
Příspěvky: 8808
Registrován: 14 úno 2005, 01:00
Bydliště: Brno (JN89GF)
Kontaktovat uživatele:

#11 Příspěvek od forbidden »

OK, v tom se budu muset zorientovat a zažít si to. A hlavně prostě zkoušet. Díky oběma.

Longin: manuál k XC8 má 600 stran, zatím jsem do něho radši nekoukal. Učím se to z knížky od Matouška a i když není až tak stará, tak tam používá třeba MCC18 na překlady, ale to se právě v některých věcech od XC8 liší. Takže semtam něco nefunguje a musím bádat proč a jak. Takže je možný, že XC8 odlehčený funkce obsahuje, když je určený pro 8-mi biťáky.

Wolfik
Příspěvky: 1076
Registrován: 28 črc 2009, 02:00

#12 Příspěvek od Wolfik »

Letmo jsem koukal do manuálu toho kompileru a zdá, že maj prostě tu svoji implementaci stdio tvrdě zadrátovanou.

Otázka je, jestli portací nějaké externí odlehčené knihovny si pomůžeš (newlib, embedded printf) apod.

Většinou jde jenom to, že implementuješ nějakou obdobu funkce putchar() a pak to přesměruješ na standartní výstup.

Ve tvým kompilátoru je třeba naznačeno tohle s UARTem

Kód: Vybrat vše

void putch(char data) {
  while( ! TXIF)  // check buffer
    continue;     // wait till ready
  TXREG = data;   // send data
}
přesměrování standartního výstupu se u GNU AVR Cdělá třeba takhle:

Kód: Vybrat vše

#include <stdio.h>
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
                                         _FDEV_SETUP_WRITE);
static int
uart_putchar(char c, FILE *stream)
{
  if (c == '\n')
    uart_putchar('\r', stream);
  loop_until_bit_is_set(UCSRA, UDRE);
  UDR = c;
  return 0;
}
int
main(void)
{
  init_uart();
  stdout = &mystdout;
  printf("Hello, world!\n");
  return 0;
}
Ten tvůj PIC má 2kB FLASHky. To je na hrátky s printf a sprintf dost málo :D
Další kámen úrazu je v v datové paměti, kde si podle mě zbytečně ukládáš konstatní řetězce - jednou jsou ve programové paměti a podruhé v datové zbytečně. Kompilátor by měl umět vytvářet a přistupovat ke konstatním proměnným jenom ve FLASHCe, ale pochybuju, že toho dosáhneš použitím const v Cčku.

Trošku OT:
Chápu, že se chceš asi urputně držet svých 8-bitových PICů, co jsou za zenitem, ale možná by stálo za úvahu pouvažovat o nějakých modernějších 8-bitových mcučkách, které nemají takové paměťové limitace, periferie jako ten PIC a nemají krkolomný přístup k programování v C...a stojej zhruba stejně.

Například nové STM8 jsou dobrý (k SDCC kompilátoru máš slušný příklady), AVR8 nebo modernější PIC8, když už seš zvyklý na PICy...

Uživatelský avatar
forbidden
Příspěvky: 8808
Registrován: 14 úno 2005, 01:00
Bydliště: Brno (JN89GF)
Kontaktovat uživatele:

#13 Příspěvek od forbidden »

Však já mám tu printf přesměrovanou na LCD právě pomocí putch.
A konstatnty, který není nutno držet v datové samozřejmě jen do programové nacpu, to není problém. To jde bez problémů.
Ten kód zatím nemá žádnej hlubší smysl, jen si tak zkouším, takže zbytečně obsazená datová paměť mě momentálně netrápí. Mě jen překvapilo, jak moc to naroste při použití těch formátovaných výstupů.
A na osmibiťácích taky netrvám, jen jich mám v šuplíku hodně a chci je využít. A taky jsem si říkal, že začnu na těch nejjednodušších. Nicméně PICů se chci držet už jen ze zvyku. Pro mě momentálně nemá smysl začínat s něčím novým. Jestli napíšu 5 programů za rok, myslím smysluplných projektů, který někde použiju, tak je to moc. Mám to jen jako zábavu, není moc času se tomu věnovat.
Leda bych změnil zaměstnání, kde bych elektroniku využil, to by byla jiná.

Uživatelský avatar
forbidden
Příspěvky: 8808
Registrován: 14 úno 2005, 01:00
Bydliště: Brno (JN89GF)
Kontaktovat uživatele:

#14 Příspěvek od forbidden »

Tak jsem trochu zklamanej celkovou efektivitou překladu. Blbej výpočet třeba: t=625*(LSB+(256*MSB)) zabere v tom osmibitu taky hodně místa.
Tak to vypadá, že si zas budu hrát hlavně s logickýma bitovýma operacema, akorát místo v assembleru, tak v Cčku.
Anebo se fakt vybodnout na malý osmibity a užívat si komfortu rozežraných funkcí na něčem výkonnějším. :)

Uživatelský avatar
rnbw
Příspěvky: 32312
Registrován: 21 bře 2006, 01:00
Bydliště: Bratislava

#15 Příspěvek od rnbw »

Ma vobec ten kompilator optimalizaciu na velkost?

Odpovědět

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