xc8+pic - for nezastaví na nule

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

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
Uživatelský avatar
dracekvo
Příspěvky: 402
Registrován: 10 úno 2009, 01:00

xc8+pic - for nezastaví na nule

#1 Příspěvek od dracekvo »

Ahoj,
může mi někdo prosím vysvětlit, proč když udělám v xc8 a pic 16f88 toto

bit_to_lcd(unsigned char a)
{
char b;

for(b=7;b>=0;b--) {
if((a & (1<<b))!= 0) {
lcd_zapis("1");
} else {
lcd_zapis("0");
}
}
}

tak prostě for jede furt do nekonečna.
Aby to fungovalo, tak musím udělat odčítání od 8 do 1
for(b=8;b>0;b--) {
a pak v podmínce od b odečítat 1
if((a & (1<<b-1))!= 0) {

opravdu nechápu, proč nezastaví.

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

#2 Příspěvek od Atlan »

Pozeram ze tvoje myslenie je komplikovane pre 8bit uP. Nechces to napisat jednoduchsie? Napr s vyuzitim bitoveho posunu? Teda ak som vobec s kopy tych operatorov pochopil co mas v umysle.

C=0b1000 0000;
Bcko daj normalne. For b=0 b<7; b++
(
If (a&c) posli 1 else posli 0;
C>>1;
)
Naposledy upravil(a) Atlan dne 18 úno 2017, 21:45, celkem upraveno 1 x.

Uživatelský avatar
dracekvo
Příspěvky: 402
Registrován: 10 úno 2009, 01:00

#3 Příspěvek od dracekvo »

Ten if sem někde ukradl. Mě to moc nejde na mozek pracovat ve vyšším jazyce s bitama.

Má to být věc, co mi na LCD vypíše obsah charu bitově.
Tj 3 mi zobrazí jako 00000011.

b jsem dal obrázeně, protože mi ho to vypisovalo pozpátku 11000000.


tvůj příklad zkusím zítra implementovat. Děkuji

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

#4 Příspěvek od mtajovsky »

Mě to funguje. Vypadá to, že váš překladač bere char b jako unsigned. Když se pak b dekrementuje z nulové hodnoty tak se výsledek nebere jako -1, ale jako 127. Pokud chcete zachovat funkci v podobném tvaru, tak bych použil méně využívaný cyklus do-while, který programátoři pohříchu opomíjejí:

Kód: Vybrat vše

void bit_to_lcd1(unsigned char a) 
{ 
char b = 7; 

    do
    { 
        if((a & (1<<b))!= 0)
        { 
            lcd_zapis("1"); 
        }
        else
        {
            lcd_zapis("0"); 
        } 
    }while(b-- != 0); 
} 

Uživatelský avatar
Programator
Příspěvky: 1
Registrován: 19 úno 2017, 01:00

#5 Příspěvek od Programator »

Typ char je maličko odlišný od ostatních intergrálních typů - char, signed char a unsigned char jsou tři odlišné typy, přitom je nespecifikováno zdali je typ char znaménkový nebo ne a každý kompilátor to může mít podle toho, jak se autor vyspal. To je i tento případ. Kompilátor tazatele má char unsigned, a kompilátor p. mtajovského signed. Řešením je buď počítat od 8, nebo změnit typ na signed char.

Pozn.: Jako profesionální programátor musím říct, že je pravda, že se cyklu do-while vyhýbám, stejně jako drtivá většina ostatních programátorů, ale ono to má svoje důvody - čitelnost, přehlednost, korektnost apod. Ale to by bylo na delší diskuzi (čti flamewar).

Uživatelský avatar
lesana87
Příspěvky: 3296
Registrován: 20 zář 2014, 02:00

#6 Příspěvek od lesana87 »

V SDCC pro Z80 mi vychází nejkratší kód při použití for a ternárního operátoru, volání lcd_zapis je ve výsledném asm jen jednou. Při použití if se lcd_zapis volá dvakrát. Ale to asi bude závislé od chytrosti překladače. :)

Kód: Vybrat vše

void bit_to_lcd1(unsigned char a)
{
	unsigned char b;

	for (b = 0b10000000; b > 0; b >>= 1) {
		lcd_zapis(a & b ? "1" : "0");
	}
}

Jenda_KL
Příspěvky: 1173
Registrován: 10 zář 2008, 02:00
Bydliště: Kadaň
Kontaktovat uživatele:

#7 Příspěvek od Jenda_KL »

dracekvo píše:for(b=7;b>=0;b--)
protože for (init; podmínka; akce).
Podmínka b>=0 je splněna vždy. Po podtečení (b==255) je splněna taktéž.
edit: Jsem nečetl celé, vidno bylo toto, což mě taky nachytalo.

Odpovědět

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