Problem s displayom - chyba po volani instrukcii

Pro kolemjdoucího :
Mezi jednotlivýma částma dat není delay potřeba.
První se posílá vyšší polovina bytu.

Souhlasím s tím (pokud nemáš jednotlivé bity od LCDčka připojené na různé bity a porty MCU) udělat zápis celé poloviny bytu najednou.

Mohl by být rozdíl v případě rotací vpravo, kdy u neznaménkového čísla se doplňuje do nejvyššího bitu 0, ale u znaménkového se opakuje nejvyšší bit (tedy podle překladače, některé rotují signed také s 0). Ale vzhledem k tomu že tady se výsledek maskuje & 1, tak by rozdíl neměl být.

Párkrát jsem se už s unsigned napálil, když jsem např. udělal konstrukci typu “for(u8 i=9; i>=0; i–)” a divil se proč mi program mrzne. :slight_smile:

Jestli je “E” nadefinovaný jako volatile, tak překladač pro něj zdánlivě nadbytečné zápisy nevyhazuje.

Panda38:
E je nějaké makro - definice bitu SFR ( nebo jak se u picu jmenují) registru - buď PORT, nebo LAT - (to ví jen autor) - něco jako:

#define E	PORTCbits.RC3

to je v C18 - ten XC8 neznám

nevím jak by se toto dalo definovat jako volatile

Navíc v takovém Codevisionu pro AVRka bych si v tomto případě s volatile moc nepomohl - tam to funguje tak, že prefix volatile jenom řekne překladači, aby nepoužil pro proměnnou jeden ze 32 pracovních registrů - aby nedošlo k jeho přepsání během přerušení.Obsahuje ale direktivy, opt+ a opt-, kterými vyloučím z optimalizace části kódu, které potřebuju. Přiznám, že u piců jsem to až tak detailně zatím nezkoumal.C18 nic takového neumí - snad jen vypnout optimalizaci úplně - proto ta nutnost vkládat do “nelogické” posloupnosti příkazů alespoň ten nop .

Stejně bych ale viděl zádrhel v tom, že pokud by měl “logicky” propojené
piny portu a LCD nějak takto:

PB0(LCD1) - D4
PB1(LCD2) - D5
PB2(LCD3) - D6
PB3(LCD4) - D7

tak bude posílat ta jeho funkce ten půlbyte zrcadlově obrácený.

samozřejmě že by to tak šlo - dokonce by to bylo mnohem rychlejší - myslím tím princip maskování - toto konkrétně asi funkční nebude

tvoje

LATD &= 0xf0; LATD |= (unsigned char)(sendBites & 0x0f);

budou nějaké 3 - 4 asm instrukce, zatímco jeho

LCD1 = 1 & (sendBites >> 7); LCD2 = 1 & (sendBites >> 6); LCD3 = 1 & (sendBites >> 5); LCD4 = 1 & (sendBites >> 4);

je minimálně 26 instrukcí ale spíš víc

teď budu trochu OT, ale už jsem viděl, že hlavně u větších datových typů (long atd) používá autor místo bitového posunu třeba(1>>15) radši dělení
/32768 - ale nezkoumal jsem jaký to má efekt

Díval jsem se do příkladu >> definice <<, PORTCbits je struktura s bitovým polem (RC0…) a celá struktura je označená jako volatile, takže to by mělo být v pořádku.

Rozumný překladač to má umět rozpoznat že to má nahradit optimálnějším bitovým posunem - alespoň GCC a MSVC to dělají (tj. místo word/32768 by udělal ((word rol 1) and 1) ).

proc ?? nejak nechapu (jen ma nechapavost). Pokud je unsigned bez znamenka tzn. (9 je 0b00001001) - 1 = (8 je 0b00001000). Signed je tedy (9 je 0b00001001) to je totez nebo ne ?? Prosim blizsi info :smiley: . Nezalezi spise na kompilatoru (manualu ke kompilatoru) ?

Mozna XC8 zna tohle a treba by se to dalo nejak spojit:

volatile bit D0	@(((unsigned) &LATD)*8) + 7;
volatile bit D1	@(((unsigned) &LATC)*8) + 4;
volatile bit D2	@(((unsigned) &LATA)*8) + 1;
volatile bit D3	@(((unsigned) &LATB)*8) + 2;

volatile union {
    struct {
        unsigned D0            :1;
        unsigned D1            :1;
        unsigned D2            :1;
        unsigned D3            :1;
        unsigned               :4;

			};
} LCDbits;

Ale to uz jsem si asi trosku ulit ne ?? Nikdy jsem to nezkousel jen by me zajimalo jak budete nadavat… :smiley: a jestli by to ubec slo na XC8

Taky tomu nějak nerozumím - problém by snad mohl být při dekrementaci z nuly - u unsigned char bude hodnota 255 - nebude tedy menší než nula, ale k tomu by snad nemělo dojít??

Já osobně tedy radši přičítám “for(u8 i=0; i<9; i++)” a nemám problém s použitým datovým typem

Protože při poslední iteraci se program dostane z 0 na 255 místo na -1, to znamená že podmínka je vždy splněna a cyklus se nikdy neukončí. Překladač to i sám pozná že je to blbost a nahradí to nekonečnou smyčkou. … tahle chyba se stane snadno, když se “i” deklaruje někde dřív jako unsigned a pak se na to zapomene a chce se využít v nějakém jiném cyklu, který indexuje do 0.

Je-li to z funkce programu jedno, bývá odečítání efektivnější. K testu dosažení nuly stačí využít Zero flag z poslední dekrementace (i když pravda že některé překladače tohle zefektivnění nevyužívají). U inkrementace se musí provádět další komparační instrukce. Pokud je zarážkou výraz nebo proměnná, tak tam je to už úplně jasné, protože při přičítání se musí po každé iteraci vyhodnocovat stále znovu koncová hodnota nebo načítat obsah proměnné.

jj tak to … me jen nejak neslo do hlavy jak by se to mohlo stat :smiley: . Ja na to pouzivam jiny mechanizmus. Pokud pouzivam nejakou promennou ve smyckach tak pokazde ji pricitam, jinak pointery ale myslim, ze jsem asi nikdy nepouzil – u cekacich smycek… Ale kdyz to tak pisu tak mozna jsem s tim uz mel problem. Ve smyckach kde se pracovalo s dat.pol[unsigned char]… asi fakt jo …

Jsme už sice totálně OT,ale

tvar “for(u8 i=9; i>0; i–)” by tedy měl problém vyřešit

Nevím v čem děláš, ale většina překladačů pro osmibity - aspoň ty co jsem s nima došel do styku vyžaduje deklaraci “někde dřív” - minimálně na začátku funkce u lokálních proměnných ten ukázkový for o kterém se bavíme by ti vyhodily jako chybu - to jen pro ty co začínají s C - což je asi i případ zakladatele vlákna - a chtěli by si to brát jako příklad.

jasny

Dojet do nuly je potřeba když to “i” má být indexem v poli.

Jasně, deklarace ve for() není správná, dříve se upřednostňovala v Microsoft VC než zjistili že je to nesprávně, ale zatím ji nezakázali (resp. jen volitelně).

…uz dost OT :slight_smile: Ale nevadi, zaujimave veci tu pisete. Ako stale opakujem dookola, ono to RAZ IDE a RAZ NEIDE. Nechapem tomu. Datove typy s tym nemaju vobec nic. Nefunguje ani odoslanie prikazu 0x00. Budem sa opakovat, ale este raz… Na vymazanie displaya mam jedinu funkciu, ktora sa proste zavola. Ak ju zavolam raz, ide vsetko OK. Ak ju zavolam druhykrat, vsetko je zle. Znova: Ako je mozne, ze sa TA ISTA funkcia vykona ROZNE? Skor nie ako to je mozne, ale preco to display neakceptuje. Nula je v akomkolvek datovom type nulou. Vsetko bezi, teda tie prikazy niesu nespravne optimalizovane. Nemam nikde nekonecnu slucku. Na zapis pouzivam LAT a pre citanie PORT. IO je PIC18F2550. Berte prosim v uvahu tieto fakty a neopakujte sa s tym stale. Zhrniem to:

Optimalizaciou sa nepreskakuju instrukcie (dokaz? display funguje).
Mam spravne casovania (dokaz? display funguje).
Na datovom type nezalezi (dokaz? nula je stale nulou).
A na zaver axioma: funkcia nech je volana nespocetnevela krat, stale je vykonavana rovnako.
“Moj” char “pojme” aj vecsie cisla (dokaz? Odoslanie 0xC2 funguje spravne a je to cislo 194)

Znova k mojmu problemu…preco nefunguje odoslanie “nuly” (jedneho z mnoha) 2x po sebe?

Asi se zase budu opakovat ale nahod cely kod i hlavickovymi soubory a mozna i schema zapojeni at je to komplet. Jinak nevim jak pomoci …

Schéma a celý program by pomohl k řešení problému.

Já jsem zkusil napsat program pro připojení LCD(typ HD44780) k PIC18F2550. Rozdíl řady PIC18 a (PIC16,PIC12) je v různém přístupu k datům v RAM a ROM(flash). Alespoň v překladači co používám, proto mám v programu funkce Lcd_Out_RAM(…) a Lcd_Out_ROM(…).
Program je jen pro test, takže přesnost měření času nic moc.
PIC18F2550_LCD44780_4bit.zip (28.8 KB)