23 de marzo de 2009

Práctica 1 · Secuencia de leds

Esta primera práctica tiene como objetivo encender en secuencia todos los leds de la placa Easy8051B. En este programa no hay interacción con el usuario, el programa se graba en el microcontrolador e inmediatamente los leds se van encendiendo en secuencia para siempre.



Vamos a encender todos los leds en secuencia, desde el puerto P0 al puerto P3, por lo tanto necesitaremos definir los registros que vamos a necesitar con SFR como ya vimos en los ejercicios de clase:

sfr P0=0x80;
sfr P1=0x90;
sfr P2=0xA0;
sfr P3=0xC0;

Importante: La placa EASY8051B trabaja con lógica inversa, es decir, para iluminar todos los LEDS del puerto P0, tendremos que escribir "P0=0x00" (coloca el valor 11111111 en el puerto). Por lo tanto hay que pensar 'al revés' ;-)

Tu programa en C tendrá la siguiente estructura:
------------------------
sfr P0=0x80;
sfr P1=0x90;
sfr P2=0xA0;
sfr P3=0xC0;


void main (void)
{ ...aquí escribirás el programa... }
------------------------

Teniendo en cuenta el asunto de la lógica negada, si queremos empezar con todos los LEDS apagados en los puertos debemos inicializarlos todos con el mismo valor=0xFF, que al negarse deja todos los LEDS a 000000 (apagados).

Definimos una variable tipo char (8 bits) que asignaremos para inicializar todos los puertos:

void main (void)
{

unsigned char leds=0xFF;
P0=leds; P1=leds; P2=leds; P3=leds;
}

Si lo dejamos aquí, el programa no hará más que apagar todos los LEDS y terminaría, con lo que no veríamos nada. De momento haremos que el programa no termine nunca, que se quede en un bucle infinito, para ello utilizamos la intrucción de C while que permite repetir las instrucciones de un bucle hasta que la condición que comprueba no se cumpla. Veamos como queda:

void main (void)
{
unsigned char leds=0xFF;
while(1) { P0=leds; P1=leds; P2=leds; P3=leds; }
}


De este modo la condición del while siempre es cierta (1=TRUE) y el bucle nunca acabará. No obstante debes tener en cuenta que cuando se graba un programa en el microcontrolador, por defecto, se ejecutará aunque no incluyas el while en el bloque main, pero si te aseguras mejor.

Hasta aquí no cambia nada, los LEDS estarán apagados, para que se aprecie el efecto carrusel, habrá que ir encendiendo uno a uno los bits de cada puerto, esto lo conseguiremos desplazando el registro completo con el operador ">>", al aplicarlo a los puertos, empezarán a entrar ceros por la derecha (y como es lógica inversa..encendiendo los LEDS).

void main (void)
{ unsigned char leds=0xFF;
while(1) { P0=leds; P1=leds; P2=leds; P3=leds; leds=leds>>1; }
}


La cosa es que si lo dejamos así, cuando hayan entrado todos los "0" y se hayan iluminado todos los LEDS, se quedará todo iluminado y ya no sucederá nada, habrá que hacer que se haga 8 veces (los 8 LEDS de cada puerto) y que vuelva a empezar apagándolos todos:

void main (void)
{ unsigned char leds=0xFF; int i=0;
while(1)
{
leds=0xFF;
for (i=0;i<=8;i++) { P0=leds; P1=leds; P2=leds; P3=leds; leds=leds>>1; }
}
}


El asunto es que el microcontrolador ejecuta tan rápido las instrucciones que no podemos ver como se iluminan los LEDS y los vemos todos iluminados. Necesitamos añadir un retardo cada vez que se enciende un LED para que nos dé tiempo a verlo, pero esto es la segunda práctica.

-------------------------------------------------
Nota 1: Ciudado con los bucles "for"..
- MAL -> for(i=0;i++;i<=8) - BIEN -> for(i=0;i>=8,i++)...recuerda primero siempre va la condición.
Nota 2: Comprueba bien las direcciones de los puertos en las tablas, si defines con SFR un registro en una dirección incorrecta, tu programa no funcionará.
Nota 3: Puedes utilizar la instrucción while(1) para crear un bucle infinito.
Nota 4: Cuando necesites una variable de 8 bits, puedes utilizar el tipo char, aunque 'asociemos' a texto, el tipo char define una variable numérica de 8 bits, usada generalmente para almacenar códigos de letras (códigos ASCII), pero en realidad almacena un número. Intenta usar siempre las variables ajustadas al tamaño de los datos, si utilizas int para el ejemplo de la práctica, estarás desaprovechando un montón de bits. Utilizamos 'unsigned' para aprovechar los 8 bits para el número. Si no ponemos nada, se reserva el bit de mayor peso para el signo y por lo tanto en la variable unsigned char podemos almacena un número menor.
Nota 5: Rotar el contenido de un registro. Cuando necesites desplazar el valor de un registro, puedes utilizar el operador ">>" o "<<" que es lo mismo que dividir o multiplicar el valor del registro. Puedes probarlo con un ejercicio sencillo, escribe un número binario conocido y desplaza los bits una posición a la derecha y calcula su valor. Nota 6: Mecaniza el diseño de tu programa. Primero define los registros que necesites con SFR, después las variables enteras, tipo char, etc, sigue definiendo las funciones si es que las necesitas y por último escribe el bloque principal (main).
Nota 6: El programa principal se define con main, pero un error frecuente es equivocarse en la definición del bloque principal:
MAL -> void main void() {... }
BIEN -> void main (void) { ... } void indica que tu programa no necesita ningún argumento, void entre paréntesis es lo mismo que decir que no hay argumentos. El void al principio indica que tu programa no devuelve ningún valor.

No hay comentarios: