Ciclos y retardos de tiempo - Hotboards/CodeBank8 GitHub Wiki
Crear tareas repetitivas es un trabajo muy común y usual en cualquier lenguaje de programación, ademas de ser necesaria, ya que nos ayuda a generar programas mas compactos y eficientes.
Imagina que debemos poner en 1's, uno a uno los 8 pines del puerto B, con lo aprendido en el anterior tema, lo podríamos hacer de la siguiente manera
TRISB = 0x00; /*todos los pines del puerto B como salidas*/
LATB |= (1 << 0); /*pin 0 en 1*/
LATB |= (1 << 1); /*pin 1 en 1*/
LATB |= (1 << 2); /*pin 2 en 1*/
LATB |= (1 << 3); /*pin 3 en 1*/
LATB |= (1 << 4); /*pin 4 en 1*/
LATB |= (1 << 5); /*pin 5 en 1*/
LATB |= (1 << 6); /*pin 6 en 1*/
LATB |= (1 << 7); /*pin 7 en 1*/
El anterior código es ineficiente ademas de resultar en una mayor cantidad de instrucciones para nuestro procesador. Si observamos detenidamente lo único que cambia en cada linea de código es el numero que representa el pin del puerto, así que podemos cambiar ese numero constante y reemplazarlo por una variable.
unsigned char i; /*declaramos una variable de 8 bits*/
TRISB = 0x00; /*todos los pines del puerto B como salidas*/
for(i=0;i<8;i++)
{
LATB |= (1 << i); /*pin i en 1*/
}
Ahora tenemos una sola linea de código encargada de poner en 1 cada pin del puerto B, esto lo hicimos encerrando esa linea de código dentro de un ciclo for el cual inicia la variable i a 0 y de manera automática la aumenta hasta que deja de ser menor a 8 (como los 8 pines del puerto) en ese instante se rompe el ciclo.
Ahora daremos una explicación un poco mas detallada de los ciclos for
. Un ciclo for es una forma de generar repeticiones en el lenguaje C su sintaxis es muy sencilla.
for(sentencia1;sentencia2;sentencia3)
{
expresion;
}
Donde sentencia1
es generalmente una incilizacion de alguna variable contadora, sentencia2
es la condición que determina si el ciclo continua ejecutándose o se termina, mientras la condición de sentencia2
sea verdadera las expresiones
contenidas entre las llaves se ejecutara. Y por ultimo sentencia3
es por lo general el lugar donde incrementamos la variable contadora.
En el anterior ejemplo teníamos el siguiente ciclo for(i=0;i<8;i++)
donde se usa la variable i como variable contadora. Dentro del for
la sentencia1
es la inicializacion de la variable i a cero i=0
, la sentencia2
es la condición i<8
es decir el ciclo la expresion
se ejecutara hasta que i deje de ser menor a 8. la sentencia3
es unicamente un incremento en 1 de la variable i i++
. La expresion
que se ejecuta dentro del ciclo (se ejecuta 8 veces) es LATB |= (1 << i)
.
No necesariamente debe existir una expresion
para ejecutarse dentro de un ciclo, en algunas ocasiones tendremos la necesidad de tener ciclos vacíos, ???. Si así es ciclos que no hagan nada como el siguiente.
unsigned short x;
for(x=0;x<50000;x++);
El anterior sigue siendo un ciclo for el cual lo único que hace es incrementar la variable x en uno, hasta que esta llegue a un valor de 50000, es decir el procesador quedara estancado en ese ciclo for por un determinado tiempo.
Y esto de que sirve?. Ok daremos el ejemplo mas sencillo del mundo, vamos a parpadear un led conectado a un pin del puerto B.
void main (void)
{
unsigned short i;
for(;;)
{
LATB ^= (1 << 3); /*invertimos el estado del pin 3 del puerto B*/
for(i=0;i<50000;i++); /*ciclamos el procesador hasta que i sea mayor a 50000*/
}
}
Lo único que hará este programa sera encender y apagar el pin 3 del puerto B cada 50000 incrementos, ojo si quieren saber cuanto es en mili segundos deberás calcular las instrucciones que le toma hacer este ciclo for y cuanto tiempo le toma al procesador ejecutar cada instrucción.
Aparte de los ciclos for existen los ciclos while, los cuales poseen una sintaxis mas sencilla que los anteriores
while(condicion)
{
expresion;
}
Mientras que la condición
sea verdadera expresión
se ejecutara. Como puedes ver no hay incializacion ni incrementos de alguna variable contadora, si quisiéramos emular lo que el ciclo for
hace, tendríamos que hacer pasos extras.
unsigned char i; /*declaramos una variable de 8 bits*/
TRISB = 0x00; /*todos los pines del puerto B como salidas*/
i=0; /*inicializamos variable contadora*/
while(i<8) /*ciclamos hasta que i deje de ser menor a 8*/
{
LATB |= (1 << i); /*pin i en 1*/
i++; /*incrementamos variable contadora*/
}
Una aplicación muy útil de los ciclos while
es la de ser ciclos controlados por un valor y/o expresión centinela, es decir podemos quedarnos dentro de un ciclo hasta que un evento ocurra y rompa el ciclo. A continuación ciclamos el micro parpadeando un led hasta que la entrada de un pin cambie a 0.
voi main (void)
{
unsigned short i;
TRISB &= ~(1 << 3); /*pin 3 del puerto B como salida*/
TRISB |= (1 << 4); /*pin 4 del puerto B como entrada*/
for(;;)
{
while(PORTB & (1 << 4)) /*el programa ciclara aqui hasta que el pin 4 deje de ser 1*/
{
LATB ^= (1 << 3); /*invertimos el estado del pin 3 del puerto B*/
for(i=0;i<50000;i++); /*ciclamos el procesador hasta que i sea mayor a 50000*/
}
}
}