En los tutoriales de AVR a menudo veo:
DDRA |= (1 << PA0);
PORTA |= (1 << PA0);
utilizado en lugar de:
DDRA |= PA0;
PORTA |= PA0;
¿Cuál es el propósito de esto?
PA0
se definirá como 0 por lo que la siguiente línea:
DDRA |= (1 << PA0);
Equivale a desplazar 1 a la izquierda por cero bits, dejando un OR con el valor 1 para establecer el primer bit. Considerando que la siguiente línea:
DDRA |= PA0;
Está haciendo un OR con cero, por lo que no cambiará los registros en absoluto.
DDRA |= 1
. ¿Esperan PA0
cambiar en diferentes entornos?DDRA |= 72;
o DDRA |= (1<<PA6) | (1<<PA3);
?|= 128
más sentido que |= (1 << 7)
. ¿Cómo sabes que establecerá el bit 7 al mirar valores como 128?PA0
que no es muy descriptivo de lo que realmente está haciendo.¿Por qué hacen esto? Probablemente porque todos los demás a quienes piden ayuda o de quienes aprendieron lo hicieron de esa manera. Y porque las definiciones estándar están extrañamente hechas.
Cambiar por un número, típicamente un número decimal, moverá ese valor por tantas posiciones binarias. 1 << PA0
desplazará 1 PA0
a la izquierda. Como PA0
es 0, no hay desplazamiento. Pero dado 1 << 6
1 se convertirá en 0b1000000. Dado 13 << 6
, cambiará 13, en binario que es 0b1101, por 6 para convertirse en 0b1101000000 o 832.
Ahora, necesitamos ver cómo se definen PA0 - PA7. Por lo general, se definen en el encabezado específico para su microcontrolador específico, incluido a través de io.h o portpins.h
#define PA7 7
#define PA6 6
~
#define PA1 1
#define PA0 0
¡Se definen como su posición numérica, en decimal!
No se pueden asignar directamente, como bits, porque no son bits individuales.
Si supusiera que PORTA |= PA7;
PORTA es 0b00000000 (todo apagado), obtendrá:
PORTA = PORTA | PA7;
oPORTA = 0 | 7;
oPORTA = 0 | 0b111
¿Ves el problema? Acaba de encender PA0, PA1, PA2, en lugar de PA7.
Pero PORTA |= (1 << PA7);
funciona como esperas.
PORTA = PORTA | (1 << PA7);
oPORTA = 0 | (1 << 7);
oPORTA = 0 | 0b10000000;
El otro microcontrolador mejor, el MSP430, tiene una definición estándar de bits como:
#define BIT0 (0x0001)
#define BIT1 (0x0002)
~
#define BIT6 (0x0040)
#define BIT7 (0x0080)
Estos se definen como su posición binaria, en hexadecimal. BIT0 es 0b0001, no como PA0, que es 0. BIT7 es 0b10000000, no como PA7, que es 0b111.
Entonces, las asignaciones directas P1OUT |= BIT7;
funcionarán de la misma manera P1OUT |= (1 << 7);
.
Su pregunta ya ha sido respondida, pero quiero presentar una alternativa que fue demasiado para un comentario. Una de las primeras cosas que hago cuando empiezo un proyecto incrustado es definir mi conjunto de bits y borrar macros.
#define bitset(var,bitno) ((var) |= 1 << (bitno))
#define bitclr(var,bitno) ((var) &= ~(1 << (bitno)))
Usando las macros, su código se convierte en:
bitset(DDRA,0);
bitset(PORTA,0);
El resultado final es una instrucción de conjunto de bits en ensamblador.
Eche un vistazo aquí: http://nongnu.org/avr-libc/user-manual/FAQ.html#faq_use_bv
Esas macros se usan cuando se configuran bits particulares en un registro. Por ejemplo: si PORTA tiene 8 bits de ancho, entonces PA0 es el bit más bajo, PA7 es el más alto. Para establecer PA0 en 1, debe escribir ("o escribir") 0x01 en el registro. Si desea configurar PA2, necesita un valor que en binario tenga un uno en el lugar correcto, para PA2 será 0x04.
La gente no quiere recordar qué bit tiene una posición particular (ya que otros registros pueden tener diferentes nombres de bits, por ejemplo, CS12, CS10, ADSC, etc.), por lo que usan nombres más abstractos. En lugar de escribir: PORTA = 0x04, escribe PORTA = _BV (PA2) e instantáneamente sabe que el pin PA2 se volverá alto.
Armanda
usuario_1818839
PortA(PAO) := True;
krambo
rojín
mels
_BV()
macro para obtener el "valor de bit" (p. ejPORTA |= _BV(PA0);
., personalmente creo que hace que el código sea más legible, pero las opiniones difieren bastante en la comunidad).JDługosz