Sida 1 av 2
Vad innebär "for (i=0x80;i>0;i/=2)" (C-program
Postat: 22 november 2007, 09:26:53
av PHermansson
Har börjat fundera på att koppla en SHT11 (fuktighetsmätare) till en PIC18F4450. Har kollat lite på den exempelkod som finns (
http://www.sensirion.com/en/02_sensors/ ... _sht11.htm).
Har dock kört fast tämligen omgående

Vad har 'i/=2' för funktion?
Kod: Markera allt
for (i=0x80;i>0;i/=2) //shift bit for masking
{ if (i & value) DATA=1; //masking value with i , write to SENSI-BUS
else DATA=0;
SCK=1; //clk for SENSI-BUS
_nop_();_nop_();_nop_(); //pulswith approx. 5 us
SCK=0;
}
Postat: 22 november 2007, 09:35:01
av thepirateboy
Det blir väl samma sak som att skifta värdet för "i" ett steg till höger, 0x80, 0x40, 0x20 osv.
Postat: 22 november 2007, 09:35:59
av oJsan
variabeln i delas med två varje varv som for-loopen körs.
Har du tur så översätter kompilatorn det hela till en "högerskift".
Edit: Piraten hann före...
Postat: 22 november 2007, 09:40:18
av oJsan
Hmm... lite optimering som borde fungera:
Kod: Markera allt
for (i=0x80;i>0;i/=2) //shift bit for masking
{
DATA=(i & value); //write to SENSI-BUS
SCK=1; //clk for SENSI-BUS
_nop_();_nop_();_nop_(); //pulswith approx. 5 us
SCK=0;
}
Postat: 22 november 2007, 10:01:38
av speakman
"i/=2;" kan också göras mer begripligt med "i >>= 1;"
Ger antagligen ingen skillnad i den kompilerade koden. Skulle den det så blir det åt det bättre.

Postat: 22 november 2007, 10:13:05
av AndLi
oJsan skrev:Hmm... lite optimering som borde fungera:
Kod: Markera allt
for (i=0x80;i>0;i/=2) //shift bit for masking
{
DATA=(i & value); //write to SENSI-BUS
SCK=1; //clk for SENSI-BUS
_nop_();_nop_();_nop_(); //pulswith approx. 5 us
SCK=0;
}
Det blir ju en rätt stor skillnad...
I orginalkoden blir ju DATA alltid 1 (om bitten är satt i value), men i den optimerade koden kommer DATA vara beroende av värdet av i, DATA kommer istället för att bli 1 bli 0x80,0x40,0x20 osv...
så frågan är ju hur DATA är definierat,
Postat: 22 november 2007, 10:20:16
av PHermansson
Tack för snabba svar! Då har man lärt sig något nytt idag med

DATA är definierad som en I/O-pinne som är kopplad till SHT11'an, så den optimeringen fungerar nog inte så bra. Det är ett I2C-liknande interface som används, SCK är klockan och DATA är just data.
Postat: 22 november 2007, 10:21:12
av speakman
Om den ändras till:
DATA=((i & value) == 1);
så borde det bli som oJsan tänkte...
Postat: 22 november 2007, 12:51:56
av GrodanB
Sen vill jag mena att man litar aldrig på en kompilator att den skall göra nått smart. Vet man att det snabbaste sättet är en shift, ANVÄNDER man en shift!
Alltså skall man använda shift och inte division i denna kod.
Kompilatorernas "smarthet" beror inte bara på tillverkaren utan också på hur du har satt upp kompileringsflaggorna...
Sen är jag lite skeptisk till spekamans förslag till förbättring... den beror på hur kompilatorn tolkar det hela...
Genom att göra en boolsk bitoperand och sedan en logisk så blir ju bara DATA = 1 i några fall... dvs. då resultatet av den boolska operanden blir 1 och endast då. Så jag vill säga att den skall i så fall vara:
Eller har jag fel??? Inte otroligt i så fall...

Postat: 22 november 2007, 13:40:23
av speakman
Din variant är givetvis att föredra. Så hade jag helst också gjort, var nog lite för snabb med mitt inlägg bara.

Postat: 22 november 2007, 13:46:13
av oJsan
Om DATA är deklarerad som boolean (vilket var ett dumt antagande av mig) så fungerar både min och speakmans förslag (och GrodanB's).
En boolsk variabel blir SANN om ett tal skiljt ifrån 0 tilldelas den (någon som vet en annan definition som används i någon kompilator?).
bool b = (unsigned short)123; kommer alltså bli SANN.
Men GrodanB har ju rätt, hans omskrivning fungerar oavsett vad DATA är deklarerad som. Speakmans skulle fungera om man skriver såhär:

Postat: 22 november 2007, 13:50:26
av speakman
bool är ingen datatyp i C, samt !0 == 1 så min hade fungerat oavsett.
Men av logiska själ skulle jag föredra grodans variant.
Postat: 22 november 2007, 14:06:26
av GrodanB
!FALSE är lika med 1 men utdatat från (i & value) operanden är inte 0 eller 1 utan 0 eller nått annat.
Det finns de som använder ~ istället för ! i if satser men det är livsfarligt...
Så eran kod fungerar bara om man använder dv.s
För då kommer utdatat från parantesen vara definierat som 0 eller 1...
Men tanken är ju att maska bitar ur value så det är ju inte rätt.
För att kunna göra som ni föreslår får man shifta ner den utmaskade biten för att sedan sätta den till data.
Personligen hade jag nog gjort så... Dvs. shifta och sen maska med 1 och tilldela DATA resulatet... Fast jag skulle ha kollat vilket som blir minst assembler instruktioner först.
Postat: 22 november 2007, 14:35:13
av speakman
Samma tankevurpa igen. Hade det funkat, hade även oJsans version funkat.
Ett helt annat alternativ är:
DATA = i & value ? 1 : 0;
Om man vill vara på den säkra sidan.

Postat: 22 november 2007, 15:54:21
av GrodanB
Men det är ingen optimering... vill minnas att det inte ens är C

(C++ notation av en ifsats om jag inte minns fel.)
Är exakt samma som
Kod: Markera allt
if (i & value ){
DATA = 1;
} else {
DATA = 0;
}
(Kunde man inte indentera med TAB i CODE block? Använde SPACE)
Det är som att optimera genom att inte använd fetstil... Eller långa varibelnamn...

Få kompilatorer genererar olika kod för detta.