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>
asked Jul 7, 2012 at 17:52
\$\endgroup\$

2 Answers 2

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...

answered Jul 7, 2012 at 19:54
\$\endgroup\$
5
  • \$\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\$ Commented Jul 7, 2012 at 20:01
  • 3
    \$\begingroup\$ _t indicates, conventionally, that its naming a type \$\endgroup\$ Commented Jul 7, 2012 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\$ Commented Jul 7, 2012 at 23:01
  • 2
    \$\begingroup\$ +1. I use this to remove any ambiguity and for ultimate portability \$\endgroup\$ Commented Jul 8, 2012 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\$ Commented Jan 22, 2015 at 21:45
8
\$\begingroup\$

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

answered Jul 7, 2012 at 17:59
\$\endgroup\$
2
  • \$\begingroup\$ Ah the unsigned part did the job, char on it's own compiles without warnings. \$\endgroup\$ Commented Jul 7, 2012 at 18:23
  • 1
    \$\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\$ Commented Jul 7, 2012 at 18:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.