Technik: Samozřejmě to mělo být ±0.1V. Displej mi zobrazuje jako “00.0”. Takže jsem se zas upsal.
Záludnost operáturu >> ? NEvim jak ostatní programátoři, ale já vím co je posuv vpravo.
“Není definován pro signed” - myslím si že vím docela přesně, co se stane když použiju >> nebo << na signed proměnnou. Znaménko se uchovává v MSB, 7mém bitu. (u signed char což je 8bit proměnná). Ale tu v podstatě nastává menší problém. Takže asi jo, je to záludné. AVR mají celkem 5 instrukcí pro “<< a >>”: ROL, ROR, LSL, LSR, ASR.
ROL/ROR j rotace, kdy C->B7->B6…B0->C (a obráceně)
LSL a LSR: 0->B7…B0->C (a obráceně)
a ASR je právě ta výjmka. Překladač by právě mohl při použití operátoru “>>” použít tu instrukci ASR, která by správně shiftnula vpravo, a zachovala znaménko v B7. Jediná záludnost je ta, jestli překladač použije ROR/LSR nebo to správnější ASR. Škoda právě, že do AVR neudělali ASL. (to samé, ale na druhou stranu, i když by to bylo trochu složitější, protože B6 by se musel posunout do C, a B7 zachovat, tam by to bylo trošku ošemetné. (Stejná škoda, že AVR nemají rychlé instrukce dělení…)
Takže závěrem téhle menší úvahy bych řekl, že při použití “<<” na signed proměnou je výsledek jasný co se stane, a při použití “>>” to záleží jak si to přebere compiler.
To je právě jedna z věcí, co se mi na C pro AVR nelíbí. Nikdy nemáš jisté, co s tím kde překladač provede.
Třeba mi vrtá hlavou ještě tohle, na což bych rád znal odpověď:
Zápis třeba:
PORTA = (1<<PA0)|(1<<PA5);
zde by měl překladač při překladu vyhodnotit výraz " (1<<PA0)|(1<<PA5);" do konstantní hodnoty, a tu pak přes LDI a OUT nacpat do PORTA. Tohle je podle mě docel pochopitelné, ale nyní už tápu:
PORTA |= (1<<PA0)|(1<<PA5);
Co zde udělá překladač? Napadají mě 3 možnosti:
ta jedna blbá, která by pak znefunkčnila program, je to, že by udělal to samé co v předchozím případě, což je asi blbost.
Druhá možnost:do pomocného registru si nasype hodnotu PORTA, kterou pak přes instrukci ORI (logiocal or with immediate) opravdu “oroval” s tou konstantou, a pak zpět navrátil hodnotu do PORTA. To je ta podle mě nejpravděpodobnější varianta.
a ta 3tí, nejmíň pravděpodobná situace: překladač by mohl použít instrukci SBI (Set Bit in I/O register). Zde by právě mohl tímto překladač občas ušetřit čas mcu, ale záleží, kolik bitů by se muselo nastavit. Pokud bychom nastavovali ty dva bity jak jsem dával příklad, program by měl vypadat asi takhle:
in R16, PORTA
ori R16, 0b00100001
out PORTA, R16
nebo ta rychlejší varianta:
sbi PORTA, 5
sbi PORTA, 0
Sice už je to mírně offtopic, ale dík za vysvětlení. Docela mi to pomůže při dalším programování.
EDIT: Můžete mi ještě podat přesnější vysvětlení toho zaokrouhlování?
volty = (v_cnt+16)>>5;
Jako jak polovina dělitele? Co to udělá?