Tengo el siguiente código en mi programa de microcontrolador:
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
}
Donde:
Mirando el código ensamblador resultante, noté que está haciendo una comparación de 16 bits (líneas 40-44) donde, estrictamente hablando, solo 8 bits habrían sido suficientes:
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>
Me doy cuenta de que declaré analogValue como int , que de hecho es de 16 bits en AVR, pero...
¿Cómo puedo indicarle al compilador que use la comparación de 8 bits? El IDE de Arduino me permite usar byte , pero avr-gcc por defecto no lo hace.
Consulte esta página para ver el programa completo y su código resultante desensamblado.
EDITAR1:
Cambiar int
a char
cambia el código ensamblador a:
14: 11 24 eor r1, r1 ; r1 = 0
3e: 18 ba out 0x18, r1 ; PORTB
Básicamente saltándose la prueba por completo.
EDIT2: (Gracias: Wouter van Ooijen)
Cambiar int
a unsigned char
cambia el código ensamblador a:
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>
De hecho, creo que una mejor práctica que evita esta ambigüedad arquitectónica es incluir <stdint.h>
y luego usar tipos declarativos como:
y así...
La definición más o menos estándar de un byte en C es 'char sin firmar'.
unsigned
parte hizo el trabajo, char
por sí sola se compila sin advertencias.
yippie
_t
viene?vicatcu
toby jaffey
jon l
Super gato
int
hay 16 bits, dadasuint32_t flag;
las declaracionesflag &= ~0x00004000;
yflag &= ~0x00010000;
se comportarán como se esperaba, peroflag &= ~0x00008000;
se comportarán de manera bastante diferente.