I have the following code in my microcontroler program:
int analogValue = ADCH; // ADC Data Register
//
// Simple analog comparator.
// If analogValue lower than threshold then toggle output high,
// Otherwise toggle it low.
//
if ( analogValue > 128 ) {
PORTB = 0; // Port B Data Register
} else {
PORTB = _BS( outputPin ); // Port B Data Register
}
Where:
- ADCH is the register that contains the value from the ADC
- PORTB is a dital output port that toggles an LED
Looking at the resulting assembly code, I noticed that it is doing a 16 bit compare (lines 40-44) where strictly speaking only 8 bits would have been sufficient:
40: 90 e0 ldi r25, 0x00 ; 0
42: 81 38 cpi r24, 0x81 ; 129
44: 91 05 cpc r25, r1
46: 14 f0 brlt .+4 ; 0x4c <__SREG__+0xd>
48: 18 ba out 0x18, r1 ; PORTB
4a: f5 cf rjmp .-22 ; 0x36 <__CCP__+0x2>
4c: 28 bb out 0x18, r18 ; PORTB
4e: f3 cf rjmp .-26 ; 0x36 <__CCP__+0x2>
I realize I declared analogValue as int, which indeed is 16 bit on AVR, but …
How can I instruct the compiler to use 8 bit comparison? The Arduino IDE allows me to use byte, but avr-gcc by default doesn't.
Check this page for the complete program and its disassembled resulting code.
EDIT1:
Changing int
to char
changes the assembly code to:
14: 11 24 eor r1, r1 ; r1 = 0
3e: 18 ba out 0x18, r1 ; PORTB
Basically skipping the test entirely.
EDIT2: (Thnx: Wouter van Ooijen)
Changing int
to unsigned char
changes the assembly code to:
3c: 85 b1 in r24, 0x05 ; ADCH
3e: ...
40: 87 fd sbrc r24, 7 ; compare < 128 (well optimized)
42: 02 c0 rjmp .+4 ; 0x48 <__SREG__+0x9>
44: 18 ba out 0x18, r1 ; 24
46: f7 cf rjmp .-18 ; 0x36 <__CCP__+0x2>
48: 98 bb out 0x18, r25 ; 24
4a: f5 cf rjmp .-22 ; 0x36 <__CCP__+0x2>
Best Answer
I actually think a better practice that avoids this architectural ambiguity is to include
<stdint.h>
then use declarative types like:and so on...