Menu
in

TUTORIAL: Programación de microcontroladores – Entrega 4

Continuamos avanzando en nuestro tutorial de programación de microcontroladores. Hoy aprenderemos todo lo referente a la toma de decisiones en BASIC.Sabemos que un programa es, básicamente, una lista de instrucciones que el microcontrolador debe ejecutar en orden para realizar una tarea determinada. De alguna manera, se asemeja a una receta de cocina (programa) que el cocinero (microcontrolador) debe ir ejecutando. Con mucha frecuencia el cocinero debe tomar decisiones en función de diversos parámetros, y realizar una cosa u otra.

Esto también ocurre en el mundo de los microcontroladores. En cualquier programa medianamente complejo que realicemos, seguramente en algún punto debamos tomar alguna decisión basándonos en el estado de una entrada o en el valor de una variable. Por supuesto, PIC BASIC incorpora instrucciones que nos permiten este tipo de comportamiento, siendo la mas sencilla y frecuentemente utilizada la sentencia IF – THEN – ELSE – ENDIF.

Resulta muy sencillo entender su funcionamiento si traducimos su significado al español. IF – THEN – ELSE – ENDIF significa algo así como “SI ocurre tal cosa ENTONCES realizo esta tarea SINO hago esta otra FIN SI”.

Existen varias formas de utilizar esta instrucción en PIC BASIC. Veremos los tres casos posibles, comenzando por el más sencillo.

El caso más simple es el siguiente:

IF condición THEN instrucción

Como vimos, “IF” significa “SI….”, y “THEN” significa “LUEGO” o “ENTONCES”. Por lo tanto, el caso anterior puede leerse como “SI se cumple la condición, entonces ejecuto la instrucción”

La “condición” es una expresión lógica que puede ser verdadera o falsa. En caso de ser verdadera, la instrucción a continuación del THEN será ejecutada. En caso de la condición sea falsa, el programa seguirá su ejecución con la instrucción siguiente al “IF – THEN”.

Seguramente un ejemplo servirá para que lo comprendamos mejor. Supongamos el siguiente programa:

ALLDIGITAL ‘Todos los pines como E/S.

TRISA = %11111111 ‘Todo el PORTA como entradas
DIM AUX AS BYTE ‘Declaro la variable “AUX” como BYTE
DIM TOTAL AS BYTE ‘Declaro la variable “TOTAL” como BYTE

TOTAL = 100 ‘Le asigno el valor 100 a la variable “TOTAL”
AUX = 5 ‘Le asigno el valor 5 a la variable “AUX”

IF PORTA.4 = 1 THEN AUX = 4

TOTAL = TOTAL + AUX ‘Sumo a “TOTAL” el valor de “AUX”

Cundo comienza el programa, se declaran dos variables tipo BYTE (que como vimos antes, pueden almacenar valores entre 0 y 255). A una de ellas, TOTAL, se le asigna el valor “100” y a la restante, AUX el valor “5”. Hasta aquí, no hay nada que no hayamos visto antes.

La línea siguiente realiza la siguiente tarea: evalúa si la condición PORTA.4 = 1 es cierta. En caso de que efectivamente el valor presente en el bit 4 del PORTA sea “1” (ese pin del microcontrolador estará en estado alto), se ejecuta la instrucción a continuación del THEN, por lo que la variable “AUX” toma el valor “4”, y se pasa a la instrucción de abajo. Si PORTA es igual a “0”, se pasa a la instrucción siguiente sin más.

El valor final de la variable “TOTAL” depende entonces de cual sea el estado de PORTA.4 al momento de hacer la evaluación. Si es igual a “1”, “TOTAL” tendrá un valor de 104 (100 + 4). Si PORTA.4 = 0, “TOTAL” tendrá un valor de 105 (10 +5).

Veamos algunos ejemplos validos de este caso:

IF PULSADOR = 1 THEN PORTA.0 = 1
IF B > A THEN LED=ON
IF B = 5 THEN A = 0
IF (A = 0) OR (B = 5) THEN C = 2
IF PORTA.0 THEN PORTB.3 = 0

En el ultimo ejemplo la condición PORTA.0 equivale a PORTA.0 = 1.

Segundo caso: muchas veces, luego de evaluar la condición necesitamos ejecutar más de una instrucción. En los ejemplos vistos en el caso anterior siempre se ejecutaba una sola instrucción cuando la condición era cierta. La manera de ejecutar múltiples sentencias dentro de una estructura IF-THEN implica emplear el ENDIF, con lo que la sintaxis de la instrucción queda como sigue:

IF condición THEN
    instrucción 1
    instrucción 2
    …
    instrucción n
ENDIF

En realidad, no varía prácticamente nada respecto del primer caso. Solo debemos saber que en esta ocación se van a ejecutar todas las instrucciones del bloque que se encuentren entre el THEN y el ENDIF cada vez que condición sea verdadera.

Veamos un ejemplo. Supongamos el siguiente programa:

DIM A AS BYTE ‘Declaro la variable “A” como BYTE
DIM B AS BYTE ‘Declaro la variable “B” como BYTE
DIM C AS BYTE ‘Declaro la variable “C” como BYTE
DIM D AS BYTE ‘Declaro la variable “D” como BYTE
DIM TOTAL AS BYTE ‘Declaro la variable “TOTAL” como BYTE

TOTAL = 0 ‘Le asigno el valor 0 a la variable “TOTAL”
A = 2 ‘Le asigno el valor 2 a la variable “A”
B = 5 ‘Le asigno el valor 5 a la variable “B”
C = 1 ‘Le asigno el valor 1 a la variable “C”
D = 0 ‘Le asigno el valor 0 a la variable “D”

IF A = 2 THEN
    A = B + (C * D)
    TOTAL = A * B
ENDIF

El ejemplo anterior, la condición “A = 2” es verdadera, ya ese es el valor que le asignamos a “A” al comienzo del programa. Esto significa que las dos instrucciones dentro del bloque THEN-ENDIF se ejecutaran. Esto hace que TOTAL tome el valor de 10 (¡chicos, hagan las cuentitas!). Si “A” hubiese tenido otro valor, esas dos sentencias no se ejecutarían y TOTAL seguiría valiendo “0” al terminar el programa. ¿Fácil, verdad?

Ahora, analicemos el último caso posible. A veces, de acuerdo al resultado de la condición, necesitamos ejecutar un grupo u otro de instrucciones. Para eso, utilizamos la cláusula ELSE, que todavía no habíamos empleado. La sintaxis en este caso queda como sigue:

IF condición THEN
    instrucciónv 1
    instrucciónv 2
    …
    instrucciónv n
ELSE
    instrucciónf 1
    instrucciónf 2
    …
    instrucciónf n
ENDIF

Es decir, si la condición es verdadera, se ejecutan las sentencias entre THEN y ELSE. Y si la condición es falsa, las que estén entre ELSE y ENDIF. “ELSE” puede ser traducido como “en otro caso” o “si no…”.

Veamos un ejemplo de esta situación. Supongamos el siguiente programa:

ALLDIGITAL ‘Todos los pines como E/S.

TRISA = %11111111 ‘Todo el PORTA como entradas
DIM AUX AS BYTE ‘Declaro la variable “AUX” como BYTE
DIM TOTAL AS BYTE ‘Declaro la variable “TOTAL” como BYTE

TOTAL = 10 ‘Le asigno el valor 10 a la variable “TOTAL”
AUX = 2 ‘Le asigno el valor 2 a la variable “AUX”

IF PORTA.4 = 1 THEN
    AUX = 4
    TOTAL = TOTAL + 5
ELSE
    AUX = 0
    TOTAL = TOTAL + 15
ENDIF

El ejemplo anterior, la condición PORTA.4 = 1 determina que bloque de instrucciones se ejecutan. Si es verdadera, AUX = 4 y TOTAL = TOTAL + 5 son usadas. Caso contrario se ejecutan AUX = 0 y TOTAL = TOTAL + 15. Luego, independientemente de cual haya sido el caso, el programa sigue con la sentencia que se encuentre a continuación del ENDIF.

Por ultimo, tenemos que saber que es posible “anidar” instrucciones IF-THEN-ELSE-ENDIF, con lo que se pueden tomar decisiones verdaderamente complejas, con forma de “árbol”, donde cada condición representa una “rama” diferente. Por supuesto, tenemos que ser cautos en el uso de esta característica ya que debido a limitaciones en el tamaño de la pila y cantidad de memoria disponible del PIC podemos ocasionar un desborde y el programa colapsara. Este seria un ejemplo de un anidamiento:

IF PORTB.1 = 1 THEN
    IF A = 2 THEN
        A = B + (C * D)
        TOTAL = A * B
    ELSE
        A = 0
    ENDIF
ELSE
    A = 19
ENDIF

Las sentencias en color rojo corresponden a una estructura IF-THEN-ELSE-ENDIF y las que están en azul a la otra, que se encuentra dentro (“anidada” en) de la primera.

IF… ENDIF no es la única instrucción de toma de decisiones que veremos. Antes de terminar esta cuarta entrega, aprenderemos a utilizar la potente función LOOKUP. La función LOOKUP puede ser utilizada para seleccionar un dato tipo “Byte” desde una lista de constantes del mismo tipo, en función del valor de un índice (que también debe ser de tipo “Byte”). El resultado de la selección se almacena (¡como no!) también en una variable tipo byte.

La forma de la función LOOKUP es realmente sencilla:

variable = LOOKUP(byte0, byte1, …, byteN), indice

Cuando se ejecuta, “variable” tendrá el valor correspondiente al elemento que se encuentre en la posición “índice” de la lista de valores que esta entre los paréntesis. Es importante recordar (lo vamos a repetir varias veces) que el primer elemento de la lista corresponde al valor “0” de “índice”.

Veamos un ejemplo sencillo:

DIM indice AS BYTE
DIM variable AS BYTE
indice = 3
variable = LOOKUP(25, 35, 55, 70, 85, 100), indice

variable tendrá el valor “70” (decimal) al ejecutar este código. El primer elemento de la lista, recordemos, corresponde al valor “0” de indice. Si bien la lista puede contener un máximo de 255 elementos, que es el máximo direccionable por una variable indice de tipo byte, hay que asegurarse que el microcontrolador que estamos empleando tenga memoria suficiente para albergarla.

El segundo ejemplo (extraído de la propia ayuda del PIC SIMULATOR IDE), nos muestra como manejar un display LED de siete segmentos conectado al puerto B:


Dim digito As Byte
Dim mascara As Byte
‘Comienzo el bucle principal
loop:
TRISB = %00000000
digito = 7
mascara = LookUp(0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f), digito
PORTB = mascara
WaitMs 1000 ‘Espero un segundo…
Goto loop

Lo que hace concretamente ese trozo de código es buscar dentro de la lista cual es el valor binario que corresponde asignar al PORTB para que los segmentos adecuados enciendan en el display, mostrando el valor que contiene la variable “digito”.

Si algunas o todas las constantes de la lista son valores ASCII, se puede hacer mas corta y legible la misma utilizando como parte de ella una cadena de caracteres, como se ve a continuación.

MASK = LOOKUP(“ABCDEFGHIJK”), INDEX

“A” seria el valor que tendría MASK cuando INDEX vale “0”, y “K” cuando INDEX tenga el valor “10”.

Por ultimo, en caso de que el valor de INDEX sea mayor a la cantidad de argumentos de la lista, el valor de la variable (en este ejemplo MASK) no cambia.

Con esto terminamos la cuarta entrega del tutorial. En la siguiente, veremos como construir un proyecto que emplee todo lo visto hasta aquí. ¡Hasta la próxima semana!

Escrito por Ariel Palazzesi

Leave a Reply