Escribir un unico bit de un registro de un LPC1768 basado en Cortex M3

Hola a todos. Tengo una duda que me gustaría resolver. Son de un laboratorio pasado de la universidad.

Cuando trabajo con una placa de prototipo de un LPC1768 basada en un Cortex M3, sobre Keil me encuentro que por ejemplo en un registro cualquiera de 32 bits, si quiero modificar un único valor del registro tengo que estar haciendo perrerías para poner lo que yo quiera sin tocar los demás valores del registro. Os pongo ejemplos cualquiera de las cosas que hacía durante las practicas para por ejemplo encender un led conectado a un pin de uno de los puertos.

LPC_GPIO1->FIOPIN ^= 1<<29;
LPC_GPIO1->FIODIR |= 1<<29;
LPC_GPIO1->FIOPIN = 1 << 21; (esto me vale si solo quería poner en alto el pin 21 sin importar lo demás ya que escribe 0 en todo lo que no sea el 21)


Sin embargo acabo de caer en la cuenta que con arduino por ejemplo, tu puedes fácilmente poner un digitalWrite( 4 , HIGH) y haces que el pin 4 se vaya a alto o a bajo según como quieras sin afectar a los otros pines ni hacerles referencia para que se queden iguales

Que esta pasando? Acaso arduino usa un puerto diferente para cada puerto? No creo ¿como lo hace?

Y como puedo hacer yo eso con mi LPC1768? Si quiero modificar el valor de un solo pin arriba o abajo de manera sencilla como con arduino? Como lo haríais?

Gracias
 
Hay dos maneras que yo conozco.

Uno, definir mascaras que tienen todos los bits encendidos o apagados salvo el que quiero afectar. Para encender un bit especifico hago OR al registro con la mascara que tiene ese solo bit encendido. Para apagar un bit hago AND al registro con la mascara que tiene todos los bits encendidos menos ese.

La otra manera es definir estructuras con campos de bits (structures with bit fields). Fijate en el manual si encontras ejemplos para tu compilador. Yo uso otro procesador pero la idea es esa.
 
Se usa el registro Set o clr.

Por otro lado, no veo que tan difícil sea usar una máscara, más aún si se lo combina con un define.

PHP:
#define LED_1 (1<<25)    //Puerto 3.25
#define LED_2 (1<<26)    //Puerto 3.26

....
int main()
{    
    LPC_PINCON->PINSEL7=0;            //Declaro al puerto 3 como GPIO -> La función de dichos puertos se manejan a través del PINSEL7 -> Bits 19:18 Puerto 3.25 y Bits 21:20 Puerto 3.26
    LPC_GPIO3->FIODIR|=LED_2|LED_1;    //Defino al puerto como salida 
    
    LPC_GPIO3->FIOSET=LED_1;    //Pongo en 1 el puerto => led apagado
    LPC_GPIO3->FIOCLR=LED_2;    //Pongo en 0 el puerto => led encendido
  ...
}

Para más detalles, fijate acá:

https://www.forosdeelectronica.com/f24/aporte-tutorial-arm-cortex-m3-lpc1768-96797/
 
Se usa el registro Set o clr.

Por otro lado, no veo que tan difícil sea usar una máscara, más aún si se lo combina con un define.

PHP:
#define LED_1 (1<<25)    //Puerto 3.25
#define LED_2 (1<<26)    //Puerto 3.26

....
int main()
{    
    LPC_PINCON->PINSEL7=0;            //Declaro al puerto 3 como GPIO -> La función de dichos puertos se manejan a través del PINSEL7 -> Bits 19:18 Puerto 3.25 y Bits 21:20 Puerto 3.26
    LPC_GPIO3->FIODIR|=LED_2|LED_1;    //Defino al puerto como salida 
    
    LPC_GPIO3->FIOSET=LED_1;    //Pongo en 1 el puerto => led apagado
    LPC_GPIO3->FIOCLR=LED_2;    //Pongo en 0 el puerto => led encendido
  ...
}

Para más detalles, fijate acá:

https://www.forosdeelectronica.com/f24/aporte-tutorial-arm-cortex-m3-lpc1768-96797/

Tengo dos preguntitas, perdona si son basicas pero hace ya tiempo que dí ese laboratorio.

Parece que tu usas set y clr que creo que soluciona mi problema. Yo usaba FIOPIN, y por tanto tenía que escribir el registro entero. Osea, si hacia LPC_GPIO3->FIOPIN=LED_1 lo que estaría haciendo seria escribir en el puerto3 un 0 en todos los pines, osea apgarlos, menos en el 25 que lo encendería. Con set y clr es mucho mas comodo ahora que lo veo ya que sabiendo que set solo enciende y clr solo apaga me soluciona la vida. ¿me equivoco?

Lo segundo. Que significa el "|=", no soy capaz de encontrarlo en google, imagino por el sistema de busqueda. NO recuerdo ahora mismo y seguro que es una tontería pero no lo encuentro.

Muchas gracias.
 
...yo usaba FIOPIN

Ese registro normalmente se lo usa como lectura para saber el estado de los pines.

Si lo escribís, tenés que usarlo en conjunto con el registro FIOMASK.

Con set y clr es mucho mas comodo ahora que lo veo ya que sabiendo que set solo enciende y clr solo apaga me soluciona la vida. ¿me equivoco?

Exacto, todo bit en 1 que pongas, seteará o borrará dicho bit, ejemplo:

PHP:
...
LPC_GPIO3->FIOSET=(1<<25);
LPC_GPIO3->FIOCLR=(1<<26);
...

Con la primera operación seteo el bit 25 del puerto 3 y con la segunda borro el bit 26 del puerto 3, sin alterar el resto de los bits.

Lo segundo. Que significa el "|=", no soy capaz de encontrarlo en google, imagino por el sistema de busqueda. NO recuerdo ahora mismo y seguro que es una tontería pero no lo encuentro.

Es una doble operación:

1- "|" realiza una OR lógica.
2- "=" asigna un valor a una variable/registro.

En conjunto, esa operación sería similar a esta:

PHP:
variable_1=variable_1|variable_2;  //Opción 1
...
variable_1|=variable_2;  //Opción 2

Es decir, "variable_1" tomará el resultado de hacer una OR lógica del viejo valor de "variable_1" y "variable_2". Obviamente el viejo valor de "variable_1" se pierde.
 
Atrás
Arriba