6
\$\begingroup\$

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>
\$\endgroup\$
18
\$\begingroup\$

I actually think a better practice that avoids this architectural ambiguity is to include <stdint.h> then use declarative types like:

  • uint8_t for unsigned 8-bit integers
  • int8_t for signed 8-bit integers
  • uint16_t for unsigned 16-bit integers
  • uint32_t for unsigned 32-bit integers

and so on...

\$\endgroup\$
  • \$\begingroup\$ This appears to work (checked the assembly code again). Wasn't familiar with these types at all. Where does the _t come from? \$\endgroup\$ – jippie Jul 7 '12 at 20:01
  • 3
    \$\begingroup\$ _t indicates, conventionally, that its naming a type \$\endgroup\$ – vicatcu Jul 7 '12 at 20:25
  • 3
    \$\begingroup\$ These are standard fixed width integer types, introduced in C99. You may need to #include <stdint.h>. en.wikipedia.org/wiki/C_data_types#Fixed_width_integer_types \$\endgroup\$ – Toby Jaffey Jul 7 '12 at 23:01
  • 2
    \$\begingroup\$ +1. I use this to remove any ambiguity and for ultimate portability \$\endgroup\$ – Jon L Jul 8 '12 at 2:05
  • \$\begingroup\$ A danger when using such types is that expression types are often non-portable in surprising ways. For example, on a system where int is 16 bits, given uint32_t flag;, the statements flag &= ~0x00004000; and flag &= ~0x00010000; will behave as expected, but flag &= ~0x00008000; will behave rather differently. \$\endgroup\$ – supercat Jan 22 '15 at 21:45
8
\$\begingroup\$

The more-or-less standard definition of a byte in C is 'unsigned char'.

\$\endgroup\$
  • \$\begingroup\$ Ah the unsigned part did the job, char on it's own compiles without warnings. \$\endgroup\$ – jippie Jul 7 '12 at 18:23
  • \$\begingroup\$ A famous C 'gotcha' is that the compiler is free to interpret 'char' as either 'signed char' or 'unsiged char', so the effective range of plain 'char' that you can count on is 0..127. Use plain 'char' only for 7-bit ASCII, never for anything else. \$\endgroup\$ – Wouter van Ooijen Jul 7 '12 at 18:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.