Stránka 1 z 1

xc8+pic - for nezastaví na nule

Napsal: 18 úno 2017, 16:41
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í.

Napsal: 18 úno 2017, 16:52
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;
)

Napsal: 18 úno 2017, 18:34
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

Napsal: 18 úno 2017, 18:56
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); 
} 

Napsal: 19 úno 2017, 08:48
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).

Napsal: 19 úno 2017, 09:19
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");
	}
}

Napsal: 21 úno 2017, 19:02
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.