[go: up one dir, main page]

100% encontró este documento útil (1 voto)
2K vistas40 páginas

Guía de Programación PIC BASIC

Este documento presenta una introducción al lenguaje de programación BASIC para microcontroladores PIC. Explica conceptos básicos como variables, tipos de datos, puertos, operaciones lógicas y matemáticas. También incluye ejemplos de código para declarar variables, acceder a puertos y bits, y realizar operaciones con variables. El documento concluye presentando un primer programa simple que enciende y apaga un LED.

Cargado por

Omar Muñoz
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
100% encontró este documento útil (1 voto)
2K vistas40 páginas

Guía de Programación PIC BASIC

Este documento presenta una introducción al lenguaje de programación BASIC para microcontroladores PIC. Explica conceptos básicos como variables, tipos de datos, puertos, operaciones lógicas y matemáticas. También incluye ejemplos de código para declarar variables, acceder a puertos y bits, y realizar operaciones con variables. El documento concluye presentando un primer programa simple que enciende y apaga un LED.

Cargado por

Omar Muñoz
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 40

Introducción

¡Aprende BASIC!
Esta guia o tutorial esta dedicada al lenguaje de
programación PIC BASIC incluido en elPIC SIMULATOR IDE,
y puede ser útil para aquellos que están aprendiendo a utilizar
otros dialectos de BASIC de microcontroladores, como PIC
BASIC PRO (PBP) oPROTON, ya que se parecen mucho.
NOTA: Este artículo forma parte de la Revista
uControlNumero 1, Numero 2 y Numero 3.
Tabla de contenidos
 [esconder]

 1 Introducción
 2 Variables
o 2.1 Tipos
o 2.2 DIM
 3 RESERVE
 4 Puertos
 5 Punteros
 6 SYMBOL
 7 GOTO
 8 Operaciones Lógicas y Matemáticas
 9 Mi primer programa: Un LED
parpadeando
 10 Mi segundo programa: Usando un
pulsador
 11 IF - THEN - ELSE - ENDIF
o 11.1 CASO 1
o 11.2 CASO 2
o 11.3 CASO 3
 12 FOR - TO - STEP - NEXT
 13 WHILE - WEND
 14 LOOKUP
 15 SHIFTLEFT y SHIFTRIGHT
 16 Displays LCD
o 16.1 LCD alfanuméricos
 17 Temas relacionados
 18 Revista uControl
 19 Autor

Variables
Vamos a comenzar a ver algo de la programación en el
BASIC incluido en el entorno PIC SIMULATOR IDE, al que en
adelante nos referiremos como "BASIC", a secas.
La programación seria prácticamente imposible sin el uso
de variables. Podemos hacernos una imagen mental de las
variables consistente en una caja en la que podemos guardar
algo. Esa caja es una de las muchas que disponemos, y tiene
en su frente pegada una etiqueta con su nombre. Estas cajas
tienen ciertas particularidades, que hace que solo se puedan
guardar en ellas determinados tipos de objetos.
En esta analogía, cada caja es una variable, su contenido es
el valor que adopta, y la etiqueta es el nombre de la variable.
Como su nombre lo indica, y como veremos mas adelante, el
contenido de una variable puede ser modificado a lo largo del
programa.
Tipos
En BASIC tenemos distintos tipos de variables, según el dato
que puedan almacenar:

 Bit (un bit de longitud, almacena 0 o 1 únicamente)


 Byte (un byte de longitud, almacena números enteros
entre 0 y 255)
 Word (dos bytes de longitud, almacena números enteros
entre 0 y 65,535)
 Long (cuatro bytes de longitud, almacena números
enteros entre 0 y 4,294,967,295)

El tipo "Long" solo esta disponible mediante un modulo


opcional al PIC SIMULATOR IDE. A diferencia de otros
BASIC, la declaración de variables puede ser hecha en
cualquier parte del programa, y todas son consideradas
globales, es decir, su valor es accesible desde todas las
subrutinas y zonas del programa. El numero de variables esta
lógicamente limitado al monto de memoria RAM disponible en
cada microcontrolador.

Espacio de publicidad
DIM
Las variables deben ser declaradas antes de utilizarlas,
mediante la instrucción DIM, como se muestra en los
siguientes ejemplos:

DIM A AS BIT
DIM B AS BYTE
DIM X AS WORD
DIM Y AS LONG

También es posible utilizar vectores, que son una matriz de


dimensiones 1xN . Por ejemplo, la sentencia siguiente:

DIM A(10) AS BYTE

declara un vector (al que nos referiremos algunas veces


como "array") de diez elementos del tipo BYTE, que serán
accedidos mediante el uso de subíndice (entre paréntesis) del
0 al 9.
Las variables tipo Word, como vimos, están compuestas por
dos bytes. el primero de ellos es llamado byte "alto" y el otro
"bajo", dado que el primero contiene los 8 bits mas
significativos. En BASIC podemos acceder individualmente a
cada uno de los bytes que componen un Word mediante las
extensiones ".HB" (High byte, o byte alto) y ".LB" (Low Byte o
byte bajo) . Veamos un ejemplo:
DIM A AS BYTE
DIM B AS WORD
A = B.HB
A = B.LB 'Esto es lo mismo que A = B
B.HB = A
B.LB = A
B = A 'Esto también borra el byte alto de la variable B

Los bits individuales de cada variable pueden ser accedidos


individualmente también, simplemente poniendo como
extensión ".n" donde "n" es el numero de bit (1,2, 3, etc. )

DIM A AS BYTE
DIM B AS BIT
B = A.1
B = A.7
A.0 = A.5

RESERVE
La sentencia RESERVE le permite al programador reservar
un numero de posiciones de la RAM para su uso en rutinas
en assembler o para el In-Circuit Debugger de MPLAB.
Simplemente, si queremos reservar 20 bytes de RAM,
escribimos:

RESERVE 20

Puertos
Todos los registros del microcontrolador esta disponibles para
usar en los programas BASIC, como si se tratase de variables
del tipo BYTE con el nombre del registro utilizado en las
datasheet (PORTA, PORTB, TRISA, etc.). Por supuesto, se
puede acceder a bits individuales de los registros con la
técnica vista párrafos atrás. Algunos ejemplos:
TRISA.1 = 0
TRISB = 0
PORTA.1 = 1
PORTB = 255
STATUS.RP0 = 1
INTCON.INTF = 0

Existe una "forma corta" de acceder a los bits individuales de


cada port, simplemente usando las variables BASIC tipo byte
RA, RB, RC, RD, RE o bien las tipo bit RA0, RA1, RA2, ...,
RE6, RE7

RA = 0xFF
RB0 = 1

Punteros
En BASIC también podemos usar punteros. En realidad,
cualquier variable definida como tipo BYTE o WORD pude ser
usada como un putero de memoria, usándola como
argumento de la función POINTER. El valor contenido por la
variable debe tener un valor comprendido entre 0 y 511.
Ejemplos:

DIM X AS WORD
DIM Y AS BYTE
X = 0x3F
Y = POINTER(X)
Y = Y + 0x55
X = X - 1
POINTER(X) = Y
Y = 0xAA
X = X - 1
POINTER(X) = Y

SYMBOL
Una forma de escribir programas que nos resulten mucho
mas fáciles de entender es el uso de nombres simbólicos, o
SYMBOL. Un "symbol" es una cadena que contiene código,
asignado a un nombre. Al momento de compilar, PIC BASIC
hace la "búsqueda y reemplazo" de nuestros símbolos y luego
genera el código ASM y el HEX. Supongamos que tenemos
un LED conectado al bit cero del puerto B. Mediante
SYMBOL podemos hacer:

SYMBOL LED1 = PORTB.0

Luego, si queremos encender el LED, en lugar de

PORTB.0 = 1

podemos hacer

LED1 = 1

que es mucho mas claro y fácil de leer. Por supuesto, el


código que aparece a la derecha del igual no puede contener
instrucciones o comandos.
Las constantes (valores que usamos en nuestro programa, y
que, por ejemplo, asignamos a las variables) pueden ser
escritas en decimal (directamente el valor), en hexadecimal
(anteponiendo "0x" o posponiendo "H" al valor) o en binario
(anteponiendo "%" al valor). Por ejemplo:

DIM A AS BIT
DIM B AS BYTE
A = TRUE
B = 0x55
B = %01010101

Por supuesto, se pueden asignar nombres a las constantes,


usando la instrucción CONST:
DIM A AS WORD
CONST PI = 314
A = PI

Hay tres instrucciones para el manejo individual de bits, que


si bien no hacen nada que no se puede resolver con otras
instrucciones o símbolos, ayudan mucho en la lectura del
código. Se tratan de HIGH, LOW y TOGGLE, que ponen el bit
en alto, bajo o lo invierten, respectivamente. Importante: Si el
bit implicado como argumento de una de estas instrucciones
es un bit de un PORT, el mismo bit en el TRIS
correspondiente es puesto en cero, y dicho pin queda
configurado como salida. Algunos ejemplos:

HIGH PORTB.0
LOW ADCON0.ADON
TOGGLE OPTION_REG.INTEDG

GOTO
Esta es una de las instrucciones más polemicas que se
encuentra en todos los dialectos BASIC. GOTO significa
literalmente "IR A", y sirve justamente para eso: desviar el
flujo del programa a otro punto.
Para usar GOTO, es necesario poner una etiqueta en el lugar
al que queremos "saltar". Las etiquetas son simplemente
nombres terminados en ":", tal como se ve a continuación:

...
...
calculos:
...
...
...
...
...
GOTO calculos
...
...

En el ejemplo anterior, el programa se ejecutará hasta


encontrar la instrucción "GOTO calculos", que hara que se
ejecuten nuevamente las instrucciones siguientes a la
etiqueta "calculos:". Cabe aclarar que las etiquetas no son un
código ejecutable, es decir, no realizan ninguna acción, solo
son un "marcador" del lugar al que se puede saltar con
GOTO.

Operaciones Lógicas y
Matemáticas
PIC SIMULATOR IDE dispone de cinco operaciones
matemáticas básicas, disponibles para las variables tipo Byte
y Word. Estas son la suma (operador +), la sustracción
(operador -), el producto (operador *), el cociente (operador /)
y el módulo (operador MOD) .Por supuesto, el compilador es
capaz de combinarlas para obtener operaciones matemáticas
mas complejas.

DIM A AS WORD
DIM B AS WORD
DIM X AS WORD
A = 123
B = A * 234
X = 2
X = (12345 - B * X) / (A + B)

Es posible calcular raíces cuadradas (aunque el resultado


debe ser entero) con la función SQR:
DIM A AS WORD
A = 3600
A = SQR(A)

Para las variables de tipo Bit existen siete operaciones


lógicas disponibles. Solo es posible efectuar una operación
lógica por instrucción (aunque es muy posible que próximas
versiones permitan mas flexibilidad. Este al tanto de las
novedades!). Estas operaciones también están disponibles
para variables tipo Word o Byte. Veamos algunos ejemplos:

DIM A AS BIT
DIM B AS BIT
DIM X AS BIT
X = NOT A
X = A AND B
X = A OR B
X = A XOR B
X = A NAND B
X = A NOR B
X = A NXOR B
DIM A AS WORD
DIM B AS WORD
A = A OR B
PORTB = PORTC AND %11110000

Mi primer programa: Un LED


parpadeando
Luego de estos capítulos de introducción, puramente teóricos,
vamos a encarar nuestro primer programa. A diferencia de un
programa de ordenador, donde uno escribe el programa, lo
compila, lo ejecuta y ya, en el mundo de los
microcontroladores hay que, previamente, definir el tipo de
microcontrolador que se va a utilizar, cual va a ser su
frecuencia de clock, como va a ser el circuito en que se va a
utilizar el mismo, etc.
Para estas practicas, utilizaremos un PIC16F628A, uno de los
mas difundidos y que mas o menos viene a reemplazar al
viejo y popularPIC16F84A, ya obsoleto. El diagrama circuital
que utilizaremos para las primeras practicas es el siguiente:

Si bien se supone que quien esta leyendo este tutorial tiene


una buena idea sobre electrónica y microcontroladores (si no,
puede leer el resto de uControl), igualmente vamos a hacer
una muy breve descripción del circuito.
En primer lugar, vamos a aprovechar el oscilador interno
del PIC16F628Ay nos evitaremos el xtal y condensadores
asociados. El puerto B del micro (pines 6 al 13) esta
conectado a 8 LEDs mediante 8 resistencias de 220ohms,
que tienen como función limitar la corriente que circula por los
LEDS. Estos serán nuestras "salidas". Los pines 17 y 18,
correspondientes al PORTA.0 y PORTA.1 están conectados a
sendos pulsadores, que al ser presionados conducen 5V (un
"1") al pin respectivo. Cuando están en reposo, las
resistencias R1 y R2 se encargan de mantener el pin en "0".
Por ultimo, el pin 1 (PORTA.2) comanda un parlante mediante
un transistor, para hacer alguna prueba con sonidos.
El circuito debe alimentarse con 5v bien filtrados y regulados.
Volviendo a nuestro programa, vamos a escribir el "hola
mundo" de los microcontroladores: encender un LED.
El primer paso es, desde el menú "Opciones" -> "Select
Microcontroller", elegir el PIC16F628A.

Luego, debemos configurar los bits correspondientes:


Lo destacable por ahora de esta configuración es que
estamos dejando la memoria (FLASH y EEPROM) sin
protección, que el pin RESET se va a comportar como I/O y
que usaremos como oscilador el oscilador interno INTRC.
Una vez hecho esto, arrancamos el edito de BASIC
(presionando CTRL-C, por ejemplo), y escribimos el siguiente
código:

AllDigital
TRISA = %11111111
TRISB = %00000000
loop:
PORTB.0 = 1
WaitMs 500
PORTB.0 = 0
WaitMs 500
Goto loop

Vamos a analizarlo línea por línea para entender su


funcionamiento:
La línea 001 utiliza la sentencia AllDigital para convertir todos
los pines del micro en pines de E/S. Esto equivale a
deshabilitar los comparadores, conversores A/D y todos los
módulos que pudiese tener nuestro microcontrolador. No es
la única manera de hacer esto, pero si la mas sencilla desde
el punto de vista del programador BASIC.
Las líneas 003 y 004 convierten todos los pines del puerto A
en entradas ( TRISA = %11111111 ) y los del puerto B en
salidas ( TRISB = %00000000 ). El "%" indica que el numero
que viene a continuación esta en binario. Se podría haber
escrito, por ejemplo TRISB = 0 y hubiera sido lo mismo.
Personalmente me gusta esta manera, ya que "veo" el estado
de cada pin. Por supuesto, es valido activar como entrada
algunos pines, y como salidas otros, haciendo algo parecido a
TRISB = %11000111.
En la línea 006 encontramos una "etiqueta" ( loop: ). Esta no
hace nada, solo sirve como referencia para enviar el flujo del
programa a esa línea desde otro lugar, mediante la sentencia
"Goto".
La línea 007 pone en "1" el pin correspondiente a PORTB.0,
de manera que en el pin 6 del microcontrolador habrá 5V.
Esta tensión hará que circule una corriente a través de la
resistencia limitadora y el LED1, haciendo que este se
encienda, ya que el cátodo se encuentra conectado a 0V.
En 008 tenemos la sentencia WaitMs 500 . WaitMs se
encarga de hacer una pausa en milisegundos. La duración de
la pausa esta dada por el numero que sigue a la instrucción,
en este caso 500 milisegundos, o medio segundo.
Luego, en 009, otra vez se vuelve a poner en 0 el pin 6,
mediante PORTB.0 = 0 , lo que provoca que ese pin se ponga
a 0V, y no haya mas circulación de corriente a través de la
resistencia y del LED, con lo que este se apaga.
En 010 se hace nuevamente una pausa de medio segundo, y
por ultimo, la línea Goto Loop hace que el programa continúe
en la línea 006 (que es donde esta la etiqueta Loop).
El programa se repite indefinidamente, encendiendo el LED
medio segundo, apagándolo otro medio segundo.
Si presionamos F9 o vamos al menú que vemos a
continuación:

PIC SIMULATOR IDE compilara el programa, y cargara el


HEX resultante en el simulador. Aparecerá el cuadro de
dialogo siguiente, en donde se nos informa entre otras cosas
que no han ocurrido errores, el tamaño del programa (69
words), y la ruta a donde se ubicaron los archivos generados.

Si volvemos a la ventana principal del PIC SIMULATOR IDE,


y desde "Tools" -> "Microcontroller View" abrimos la vista del
microntrolador, al darle "Start" a la simulación tendremos algo
parecido a lo que sigue:
En la captura se puede apreciar que el pin 6, correspondiente
a RB0 esta en "ON". Si esperamos lo suficiente, veremos
como pasa a "OFF", y mas tarde vuelve a "ON", etc. Si
queremos esperar menos tiempo, y esto lo debemos tomar
como una regla general al correr simulaciones, podemos
disminuir el tiempo indicado en las instrucciones "WaitMS" a
valores iguales a 1, de esta manera la simulación será mucho
mas ágil. Por supuesto, al momento de llevar el HEX a
nuestro microcontrolador en el circuito "real", debemos
cambiar a los tiempos originales y volver a compilar. Caso
contrario, el LED permanecería encendido solo una milésima
de segundo, luego apagado el mismo tiempo, etc., por lo que
nuestro ojo lo percibiría como encendido a medias, incapaz
de discriminar su verdadero estado.
Se podría haber utilizado la instrucción SYMBOL para hacer
mas claro el programa. En el siguiente ejemplo, hemos hecho
algunos cambio y obtenido un programa que hace
exactamente lo mismo que el anterior, pero que resulta mas
claro de entender, ya que se aproxima algo mas al "lenguaje
natural":

Mi segundo programa: Usando


un pulsador
En la segunda practica del lenguaje BASIC veremos como
leer una entrada del PIC. Utilizaremos el mismo esquema que
vimos antes, y el programa que mostramos a continuación:

AllDigital
TRISA = %11111111
TRISB = %00000000
loop:
PORTB.0 = PORTA.0
Goto loop

Como resulta evidente a simple vista, el programa


ejemplo2.bas es muy similar al ejemplo1.bas que vimos en el
capitulo anterior. Las diferencias están dentro del bucle. La
instrucción PORTB.0 = PORTA.0 hace que el valor del bit 0
del PORTB tome el valor del bit 0 del PORTA. Que ambos
bits sean el cero es solo una coincidencia, se podrían haber
elegido otros valores.
Al ejecutarse el programa, cada vez que se accione el
pulsador conectado a PORTA.0, ese pin se pondrá a estado
alto, ya que la corriente circulara desde +V al pin 17 del PIC
por medio del pulsador. Ese "estado alto" se interpreta dentro
del PIC como un "1", y es el valor que se le asigna a
PORTB.0 , con lo que el también pasara a estado alto. Eso
provocara que el led conectado en ese pin se ilumine.
Cuando soltamos el pulsador, PORTA.0 vuelve a estado bajo,
ya que se pone a masa a través de la resistencia de 10K, y
PORTB.0 hará lo propio, apagando el LED.
Nuestro sencillo (sencillísimo!) programa todo lo que hace es
"copiar" en el LED el estado del pulsador.
Si presionamos F9 o vamos al menú que vemos a
continuación
PIC SIMULATOR IDE compilara el programa, y cargara el
HEX resultante en el simulador. Aparecerá el cuadro de
dialogo que nos informa que no han ocurrido errores y que el
tamaño del programa esta vez es de 20 words.
Si volvemos a la ventana principal del PIC SIMULATOR IDE,
y desde "Tools" -> "Microcontroller View" abrimos la vista del
microntrolador, al darle "Start" a la simulación tendremos algo
parecido a lo que sigue:
El pin 6, correspondiente a RB0 esta en "OFF" por que el
pulsador del pin 17 (RA0) esta en OFF. Si con el mouse
hacemos un click sobre la "T" que esta al lado del pin 17, la
vista del microcontrolador pasara al estado que muestra la
imagen siguiente:

Recordemos que el botón "T" significa "cambio" (Toggle) por


lo que el estado del pin 17 permanecerá en alto hasta que lo
pulsemos otra vez, y el estado del microcontrolador volverá a
ser el inicial. Como en cualquier curso, conviene realizar
estas practicas, que aunque puedan parecer muy sencillas
nos ayudaran a conocer las herramientas disponibles y
"tomar confianza" al programa. También es interesante el
realizar cambios en el programa BASIC, recompilar y analizar
los resultados.

IF - THEN - ELSE - ENDIF


En cualquier programa medianamente complejo que
queramos realizar, seguramente necesitaremos en algún
punto tomar alguna decisión basándonos en el estado de una
entrada o en el valor de una variable. PIC BASIC incorpora
instrucciones que nos permiten este tipo de comportamiento,
siendo la mas sencilla y frecuentemente utilizada la
sentencia IF - THEN - ELSE - ENDIF.
Existen varias formas de utilizar esta instrucción.
Comenzaremos con los casos mas sencillos y a lo largo de
este capitulo iremos agregando complejidad hasta ver todas
las posibilidades.
CASO 1
El caso mas simple es el siguiente:

IF condición THEN instrucción

"IF" significa "SI....", y "THEN" significa "LUEGO" o


"ENTONCES". 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".
Veamos un ejemplo. Supongamos el siguiente programa:

ALLDIGITAL 'Voy a usar todos los pines como E/S.


TRISA = %11111111 'Todo el PORTA como entradas
DIM A AS BYTE 'Declaro la variable "A" como BYTE
DIM TOTAL AS BYTE 'Declaro la variable "TOTAL" como BYTE
'
TOTAL = 10 'Le asigno el valor 10 a la variable "TOTAL"
A = 2 'Le asigno el valor 2 a la variable "A"
'
IF PORTA.4 = 1 THEN A = 4
'
TOTAL = TOTAL + A 'Sumo a "TOTAL" el valor de "A"

Cundo comienza el programa, se declaran dos variables tipo


BYTE (que pueden almacenar valores entre 0 y 255), y a
TOTAL se le asigna el valor "0" y a "A" el valor "2". 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",
se ejecuta la instrucción a continuación del THEN, la variable
"A" 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
mas.
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 14
(10 + 4). Si PORTA.4 = 0, "TOTAL" tendrá un valor de 12 (10
+ 2).
Veamos algunos ejemplos validos de este caso:

IF A = B THEN PORTA.0 = 1
IF B > A THEN A = B
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.

CASO 2
Muchas veces, luego de evaluar la condición necesitamos
ejecutar mas de una instrucción. En los ejemplos vistos en el
CASO 1 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:

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

No varia prácticamente nada respecto del primer caso, solo


que esta vez se van a ejecutar todas las instrucciones 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 (puesto


que ese es el valor que le asignamos a "A" mas arriba), por lo
que las dos instrucciones dentro del THEN-ENDIF se
ejecutaran. Esto hace que TOTAL tome el valor de 10 (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.

CASO 3
Hay veces que de acuerdo a la condición, queremos ejecutar
un grupo u otro de instrucciones. Para eso, utilizamos el
ELSE:

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. Supongamos el siguiente programa:

ALLDIGITAL 'Voy a usar todos los pines como E/S.


'
TRISA = %11111111 'Todo el PORTA como entradas
DIM A AS BYTE 'Declaro la variable "A" como BYTE
DIM TOTAL AS BYTE 'Declaro la variable "TOTAL" como BYTE
'
TOTAL = 10 'Le asigno el valor 10 a la variable "TOTAL"
A = 2 'Le asigno el valor 2 a la variable "A"
'
IF PORTA.4 = 1 THEN
A = 4
TOTAL = TOTAL + 5
ELSE
A = 0
TOTAL = TOTAL + 15
ENDIF

El ejemplo anterior, la condición PORTA.4 = 1 determina que


bloque de instrucciones se ejecutan. Si es verdadera, A = 4 y
TOTAL = TOTAL + 5 son usadas. Caso contrario se ejecutan
A = 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. 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 negro corresponden a una estructura


IF-THEN-ELSE-ENDIF y las que están en verde a la otra, que
se encuentra dentro ("anidada" en) de la primera.

FOR - TO - STEP - NEXT


Así como la toma de decisiones que vimos en el capitulo
anterior esta presente en casi todos nuestros programas, las
estructuras que permiten repetir un grupo de instrucciones un
numero determinado de veces también son indispensables.
En PIC SIMULATOR IDE hay dos de ellas. Veremos en este
capitulo la primera, FOR - TO - STEP - NEXT.
Esta estructura necesita una variable (tipo Byte o Word) para
funcionar. En cada iteración del bucle, la variable va
cambiando su valor. Cuando el valor de la variable alcanza o
supera el valor prefijado, el bucle termina. La forma del bucle
es la siguiente:

FOR variable = valor_inicial TO valor_final STEP paso


instruccion1
instruccion2
...
instruccionn
NEXT variable

Veamos un ejemplo concreto. Supongamos que queremos


sumar los números del 1 al 100. El programa quedaría como
sigue:
DIM A AS BYTE 'Declaro la variable "A" como BYTE
DIM TOTAL AS WORD 'Declaro la variable "TOTAL" como WORD
'
TOTAL = 0 'Asigno "0" a la variable "TOTAL".
'
FOR A = 1 TO 100 STEP 1 '"A" va de 1 a 100 de 1 en 1
TOTAL = TOTAL + A 'Sumo "A" al valor de "TOTAL".
NEXT A 'fin del bucle.

Hemos declarado la variable A como BYTE, ya que su valor


va a mantenerse en el rango 0..255. Para TOTAL utilizamos
una variable tipo WORD, ya que la suma va a superar el valor
máximo de un BYTE. (Recordemos que WORD permite
valores en el rango 0..65535)
El bucle se ejecuta 100 veces, la primera de ellas A vale 1, la
segunda 2, la tercera 3, hasta la ultima en la que vale 100.
Ese incremento (1 por ves) esta dado por el valor a
continuación del STEP. En los casos como este en que STEP
vale 1, puede omitirse, como veremos en ejemplos
posteriores.
TOTAL comienza valiendo 0 (se le asigna ese valor fuera del
bucle) y en cada iteración se le suma el valor que tenga A en
ese momento. De esa manera, TOTAL va tomando los
valores 1, 3, 6, 10, .... 5050.
Tanto valor_inicial como valor_final y paso pueden ser
variables. El siguiente trozo de código hace lo mismo que el
anterior, pero usa variables:

DIM A AS BYTE 'Declaro la variable "A" como BYTE


DIM INICIO AS BYTE 'Declaro la variable "INICIO" como BYTE
DIM FINAL AS BYTE 'Declaro la variable "FINAL" como BYTE
DIM PASO AS BYTE 'Declaro la variable "PASO" como BYTE
DIM TOTAL AS WORD 'Declaro la variable "TOTAL" como WORD
'
INICIO = 1 'Asigno "1" a la variable "INICIO".
FINAL = 100 'Asigno "100" a la variable "FINAL".
PASO = 1 'Asigno "1" a la variable "PASO".
TOTAL = 0 'Asigno "0" a la variable "TOTAL".
'
FOR A = INICIO TO FINAL STEP PASO '"A" va de 1 a 100 de 1 en 1
TOTAL = TOTAL + A 'Sumo "A" al valor de "TOTAL".
NEXT A 'fin del bucle.

Y el mismo ejemplo, sin usar STEP:

DIM A AS BYTE 'Declaro la variable "A" como BYTE


DIM TOTAL AS WORD 'Declaro la variable "TOTAL" como WORD
'
TOTAL = 0 'Asigno "0" a la variable "TOTAL".
'
FOR A = 1 TO 100 '"A" va de 1 a 100 de 1 en 1
TOTAL = TOTAL + A 'Sumo "A" al valor de "TOTAL".
NEXT A 'fin del bucle.

Hay casos en que es necesario que el valor de la variable de


control del bucle se decremente en lugar de ir aumentando.
En ese caso, se puede usar un valor negativo para STEP. El
siguiente ejemplo cuenta desde 50 hasta 20, de 5 en 5:

DIM A AS BYTE 'Declaro la variable "A" como BYTE


'
FOR A = 50 TO 20 STEP -5 '"A" va de 50 a 20 de 5 en 5
instruccion1
instruccion2
...
instruccionn
NEXT A 'fin del bucle.

De la misma manera que ocurría con IF-THEN-ELSE-ENDIF,


pueden anidarse diferentes bucles FOR-TO-STEP-NEXT ,
uno dentro de otro:

FOR variable1 = valor_inicial1 TO valor_final1 STEP paso1


FOR variable2 = valor_inicial2 TO valor_final2 STEP paso2
instruccion1
instruccion2
...
instruccionn
NEXT variable2
NEXT variable1

La única condición es que un bucle este completamente


dentro del otro. El siguiente anidamiento daría un error en el
compilador:

FOR variable1 = valor_inicial1 TO valor_final1 STEP paso1


FOR variable2 = valor_inicial2 TO valor_final2 STEP paso2
instruccion1
instruccion2
...
instruccionn
NEXT variable1
NEXT variable2

Para terminar, veamos el siguiente código:

AllDigital
TRISB = 0
Dim a As Byte
For a = 0 To 15
PORTB = a
Next a

Si se lo corre en el PIC SIMULATOR IDE, puede verse como


los primeros 4 bits del PORTB cuentan en binario de 0 a 15.

WHILE - WEND
La segunda estructura de control que proporciona PIC BASIC
es WHILE - WEND. Su propósito es el mismo que la que
vimos en el capitulo anterior, y su estructura es la siguiente:

WHILE condición
instruccion1
instruccion2
...
instruccionn
WEND

Mientras que la condición sea verdadera, el grupo de


instrucciones dentro del cuerpo del WHILE-WEND se ejecuta.
Las características de la condición son las mismas que vimos
en el capitulo 10 para IF-THEN-ELSE-ENDIF.
Por supuesto, si no somos cuidadosos al momento de elegir
la condición, puede darse el caso de que el numero de
repeticiones del bucle sea infinito, y nunca salgamos de el.
De hecho, esta circunstancia se aprovecha en algunos
programas para repetir indefinidamente un grupo de
instrucciones. También hay que tener presente que si la
condición no es cierta al momento de ejecutar la primera vez
el WHILE, el flujo del programa pasara directamente a la
instrucción posterior al WEND y las instrucciones dentro del
bucle no se ejecutaran ninguna vez.
No hay mucho mas para decir de WHILE-WEND , solo
analizar algunos ejemplos:
Ejemplo 1: El siguiente es un bucle infinito. Como dentro del
cuerpo del WHILE-WEND no se cambia el valor de la variable
A, esta siempre vale "0" y la condición del WHILE nunca es
falsa, por lo que se repite eternamente:

DIM A AS BYTE
A = 0
...
WHILE A = 0
instruccion1
instruccion2
...
instruccionn
WEND
...
Ejemplo 2: Las instrucciones dentro del siguiente WHILE-
WEND no se ejecutan nunca, dado que la condicion siempre
es falsa:

DIM A AS BYTE
A = 0
...
WHILE A > 0
instruccion1
instruccion2
...
instruccionn
WEND
...

Ejemplo 3: Las instrucciones dentro del siguiente WHILE-


WEND se ejecutan 10 veces, y al terminar la variable B
contiene la suma de los números del 0 al 10 naturales:

DIM A AS BYTE
DIM A AS BYTE
A = 0
B = 0
'
WHILE A < 10
A = A + 1 'Incremento la variable A
B = B + A 'Sumo a B el valor de la variable A
WEND

Cuando A = 10, se suma su valor a A, y al llegar al WEND el


control del programa se transfiere al WHILE, donde se evalúa
la condición A < 10, se determina que es falsa, y el programa
pasa el control a la línea que exista después del WEND.

LOOKUP
La función LOOKUP puede ser utilizada para seleccionar un
Byte desde una lista de constantes del mismo tipo, de
acuerdo al valor de un índice (también 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 la siguiente:

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

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
For digito = 0 To 9
mascara = LookUp(0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f), digito
PORTB = mascara
WaitUs 10 'esta demora debe ser mayor si no es una simulación!
Next digito
Goto loop

Este es el aspecto que muestra el simulador cuando


ejecutamos el programa anterior. Debemos asegurarnos de
que uno de los dígitos LED este configurado como conectado
al puerto PORTB, tal como se ve en la imagen:

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.

SHIFTLEFT y SHIFTRIGHT
SHIFTLEFT y SHIFTRIGHT son funciones a nivel bit que
pueden ser utilizadas para "correr" el contenido de variable a
la izquierda o a la derecha. Cada uno de los bits que
componen la variable se desplazan una posición (a la
izquierda o a la derecha, de acuerdo a que función
utilicemos). Esto tiene dos consecuencias. En primer lugar, el
bit de mas a la izquierda (SHIFTLEFT) o derecha
(SHIFTRIGHT) se pierde. Y el espacio creado en el otro
extremo se completa con un "0".

SHIFTLEFT

SHIFTRIGHT
El siguiente ejemplo muestra como utilizar estas funciones en
un programa:

TRISB = 0x00
PORTB = %00000011
goleft:
WaitUs 5 'esta demora debe ser mayor si no es una simulación!
PORTB = ShiftLeft(PORTB, 1)
If PORTB = %11000000 Then Goto goright
Goto goleft
goright:
WaitUs 5 'esta demora debe ser mayor si no es una simulación!
PORTB = ShiftRight(PORTB, 1)
If PORTB = %00000011 Then Goto goleft
Goto goright

Lo que hace el programa es muy sencillo: enciende los dos


primeros bits del PORTB, espera un tiempo, los desplaza
hacia la izquierda, si esos bits llegaron al extremo de la
variable tipo byte que es el PORTB, se invierte el sentido del
desplazamiento.

Displays LCD
LCD alfanuméricos
A grandes rasgos, y a pesar de la simplicidad que brinda el
disponer de un mismo integrado especializado en casi todos
los modelos de displays, la escritura en estos es
relativamente compleja, dado que se deben respetar
protocolos de inicialización, tiempos entre envío de datos,
etc., lo que hace bastante tediosa su programación en
assembler.
Pero PIC BASIC dispone de un juego de instrucciones
especiales para manejar displays en modo “8 bits” y
en modo “4 bits” que nos evitan toda esa complejidad.
El manejo de los LCD se hace mediante el uso de
sentencias “DEFINE”, que le dicen al compilador a que pines
del microcontrolador hemos conectado cada uno de los pines
del LCD. La forma de la instrucción DEFINE es la siguiente:

DEFINE parametro = valor

Donde “parametro” es el nombre del parámetro al que le


queremos asignar el “valor”. Los parámetros disponibles para
el manejo de LCD alfanuméricos son los siguientes:

 LCD_BITS: Define el número de bits de la interfaz de


datos. Se pueden asignar valores de 4 u 8, siendo 4 el
valor por defecto.

 LCD_DREG: Define a que puerto del PIC tenemos


conectado el port de datos del LCD. Los valores permitidos
son PORTA, PORTB, PORTC, etc. Por defecto se asume
PORTB.

 LCD_DBIT: Define cual es el primer pin del puerto que


usamos para enviar los datos al LCD cuando
seleccionamos un bus de 4 bits. Solo puede ser el 0 (para
los pines el 0, 1, 2 y 3) o 4 (para usar los pines 4, 5, 6 y 7).
Por defecto se asume “4”, y esta instrucción se ignora para
LCD_BITS = 8.

 LCD_RSREG: Define a que puerto del PIC tenemos


conectado el pin RS del LCD. Los valores permitidos son
PORTA, PORTB, PORTC, etc. Por defecto se asume
PORTB.

 LCD_RSBIT: Define a que pin del puerto tenemos


conectado el pin RS del LCD. Por defecto se asume “3”.
 LCD_EREG: Define a que puerto del PIC tenemos
conectado el pin E del LCD. Los valores permitidos son
PORTA, PORTB, PORTC, etc. Por defecto se asume
PORTB.

 LCD_EBIT: Define a que pin del puerto tenemos


conectado el pin E del LCD. Por defecto se asume “2”.

 LCD_RWREG: Define a que puerto del PIC tenemos


conectado el pin RW del LCD. Los valores permitidos son
0, PORTA, PORTB, PORTC, etc. Por defecto se asume
“0”, que significa “no usamos el pin RW”.

 LCD_RWBIT: Define a que pin del puerto tenemos


conectado el pin RW del LCD. Por defecto se asume “0”,
que significa “no usamos el pin RW”.

 LCD_COMMANDUS: Define cuantos microsegundos


demora la escritura de un comando en el display. Por
defecto, este valor es de 5000. La mayoría de los LCD
funcionan bien con un valor de 2000, lo que hace más
rápidos nuestros programas.

 LCD_DATAUS: Define cuantos microsegundos demora


la escritura de un dato en el LCD. Por defecto, este valor
es de 100.

 LCD_INITMS: Define cuantos microsegundos demora la


inicialización e la electrónica del LCD. Por defecto, este
valor es de 100.
Luego, tenemos una serie de instrucciones que manejan el
envío de comandos e instrucciones al display:
LCDINIT debe utilizarse antes de enviar cualquier comando o
dato al LCD. La forma de esta instrucción es al siguiente:
LCDINIT n

Donde “n” es el tipo de cursor que queremos que muestre el


display. “0” significa que el cursor estará oculto, “1” significa
que el cursor parpadeara, “2” nos mostrara un cursor
subrayado, y “3” un cursor subrayado y parpadeando.
LCDCMDOUT es la instrucción que envía comandos al LCD.
Se emplea de la siguiente manera:

LCDCMDOUT comando

Donde “comando” es alguno de los siguientes:

 LcdClear: Borra el contenido del LCD.


 LcdHome: Lleva el cursor a la primera posición del
primer renglón del LCD.
 LcdLine2Home: Lleva el cursor a la primera posición del
segundo renglón del LCD.
 LcdLeft: Mueve el cursor una posición a la izquierda.
 LcdRight: Mueve el cursor una posición a la derecha.
 LcdShiftLeft: Desplaza el contenido del LCD una
posición a la izquierda.
 LcdShiftRight: Desplaza el contenido del LCD una
posición a la derecha.
 LcdLine1Clear: Borra la primera línea del LCD.
 LcdLine2Clear: Borra la segunda línea del LCD.
 LcdLine1Pos(x): Coloca el cursor en la posición “x” del
primer renglón del LCD. “X” puede tener cualquier valor
entre 1 y 40
 LcdLine2Pos(x): Coloca el cursor en la posición “x” del
segundo renglón del LCD. “X” puede tener cualquier valor
entre 1 y 40

LCDOUT envía datos al display. Si son caracteres,


simplemente los ponemos entre comillas a continuación del
comando. Si se trata de mostrar el contenido de una variable,
se escribe la variable (precedida por “#”) a continuación del
comando. Si se necesitan imprimir varias variables, se
pueden separar por “comas”.
A continuación, un par de ejemplos de cómo se utilizan todas
estas instrucciones. El primero se encarga de mostrar un
texto parpadeando en la primera línea del display. Intenten
deducir como está conectado el LCD al PIC mirando las
instrucciones “DEFINE” del principio del programa.

DEFINE LCD_BITS = 8
DEFINE LCD_DREG = PORTB
DEFINE LCD_DBIT = 0
DEFINE LCD_RSREG = PORTD
DEFINE LCD_RSBIT = 1
DEFINE LCD_EREG = PORTD
DEFINE LCD_EBIT = 3
DEFINE LCD_RWREG = PORTD
DEFINE LCD_RWBIT = 2
'
LCDINIT 0 ‘inicializo el LCD sin cursor.
'
loop:
LCDOUT "www.uControl.com" ‘Muestra el texto…
WAITMS 1000 ‘Espero un segundo
LCDCMDOUT LcdClear ‘Borro el display
WAITMS 1000 ‘Espero un segundo
GOTO loop ‘Vuelvo a loop: para repetir indefinidamente.

El segundo ejemplo muestra como imprimir el contenido de


una variable (“A”) en el LCD. Concretamente, se muestra un
texto en el primer renglón, mientras que en el segundo se
cuentan los números del 65535 al 0 en el segundo.

DEFINE LCD_BITS = 8
DEFINE LCD_DREG = PORTB
DEFINE LCD_DBIT = 0
DEFINE LCD_RSREG = PORTD
DEFINE LCD_RSBIT = 1
DEFINE LCD_EREG = PORTD
DEFINE LCD_EBIT = 3
DEFINE LCD_RWREG = PORTD
DEFINE LCD_RWBIT = 2
'
DIM A AS WORD
A = 65535
'
LCDINIT 3 ‘Cursor parpadeando
WAITMS 1000
'
loop:
LCDOUT "¡Estoy contando!” ‘Texto del primer renglón
LCDCMDOUT LcdLine2Home ‘Paso al Segundo renglón
LCDOUT #A ‘Muestro el valor de A
A = A - 1
WAITMS 250
LCDCMDOUT LcdClear ‘Limpio del display
GOTO loop

También podría gustarte