AVR programación en C – 05 Uso de Registros como Parámetros

Hola de nuevo a todos, en este post trataré de hablar de cómo usar los registros de propósito específico (SFR’s) de los microcontroladores AVR como parámetros en funciones o clases (en C++), esto puede resultar muy útil a la hora de crear librerías que manipulen, por ejemplo, los puertos del microcontrolador para llevar acabo una tarea, como el uso de un Display LCD, al cual lo podríamos conectar a cualquier puerto del micro y decir en las funciones a que puerto y a que pines se conecta, haciendo el código muy portable para otros modelos de AVR’s.

Pero… ¿qué es un registro en los AVR’s?

Como bien se mencionó en el Tutorial de Puertos de E/S:

“Un registro es un espacio de almacenamiento especial del microcontrolador que esta relacionado (conectado) a algún periférico y que cada bit representa el funcionamiento o estado del mismo. Los registros tienen un nombre único de acuerdo a su funcionamiento, y los bits individuales del registro también suelen tener un nombre único y un propósito específico.”

En los microcontroladores AVR, como en otros muchos micros, los registros están mapeados a memoria, es decir, que se accede a ellos como si de la memoria RAM se tratase, y cada registro tiene una dirección única mediante la cual se puede acceder. La mayoría de los registros son de escritura y lectura, algunos son de solo lectura y otros de solo escritura.

El compilador avr-gcc maneja los registros como apuntadores a memoria, con esto cada registro es una dirección de memoria y esta dirección varía de un modelo de micro a otro, aunque varios microcontroladores contengan los mismos registros (ejemplo DDRB) no es obligatorio que se encuentren en la misma dirección, para eso se usa la librería <avr/io.h>que contiene todas las definiciones de los registros y de los bits en registros con un nombre simbólico común para muchos microcontroladores, pero con un mapeo de direcciones distinto.

Adentrándonos en la librería avr-libc veremos que existen una serie de macros (una tras otra) para declara registros SFR, pero al final termina en una dirección de memoria, como se mencionó anteriormente, que es un puntero a volatile uint8_tuint8_t a su ves es un typedef de unsigend char declarado como volatilese declara volatile para decir al compilador que es una dirección de memoria y que no se debe optimizar, para que no cambie su valor a la hora de compilar.

Ahora, si deseamos pasar un registro a una función o a un método, bastará con que el parámetro a recibir sea un apuntador volatile de unsigned char  (o uint8_t). Haciendo un ejemplo muy ilustrativo (solo como referencia):

/*Esto es para C*/
void LCD_Init(volatile unsigned char* DDRx, volatile uint8_t* PORTx){

    *DDRx=0xFF;
    *PORTx=0x0;
    .
    .
    .
}

/*Esto es para C++*/
void LCD_Init(volatile unsigned char& DDRx, volatile uint8_t& PORTx){

    DDRx=0xFF;
    PORTx=0x0;
    .
    .
    .
}

/*La llamada a la función sería:*/
int main(void) {

   LCD_Init(DDRB,PORTB); //C++
   LCD_Init(&DDRB,&PORTB); //C
   .
   .
   .
}

Como ven, es relativamente sencillo pasar registros SFR a las funciones, en otro post usaremos esta habilidad para crear una librería que manipule un Display LCD de 16×2 caracteres configurando el puerto y los pines a los que está conectado.

Hasta aquí el post, espero poder hacer mas aportes en los próximos días, o semanas, o meses…. estaré a en búsqueda de nuevos admins que puedan escribir en este blog, para que valla creciendo y se enriquezca cada vez mas el contenido.

Hasta la próxima!

Fred!

LINK:  Referencia de paso de registros como parámetros

Dejar un comentario

Crea una web o blog en WordPress.com

Subir ↑