C - chyba podmínky, verifikace XORWF divisor, W, ACCESS

Dobrý den,
Se v tom nějak plácám. Prosím znalce, kde dělám chybu (MPLABx, Hitech 9.80)

char kopieBytu;
#define SPI_DATA_IN PORTCbits.RC4

if ((kopieBytu & 0b10000000) != SPI_DATA_IN) //SPIverifi
{ chyba verifikace }

přeloží jako
Rozbor pokud má verifikovat (na vstupu RC4 je HI, v kopieBytu = 0b10000000) mi vyhodnotí jako chybu verifikace, což je špatně.

! if ((kopieBytu & 0b10000000) != SPI_DATA_IN) //SPIverifi
0x1F48: SWAPF PORTC, W, ACCESS (1001000 W=00001001)
0x1F4A: ANDLW 0x1 (W=00000001)
0x1F4C: MOVWF divisor, ACCESS (0x5D) (W do 0x5D)
0x1F4E: MOVF quotient, W, BANKED (0x82) (kopieBytu do W=10000000)
0x1F50: ANDLW 0x80 (W=10000000)
0x1F52: XORWF divisor, W, ACCESS (0x5D) (10000000 XOR 00000001 = 10000001) ???
0x1F54: BTFSS STATUS, 2, ACCESS

Se mi nezdá řádek 0x1F52, ten přeci o podmínce nic neříká.
Díky za reakce. Míra

:arrow_right: administrator: přejmenováno z "C - chyba podmínky"

To by chtělo ten program celej, protože takhle nikdo neví, v čem a kde to používáš, jak je co definovaný atd. To je nějaká PIC18F?

Jinak je to asi spíš pro Pandu38, to je místní C guru :slight_smile:

Panda38 PICy moc neovládá.

…Aha ale teď vidím - ten řádek s XOR dělá porovnání bajtů - pokud jsou si rovné, bude výsledkem operace nula. No a ony si nemohou být rovné, protože ty testované bity jsou na různých bitových pozicích. Musely by se narotovat na stejnou pozici. Obsah SPI_DATA_IN je v bitu 0, proto se i výsledek kopieBytu & 0b10000000 musí narotovat na pozici bitu 0 - buď o 7 bitů doprava nebo o 1 bit doleva.

Jo, jo, jo,
Jsem žil v bludu, že (kopie&0x80) hodí true/false. Míra

To by se muselo napsat např. (také to tak může stačit):

if (((kopieBytu & 0b10000000)!=0) != (SPI_DATA_IN!=0))

na HW-news mi poradili něco podobného
if (((kopieBytu & 0x80) != 0) != SPI_DATA_IN)
akorát si to nějak neumím dát v hlavě dohromady. Jestliže kopieBytu & 0x80 se nerovná 0 se nerovná SPI_DATA_IN? jak to přečíst. Poradíte klíč? Míra

Logická operace != má za výsledek číslo 0 nebo 1 (= FALSE nebo TRUE). Proto výsledkem ((kopieBytu & 0x80) != 0) bude číslo 1, je-li hodnota bitu 7 nenulová, nebo 0, je-li hodnota bitu 7 nula. Zřejmě tedy je PORTCbits.RC4 také myšleno jako logická hodnota, také výstupem bude 0 nebo 1, proto se ta dvě čísla mohou spolu porovnat na shodu.

teď jsem byl ve “vaně” a tam mi to docvaklo, že to je vlastně převod na false/true.
Ještě mi nedocvakává, proč tam není ((kopieBytu & 0x80) == 0)

už to docvaklo. protože když by byla kopieBytu&0x80 == 0 tak by to bylo TRUE!!! proto ta nerovnost( vlasně negace ) Díky Míra

Ano, byla by to opačná hodnota výrazu, což by také šlo použít (tedy použít negaci):

if (((kopieBytu & 0b10000000)==0) != !SPI_DATA_IN)

Taky Míra. :smiley:

Je to celé nějaké zamotané:

Pokud je SPI_DATA_IN definováno jako PORTCbits.RC4, tak je vlastně čten stav bitu 4 (0b000x0000) a v podmínce se maskují bity (0…6). Je vlastně testován jen bit 7 a následně porovnán s bitem 4 což nemůže nikdy dát správný výsledek.

Nemělo to celé fungovat takhle:

if( (kopieBytu & SPI_DATA_IN) == 0) {proveď program pokud RC4 == 0 a kopieBytu = 0bxxx0xxxx}

nebo
if( (kopieBytu & SPI_DATA_IN) == 16) {proveď program pokud RC4 == 1 a kopieBytu = 0bxxx1xxxx}

tj. test bitu 4 a podle hodnoty provést příslušný program.

Jak jsem pochopil z listingu, tak překladač vrátí zápis PORTCbits.RC4 (tj. přístup k jednotlivým bitům portu) jako logickou hodnotu 0 nebo 1 - narotuje testovaný bit na pozici bitu 0 a zamaskuje.

PORTCbits.RC4 je bitová hodnota, proto nabývá 1 or 0, proto musím zařídit, aby (kopieBytu & 0x80) nenabývalo hodnoty 0x80, ale 1 or 0, to udělá právě to != . Taky mě to zarazilo, člověk není zviklí, že ve výrazu může být několikrát “se nerovná”. Jde o to si ten model myšlení vměstnat do hlavy. na ((kopieBytu & 0x80) =! 0) se musí pohlížet tak, že ve výsledku je to výraz, který se na venek v podmínce if tváří jako True/False, proto se může znovu použít ==, != atd. Taky jsem o tom jenom kdysi četl, ale použil až teď. Včera mi to dvakrát za sebou != bylo divný, po pochopení “jak to funhuje” je to logické. Míra

=! je prakticky stejná operace jako jiné - např, sčítání nebo &&, jen jsou různé priority operací a různé typy operandů a výstupů.

Porovnávat výsledky porovnání ale není tak úplně správné, nemělo by se na to navykat. Tady to funguje, ale jinde nemusí. Jde o to, že logická hodnota je v C definovaná jako “FALSE je číslo 0” a “TRUE je číslo různé od nuly” (to až u pozdějšího typu bool jsou hodnoty jednoznačné). Což má za následek - může se porovnávat např. s hodnotou 0x10, což sice má logickou hodnotu TRUE, ale může se porovnávat s jiným číslem TRUE (např. 1), což by bylo špatně. TRUE je interval hodnot a ne hodnota. Logické hodnoty se mohou porovnávat na shodu jen v případech, kdy se opravdu ví, že nemohou nastat nestandardní hodnoty. Např. se musí použít operace !=, u které se ví že bude mít výsledkem 0 nebo 1.

if ((kopieBytu & 0b10000000) != SPI_DATA_IN) //SPIverifi

Tuto funkci bych rozepsal jako:
výsledek: (kopieBytu & 0b10000000) = 0 nebo 128.

Podmínka :

  1. if (0 != 16) (0 není rovna 16) = TRUE
  2. if (128 != 16) (128 není rovno 16) = TRUE

Jediný stav kdy by byl výsledek FALSE
if (16 != 16) (16 je rovno 16) = FALSE

Takže pro hodnotu kopieByte = [0…255] je podmínka vždy = TRUE

pozor, na začátku je
#define SPI_DATA_IN PORTCbits.RC4
SPI_DATA_IN může být pouze 1 or 0

Omlouvám se. Díky za upozornění, nějak jsem si to celé blbě přebral :blush: