Professional Documents
Culture Documents
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 1.
Hasta hace unos 5 aos los programas se seguan escribiendo en lenguaje Assembler,
pero gracias a que los compiladores de lenguaje C se mejoraron, en cuanto a su relacin
de compresin, y los microcontroladores ampliaron su capacidad de memoria, hoy en
da prcticamente el 99% de las aplicaciones para microcontroladores se realiza en
lenguaje C (tambin existe el compilador para lenguaje BASIC y PASCAL, sin
embargo los compiladores de lenguaje C son los mas usados por sus prestaciones).
Hoy cuando tenemos que sentarnos a trabajar con un microcontrolador el desarrollador
se encuentra ante una gran oferta de compiladores en el mercado, y surge la pregunta:
Cul elijo?
Sin duda alguna el compilador mas completo para microcontroladores PIC es el
desarrollado por la firma CCS inc.(Custom Computer Services. Inc), el cual es muy
popular en Amrica Latina por la gran documentacin que existe sobre el mismo.
En esta seccin aportaremos nuestro granito de arena, ensendoles a trabajar con el
mismo en el Entorno de Desarrollo Integrado (IDE) de Microchip MPLAB.
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 2.
En nuestra entrega anterior aprendimos a crear un proyecto dentro del MPLAB
para escribir nuestro primer cdigo en lenguaje C, hoy crearemos nuestro primer
cdigo y aprenderemos la funcin que cumplen sus elementos principales .
while(1)
//creamos un bucle infinito
{
//abrimos el bucle
output_high(PIN_B0);
//prendemos RB0
delay_ms(500);
//esperamos 500 ms
output_low(PIN_B0);
//borramos RB0
delay_ms(500);
//esperamos 500 ms
}
//cerramos el bucle
//cerramos la funcin principal
Este cdigo lo hemos escrito en lo que se conoce en la jerga tcnica como codigo en C
nativo ya que usamos las funciones de control de entrada / salida de CCS
El cdigo inicia siempre en lo que se conoce como cabecera, es decir el principio.
En esta cabecera encontraremos instrucciones dirigidas al compilador y no al
microcontrolador, dichas instrucciones se denominan directivas. Las directivas se
diferencian de las instrucciones en que:
Sin embargo esta directiva debe usarse con precaucin ya que el clock que definimos
nunca debe sobrepasar la mxima velocidad de procesamiento del PIC que se est
usando. Este parmetro se denomina MIPS (Millones de Instrucciones por Segundo) y
se obtiene dividiendo la frecuencia de entrada por cuatro.
MIPS = fosc/4
La directiva #fuse xx nos permite activar o desactivar las caractersticas del nucleo,
como ser el circuito de Watch Dog Timer, que reseta al microcontrolador ante un
cuelgue del mismo, el Brown Out Detect, que resetea el microcontrolador ante un fallo
de la alimentacin, el tipo de oscilador, etc.
Las etiquetas usadas para activar o desactivar la propiedad, estn incluidas en el archivo
de cabecera y deben ser consultadas siempre, ya que las mismas suelen cambiar entre
versiones del compilador o tipos de microcontroladores.
En lneas generales podemos decir que anteponiendo la palabra NO al fusible de
configuracin (as se llama al seteo de las propiedades), se le informa al compilador que
el fusible en cuestin est desactivado, mientras que colocando solo el nombre
activamos la propiedad.
Por otra parte para activar o desactivar los distintos fusibles se puede realizar en varias
lneas (como en el ejemplo) o se pueden activar y desactivar en una sola lnea separando
cada fusible con comas:
#fuse NOWDT,HS,NOPUT,NOLVP,NOMCLR,NOPROTECT,NOBROWNOUT
while(1)
//creamos un bucle infinito
{
//abrimos el bucle
output_high(PIN_B0);
//prendemos RB0
delay_ms(500);
//esperamos 500 ms
output_low(PIN_B0);
//borramos RB0
delay_ms(500);
//esperamos 500 ms
}
//cerramos el bucle
//cerramos la funcin principal
Todo programa siempre inicia en una rutina principal. En el lenguaje C las rutinas se
denominan funciones. Las funciones son un conjunto de sentencias u ordenes que
realizan una operacin determinada, como lo hacen las rutinas, sin embargo las
funciones tiene una caracterstica extra; a ellas se les puede pasar valores de variables
para que las procesen, y son capaces de devolvernos los resultados de dichos procesos.
Bsicamente actan como las funciones matemticas.
Todo programa C siempre inicia en la funcin principal, la cual se denomina main.
Dicho nombre no puede ser distinto, todo programa debe tener una funcin main, de lo
contrario el compilador nos indicar un error.
La funcin encierra una serie de sentencias, las cuales forman el bloque de dicha
funcin. Dicho bloque inicia con una llave { y finaliza con otra llave } .
Entre estas dos llaves se encuentran las sentencias y las estructuras lgicas.
La funcin main es una funcin especial ya que no puede recibir ningn valor, ni
tampoco puede devolver uno. Por lo tanto observe que va acompaada por dos palabras
void lo cual en el lenguaje C significa vaco; es decir que no devuelve ningn valor
(primer void) ni puede recibir ningn valor, (segundo void, el cual esta encerrado entre
parntesis).
void main(void)
{
Nuestro cdigo
}
Nuestro cdigo lo hemos escrito en formato CCS nativo. Esto significa que hemos
usado todas las funciones embebidas (incluidas dentro) del compilador para simplificar
la escritura del cdigo y que nos ahorran mucho tiempo.
Debe observarse que cada lnea la hemos decalado (separado del origen) por medio del
TABULADOR; esto es una buena prctica para poder advertir a simple vista cuales
sentencias son las que estas anidadas dentro de cada bloque del programa principal.
La primera lnea o sentencia le indica al compilador que debe desactivar todos los
puertos analgicos del PIC y que debe configurarlos como puertos digitales:
setup_adc_ports(NO_ANALOGS);
Estas son funciones de salida de datos, se encargan de poner en uno o en cero un puerto,
el cual la misma funcin se encarga de configurar como salida, no debe hacerlo el
programador. Entre parntesis le indicamos el PIN a encender o apagar. En nuestro caso
es el RB0, al cual CCS lo denomina dentro del archivo de cabecera del
microcontrolador como PIN_B0.
Este formato si bien parece en principio raro porque no se adapta al usado en el data
sheet, es prctico para los programadores NO ELECTRNICOS, y es el que ha
adoptado CCS.
Por ejemplo el RA0 CCS lo llama PIN_A0, y al RC6, PIN_C6, y as sucesivamente.
Otra de las sentencias usadas es
delay_ms(500);
La cual es una funcin de tiempo que nos permite crear un tiempo de espera en
milisegundos. Tambin existe el delay_us que nos permite crear un delay de
microsegundos.
La exactitud de la funcin delay depende de que hayamos definido correctamente la
frecuencia de clock.
De esta forma hemos hecho falshear un LED en nuestro primer cdigo.
Bueno, esto es todo por ahora , en las prximas entregas iremos descubriendo paso a
paso las utilidades de la programacin en lenguaje C y del entorno CCS.
Continuar ......
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 3.
En nuestra entrega anterior creamos nuestro primer cdigo, el cual simplemente
nos hace falsear un LED conectado al PORTB. Hoy veremos como compilar es
cdigo dentro del MPLAB y grabar el mismo dentro del microcontrolador sin salir
del entorno de desarrollo y usando la herramienta PICKIT2 o equivalente
Esto activar los controles del PICkit2 programmer, los cuales aparecern como una
nueva barra de herramientas:
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 4.
Se dice que el lenguaje C es un lenguaje de nivel medio. La razn de esta
indicacin est en que en C se pueden crear programas que manipulan la mquina
casi como lo hace el lenguaje Ensamblador, pero utilizando una sintaxis que se
asemeja ms a los lenguajes de alto nivel. De los lenguajes de alto nivel toma las
estructuras de control que permiten programar de forma estructurada.
Al tener caractersticas de los lenguajes de bajo nivel se puede tomar el control absoluto
del microcontrolador. Adems tiene atajos que gustan mucho a los programadores al
tener una sintaxis menos restrictiva que lenguajes como Pascal por ejemplo, lo que le
convierte en el lenguaje idneo para crear cualquier tipo de aplicacin.
Sus caractersticas bsicas son:
La idea es:
parmetros nombreDeFuncin(parmetros)
{
Sentencias;
}
Los smbolos { y } indican el inicio y el final de la funcin. Esos smbolos permiten
delimitar bloques en el cdigo.
El nombre de la funcin puede ser invocado desde otras sentencias simplemente
poniendo como sentencia el nombre de la funcin.
Como a veces las funciones se almacenan en archivos externos, necesitamos incluir esos
archivos en nuestro cdigo mediante una sentencia especial #include , que en realidad es
una directiva de preprocesador. Una directiva de preprocesador es una instruccin para
el compilador con el que trabajamos.
El uso es:
#include <cabeceraDeArchivoExterno>
La directiva #include permite indicar un archivo de cabecera en el que estar incluida la
funcin que utilizamos. En el lenguaje C estndar los archivos de cabecera tienen
extensin h. Los archivos de cabecera son los que permiten utilizar funciones externas
(o libreras) en nuestro programa.
Una de las libreras ms utilizadas en los programas, es la que contiene las etiquetas de
todos los registros de funciones especiales del MCU PIC que hayamos seteado en el
proyecto. En el caso de CCS esta librera est disponible en la cabecera 16Fxxx.h
En todos los lenguajes de programacin, el primer programa a realizar es el famoso
Hola mundo, un programa que escribe este texto en pantalla. En el mundo de los
microcontroladores PIC, este programa se traduce en hacer titilar un led. De esta forma
en CCS el cdigo de este programa es:
#include <18f14k50.h>
#use delay(crystal=12000000)//
#fuses
HS,NOWDT,NOLVP,NODEBUG,NOBROWNOUT,NOPLLEN,CPUDIV1,PUT,MCLR
#define LED1
PIN_B4
void main(void)
{
setup_adc_ports(NO_ANALOGS);
while(1)
{
output_high(LED1);
delay_ms(500);
output_low(LED1);
delay_ms(500);
}
}
Qu es un comentario?
Se trata de texto que es ignorado por el compilador al traducir el cdigo. Esas lneas se
utilizan para documentar el programa.
Esta labor de documentacin es fundamental. De otro modo el cdigo se convierte en
ilegible incluso para el programador que lo dise. Tan importante como saber escribir
sentencias es utilizar los comentarios. Todava es ms importante cuando el cdigo va a
ser tratado por otras personas, de otro modo una persona que modifique el cdigo de
otra lo tendra muy complicado.
En C los comentarios se delimitan entre los smbolos /* y */ para los bloque y // para las
lineas
// Esto es un comentario usado para las lneas
/* Esto es un comentario el compilador har caso omiso de este texto*/
C maneja los datos en forma de variables y constantes, conceptos con los que
supondremos que el lector est familiarizado. Las variables, simbolizadas mediante
datos alfanumricos (cuyas reglas de construccin trataremos ms adelante), presentan
caractersticas que ser muy importante considerar:
Tipo de dato: cada variable (tambin las constantes) est caracterizada por el
tipo de dato que representa.
Visibilidad: en un programa C, cada variable tiene un rango de visibilidad
(procedimientos en los que es reconocida), que depende de cmo se la haya
declarado.
Existencia: relacionado con la anterior caracterstica, es posible que el contenido
de una variable perdure, o que se pierda, por ejemplo, al terminarse un
procedimiento.
El primero de ellos incluye todos los caracteres que tienen algn significado para
el compilador.
El segundo incluye todos los caracteres representables.
C acepta slo ciertos caracteres como significativos. Sin embargo, otros caracteres
pueden formar parte de expresiones literales (constantes literales, nombres de archivo,
etc.) que no sern analizadas por C.
Los caracteres a los que C asigna especial significado se pueden clasificar en
alfanumricos y signos especiales. Los caracteres alfanumricos incluyen las letras
(alfabeto ingls, de A a Z), maysculas y minsculas, los dgitos, y el guin bajo
(underscore: _).
En todos los casos, las maysculas son consideradas distintas de las minsculas. Toda
cadena alfanumrica con significacin en C est compuesta exclusivamente por estos
caracteres.
Los signos especiales son los listados a continuacin. Ellos se emplean como
delimitadores, operadores, o signos especiales.
Maysculas: A - Z
Minsculas: a - z
Dgitos: 0 9
Guin bajo: _
Coma ,
Punto .
Punto y coma ;
Dos puntos :
Signo de interrogacin ?
Signo de admiracin !
Comilla simple
Comilla doble
Barra vertical |
Barra /
Barra invertida \
Tilde ~
Signo ms +
Signo menos Parntesis izquierdo (
Parntesis derecho )
Corchete izquierdo [
Corchete derecho ]
Llave izquierda {
Llave derecha {
Signo Mayor >
Signo Menor <
Signo igual =
Asterisco *
Ampersand &
Porciento %
Caret ^
Qu es un identificador?
Los identificaremos se utilizan para identificar, (valga la redundancia): variables, constantes, funciones,
etc.
Deben comenzar con una letra. Mxima longitud: 32 caracteres.
Slo pueden contener letras y nmeros, pero no caracteres especiales, salvo el guin bajo, (underscore).
No se deben confundir con palabras reservadas de C, (una variable, por ejemplo no puede llamarse int, ni
main, etc.) y hay diferencias entre maysculas y minsculas. Como norma se utilizan las minsculas; las
maysculas se usan para las constantes.
Las palabras reservadas o tambin conocidas como palabras claves sirven para indicar al
microcontrolador que realice una tarea muy determinada (desde evaluar una comparacin, hasta definir el
tipo de una variable) y tienen un especial significado para el compilador es por ello que no pueden usarse
como identificadores:
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
BYTES
1
1
2
4
4
0
0
BYTES
1
2
4
8
4
8
1
0
A diferencia del compilador ANSI C CCS tiene sus tipos de datos predefinidos sin
signo, es decir que solo podemos almacenar valores positivos excepto que
especifiquemos antes del tipo la palabra clave signed
ACCIN
Resta
Suma
Multiplicacin
divisin.
(slo para enteros) Resto de la divisin entera
Decremento
Incremento
ACCIN
Mayor que
Mayor igual que
Menor que
Menor igual que
Igual que
Distinto que
ACCIN
And
Or
Not
La operacin lgica no se realiza a nivel bit entre los operandos, sino que establece una
relacin entre condiciones comparativas en las que participan los operandos, ejemplo
(condicin 1) && (condicin 2) establece que si se cumple la condicin 1 y la condicin
2.
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 5.
FORMATO
Un solo carcter
Decimal (un entero)
Un entero
Punto decimal flotante
Notacin cientfica
Octal
Hexadecimal
Entero sin signo
Cadena de caracteres
Imprime un signo %
Direccin de un puntero
Los formatos pueden tener modificadores para especificar el ancho del campo, el
nmero de lugares decimales y el indicador de alineacin a la izquierda.
Ejemplos:
%05d, un entero de 5 dgitos de ancho; rellenar con ceros. Alineado a la derecha.
%10.4f, un real de 10 dgitos de ancho, con 4 decimales. Alineado a la derecha.
%-10.2f, un real de 10 dgitos de ancho, con 2 decimales. Alineado a la izquierda.
DESCRIPCIN
Salto de lnea retorno de carro (ENTER)
Tabulado horizontal
Tabulado vertical
Retorno de carro.
Backspace.
Alimentacin de pgina.
Continuar ......
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 6.
Cules son las estructuras bsicas de C?
Estas estructuras son las que le dan inteligencia al programa permitiendo que el
microcontrolador haga algo a partir de una condicin que es evaluada
Sentencia if:
Forma general:
if (condicin)
sentencia1;
else
sentencia2;
Si la condicin es verdadera (se cumple), se ejecuta la sentencia1, de lo contrario la
sentencia2. (esta estructura suena de la siguiente forma: si la (condicin) se cumple, se
ejecuta la sentencia1, sino, se ejecuta la sentenca2.
Y anidar:
if (x)
if (a<b)
printf(a es mayor);
else
printf(a no es mayor que b);
en caso que el else est asociado al if(x) se debera hacer:
if (x)
{
if (a<b)
printf(a es mayor);
}
else
printf(x es 0);
La sentencia switch:
La sentencia switch permite evaluar diferentes valores para una misma variable:
Su forma general es:
switch(variable)
{
case valor1:
sentencias;
break;
case valor2:
sentencias;
break;
case valor3:
sentencias;
break;
.
.
.
default:
sentencias;
}
El switch evalua cada caso, cuando coincide uno de ellos con el contenido de la
variable, ejecuta las sentencias del caso y termina el switch. En caso de no encontrar
ningn case que corresponda, en igualdad, con el contenido de la variable, ejecuta las
sentencias de la clusula default, si esta ha sido especificada, sino termina el switch.
Ejemplo:
La sentencia switch se usa en general para seleccionar menes de opciones, en este
segmento de cdigo lo que se explora es justamente el valor de la opcin seleccionada,
y segn la misma ser la operacin realizada:
switch(opcion)
{
case 1:
res = valor*valor;
printf(El cuadrado de %i es %i\n, valor, res);
break;
case 2:
res = valor*valor*valor;
printf(El cubo de %i es %i\n, valor, res);
break;
case 3:
res = valor % 2;
if (res)
prinf(El nmero %i es impar\n, valor);
else
printf(El nmero %i es par\n, valor);
break;
default:
printf(Opcin erronea);
}
La variable opcion contiene el valor del men seleccionado por el usuario. En cada case
lo que se explora es si la variable ha adquirido ese valor.
Para un bloque de sentencias (recordemos que el bloque queda definido por las llaves.
for(inicializacin; condicin; incremento)
{
sentencias;
}
Tambin puede funcionar al revs, (los primeros 100 enteros mostrados de 100 a 1);
for(i=100; i>=1; i - -)
printf(%d, i);
Se pueden evaluar ms de una variable:
int i, j;
for(i=1, j=100; i<=100, j>0; i++, j - -)
printf(i = %d, j= %d\n, i, j);
El siguiente bucle no termina nunca, (bucle infinito):
for( ; ; )
Debemos recordar que si la cantidad de sentencias, (equivalencias, operaciones
aritmticas, llamadas a funciones, etc.), pertenecientes al bucle son ms de una, estas
deben ir entre { }.
El bucle while:
El bucle while permite ejecutar una o mas sentencias en tanto se cumpla una condicin.
Si la condicin deja de cumplirse, se dejan de ejecutar la o las instrucciones y se sale
del bloque while para continuar procesando las instrucciones que se encuentran despus
del mismo
while (condicin)
sentencia;
while (condicin)
{
sentencia1;
sentencia2;
sentencia3;
sentencia4;
.
.
Senttencia_n;
}
Ejemplo:
char salir;
salir = n;
while (salir != n)
{
printf(Estoy dentro del mientras\n);
getc(%c, &salir);
}
printf(\nYa sal);
El bucle tambin puede estar vaco. El siguiente ejemplo funcionar hasta que se pulse
la letra A:
while ((letra = getc()) != A);
El bucle do while:
La diferencia que existe con el while, es que en el bucle do while por lo menos una
vez, el programa ejecuta las sentencias del bucle, (hasta llegar a la sentencia while), y
luego decide si contina iterando, siempre que se cumpla la condicin examinada por el
while.
ACCIN
AND entre bits
OR entre bits
XOR entre bits, (or exclusivo).
NOT , (si es 1 pasa a ser 0 y viceversa)
Desplazamiento a izquierda
Desplazamiento a derecha
Estructuras De Datos:
Arrays:
Un array es una coleccin de elementos de un mismo tipo, que se referencian usando un
nombre de variable comn. En C, el array ocupa posiciones de memoria contiguas. La
direccin ms baja corresponde al primer elemento y la ms alta al ltimo. Para acceder
a un elemento especfico se usan ndices.
Arrays unidimensionales:
Forma general de declararlos:
tipo nombre-variable[tamao];
Ejemplo:
int numeros[10];
Es un arreglo de 10 elemento enteros, donde el primero es numeros[0] y el ltimo
numeros[9].
Guardemos en este array los nmeros dgitos, (0 al 9):
for(i=0; i<=9; i++)
numeros[i] = i;
ATENCIN: El lenguaje C no hace comprobacin de lmites, es decir que se pueden
seguir ingresando valores, por encima del tamao asignado al array, con consecuencias
peligrosas, ya que puede grabar sobre el propio programa, an peor, daar el sistema
operativo. El C no emite mensaje, ni en tiempo de compilacin ni en tiempo de
ejecucin, para sealar este error. Queda en manos del programador asignar el tamao
necesario a los arrays que utilicen sus programas.
Cuando se declara un array, tambin se le puede asignar valores iniciales.
Ejemplos:
int numeros[10] = {1,2,3,4,5,6,7,8,9,10};
char cadena[6] = hola;
char cadena[5] = {h, o, l, a, \0};
Cadenas (Strings):
En C no existe un tipo de datos especfico para declarar cadenas, en su lugar la idea de
cadena surge de un array de caracteres que siempre termina con el carcter nulo, (\0) y
cuya posicin debe contemplarse al dimensionar el array.
Para guardar una cadena de 10 caracteres:
char cadena[11];
Cuando se introduce una constante de cadena, (encerrada entre dobles comillas), no es
necesario terminar con el carcter nulo, ya que el C lo crea automticamente.
Ejemplo: El segmento del siguiente programa que muestra una cadena introducida
desde el teclado usando el Hyperterminal y la USART del Microcontrolador:
char cadena[100];
printf(Ingrese cadena, de hasta 100 caracteres\n);
gets(cadena);
printf(Usted ingres: %s, cadena);
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 7.
Assembler embebido
Se puede insertar cdigo en assembler mediante #asm y #endasm.
Dentro de un bloque en assembler no se deben usar:
Ejemplo:
#asm //codigo en Assembler
MOVLW 10 // Movemos decimal al contador
MOVWF count, 0
inicio: //etiqueta
NOP
NOP
DECFSZ count, 1, 0 //decrementamos el contador
BRA inicio
salir:
#endasm
//salimos del bloque assembler
Ejemplo:
struct Reloj
{
char hora;
char minuto;
char segundo;
}
De esta forma se define una estructura llamada reloj, ahora hay que declarar una
variable de este tipo:
struct Reloj Time;
En este caso la variable es de tipo empleado y se pueden acceder a los campos
miembros de la estructura de la siguiente forma:
Time.hora
Time.minuto
Time.segundo
Las estructuras son muy usadas para crear campos de BITS que nos permitan usar de
forma individual cada uno de los BITS de los registros de funciones especiales.
sentencias
return(valor_de_retorno);
Los posibles tipos de retorno son los tipos de datos ya vistos: (int, float, void, char,etc).
Para crear una funcin en C, primero hay que declarar el prototipo de la misma antes de
la funcin main() y luego de la llave final del programa se define la funcin.
Ejemplo:
La siguiente funcin suma dos valores y retorna un resultado:
int suma(int x, int y)
{
return x+y;
}
Se retorna de una funcin cuando se llega a la sentencia return o cuando se encuentra la
llave de cierre de la funcin.
Cuando lo que se desea escribir es un procedimiento que, por ejemplo, realice un delay
o muestre un texto por LCD o cargue una arreglo, o sea, que no devuelva ningn valor
se escribe como tipo de retorno void,( que significa tipo vaco).
Variable local:
Se declara apenas abrir una llave en el cdigo, cuando la llave se cierra esta variable
desaparece.
Ejemplo:
void calcula_voltaje (int val, float &voltaje)//funcion que
calcula el voltaje
{
voltaje=(val*v_max)/escala;
}
En el ejemplo de la funcin observamos el apuntador & que apunta a la variable voltaje,
de esta forma le pasamos el valor de la variable a la posicin que la misma ocupa.
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 8.
A partir de aqu comenzaremos a usar lo aprendido en los captulos anteriores. La
nica forma de asimilar e incorporar nuevos conocimientos, es poner en prctica lo
que se aprende. Iremos desde lo simple a lo complejo, desde el encendido de un
LED hasta el control por PC de nuestra aplicacin o circuito electrnico.
Para trabajar podemos usar un protoboard, sin embargo no soy muy amigo de este tipo
de herramientas ya que es fcil encontrarse con falsos contactos y crear verdaderas
maraas de cables. Es preferible construir un circuito elemental que tenga todos los
perifricos que veremos o en su defecto adquirir ya la placa armada. Si bien el adquirir
algo armado nos quita el sabor del hgalo usted mismo, nos permite ganar tiempo.
Otra herramienta que se puede usar es el PROTEUS, sin embargo la virtualizacin de
un circuito no nos permite afrontar las problemticas reales, como son los rebotes, ruido
electromagntico, etc.
Yo presentar el esquema de una placa ideal y aconsejar la compra de un modelo, sin
embargo queda en el lector el tomar estas ideas u optar por las opciones anteriores que
tambin son vlidas, lo importante es aprender.
De todas estas familias, las ms antiguas son los PIC Lnea Base y PIC Lnea Media,
concebidos para ser programados en Lenguaje Assembler, con lo cual las limitaciones
de su arquitectura, tambin limitan la cantidad de cdigo que se puede escribir en
Lenguaje C dentro del microcontrolador. Es por ello que a partir de la creacin de la
familia PIC18F y desde all en adelante, todos los microcontroladores se
concibieron para trabajar en Lenguaje C.
Sin embargo el mercado de los microcontroladores PIC Lnea Media es muy amplio y
para estos usuario Microchip mejor el ncleo de estos MCU, desarrollando una nueva
generacin , a la cual ha bautizado como PIC Lnea Media Mejorada, los cuales se
identifican por su cdigo inicial: PIC16F1xxx o PIC12F1xxx.
Esta renovacin de los viejos ncleos PIC16F introduce todas las mejoras que han
adquirido los PIC18F con el Tiempo.
Dichas caractersticas son las siguientes:
Todas estas nuevas caractersticas hacen de estos PIC los sucesores indiscutibles de la
vieja familia PIC16F con la posibilidad de migracin a PIC18F menos abrupta.
Para iniciar en nuestro curso, trabajaremos con el PIC16F1939, el cual reemplaza
tcitamente a los viejos PIC16F877A y con menor costo.
El nuevo PIC16F1939
Este microcontrolador, forma parte de la familia PIC16F193X, la cual esta constituida
por los siguientes dispositivos:
Las fuentes generadoras del clock para alimentar la CPU y los Perifricos pueden ser
distintas:
Si usamos un cristal o un resonador externo, este lo podemos conectar entre los
terminales OSC1 y OSC2. En caso de usar cristales, estos deben ser configurados en los
bits de configuracin como HS, XT o LP, segn el rango de frecuencias donde trabajen.
Para esto Microchip nos da una tablita de referencia:
En estos casos el hardware se realizar no solo conectando el respectivo cristal entre los
terminales, sino tambin 2 capacitores del tipo cermico, preferentemente NP0 respecto
a masa, para estabilizar la frecuencia, y eliminar armnicos indeseados.
En este caso el sistema utiliza un bit denominado SCS (System Clock Select ), el cual se
encuentra dentro de un registro interno que controla al oscilador y que se denomina
OSCCON. Este bit permite realizar la conmutacin por software desde el oscilador
externo al interno y viceversa.
Por lo general, excepto que se este diseando una aplicacin donde se debe ahorrar al
mximo los recursos de energa, la opcin del IESO no se utiliza.
Otro recurso novedoso es el detector de la falla del oscilador primario o externo FSCM
(Fail-Safe Clock Monitor). Este modulo, cuando se activa, monitorea el oscilador
primario (LP, XT,HS, EC, RC y el Oscilador del Timer1). Para ello compara este
oscilador con la seal de clock de 31Khz del LFINTOSC. Si el oscilador externo llegase
a perder pulsos de clock, esto ser detectado por el FSCM, lo cual activar una
bandera indicadora denominada OSFIF (Oscilador Fail Interrupt Flag), la cual si se
encuentra debidamente habilitada por medio del bit OSFIE, generar una interrupcin,
mediante la cual se puede conmutar hacia el oscilador interno usando el bit SCS
mencionado anteriormente y pasar a trabajar con el oscilador interno HFINTOSC
seteado en algn valor de frecuencia por medio del divisor de frecuencia programable.
Todas estas caractersticas pueden ser habilitadas o no, mediante el correcto seteo de los
fusibles de configuracin usando la directiva #FUSES.
Dentro de la carpeta PICC del compilador encontraremos una carpeta denominada
DEVICES, dentro de la cual encontraremos los archivos de cabecera que contienen
todas las etiquetas para manejar los microcontroladores PIC de forma sencilla y
configurar todas las opciones vistas. Existe un archivo de cabecera por cada micro:
Dentro de este archivo podemos ver el conjunto de etiquetas que nos permiten setear
estas opciones parra configurar los fusibles de configuracin desde el cdigo, usando la
directiva #FUSES:
Estas etiquetas pueden cambian entre microcontroladores porque no todos tienen las
mismas opciones de configuracin, de hecho algunas de las que mencionamos son
exclusivas de los PIC16F1XXX y PIC18F, mientras que en los PIC16F convencionales
no se encontrarn. Por ello es buena prctica que a nuestros proyectos le adjuntemos el
archivo de cabecera de nuestro microcontrolador, a modo de consulta:
Para asimilar estos conceptos vamos a aplicarlos en un proyecto inicial, el cual consiste
e leer 3 pulsadores y accionar 3 leds.
En este caso configuraremos las opciones de los fusibles de configuracin de la
siguiente manera:
LED1
LED2
LED3
SW1
SW2
SW3
PIN_B0
PIN_B1
PIN_B2
PIN_A0
PIN_A1
PIN_A2
//PORTB
//PORTB
//PORTB
//PORTA
//PORTA
//PORTA
RB0
RB1
RB2
RA0
RA1
RA2
Segn el estado lgico que se cargue en un bit del registro TRIS, el PORT
correspondiente trabajar como entrada o salida (1= Entrada, 0=Salida).
Los puertos tiene la capacidad de entregar como mximo una corriente de 25ma. Y
reconocen el estado lgico como la lgica TTL, es decir que cualquier tensin por
encima de los 2,5V es reconocida como 1 lgico, y por debajo de 0,8V como un cero.
Por otra parte entregan una tensin 1 lgico como los CMOS, la cual llega a VCC.
En los microcontroladores PIC la mayora de los puertos estn multiplexados con otras
funciones, como ser puertos de comunicaciones, entradas para el conversor analgico,
entradas a comparadores de voltaje, salidas PWM, etc.
Cuando un PIC arranca su operacin, la inicia con sus capacidades analgicas activas,
esto significa que aquellas entradas que se conectan al conversor analgico digital o a
los comparadores, o como en el caso del PIC16F1939, las entradas MTOUCH.
Es por esta razn que el usuario debe configurar dichas entradas como analgicas o
digitales antes de usarlas. Para ello existe saciado a cada PORT, un registro denominado
ANSELA para el PORTA, ANSELB para el PORTB, ANSELE para el PORTE y
ANSELD para el PORTD. Para que un puerto determinado funcione como digital, al
ANSEL correspondiente hay que ponerlo en estado lgico 1.
Para simplificar el manejo de los puertos CCS tiene una serie de funciones embebidas,
es decir que estn incorporadas en el mismo compilador, y que no se necesita agregar
ningn archivo de cabecera para usarlas.
Estas son:
output_high(PIN_XY); //pone en uno un pin determinado
output_low(PIN_XY); //pone en cero un pin determinado
output_bit(PIN_XY,estado); //pone en cero o uno un pin determinado
output_X(valor); //saca un valor de 8 bits por un puerto determinado
input(PIN_XY);
//lee el estado de un pin y nos devuelve el mismo
input_X(); //lee el estado de un puerto completo y devuelve el mismo
Para nuestro caso como no usaremos los puertos analgicos, le pasaremos a esta funcin
la etiqueta NO_ANALOGS, como figura en el archivo de cabecera 16F1939.h:
Lo que nos queda simplemente es el cdigo, el cual estar incluido dentro de un bucle
infinito, realizado mediante un while(TRUE), ya que esa ser la tarea que eternamente
deber realizar el microcontrolador.
La tarea es sencilla: nuestra CPU solo debe ver que pulsador (SW) se accion y
conforme a ello encender un LED determinado. Para cubrir este objetivo usaremos las
funciones para control I/O embebidas y las estructuras condicionales IF:
//bucle principal
while(TRUE){
if(input(SW1))
output_high(LED1);
else
output_low(LED1);
//chequeamos si SW1=1
//si si, encendemos LED1
//sino
//apagamos LED1
if(input(SW2))
output_high(LED2);
else
output_low(LED2);
//chequeamos si SW2=1
//si si, encendemos LED2
//sino
//apagamos LED2
if(input(SW3))
output_high(LED3);
else
output_low(LED3);
}
//chequeamos si SW3=1
//si si, encendemos LED3
//sino
//apagamos LED3
El esquemtico lo hemos realizado con el Proteus, y es por esta razn que debemos
advertirles que los pines de alimentacin NO FIGURAN EN EL CIRCUITO, ya que
PROTEUS da por sentado que el tcnico ya sabe como alimentarlo.
Dichos pines, para los encapsulados de 40 terminales son VCC:11 y 32, GND:12 y 31
Para poder programar nuestro cdigo dentro del microcontrolador, prepararemos en el
extremo del circuito impreso un conector de tira de pines (5 postes) para realizar la
conexin ICSP segn el siguiente esquema:
Como esta conexin ser un estndar en nuestros circuitos ya que es una forma muy
prctica de programar nuestro programa de aplicaciones sobre el PCB sin retirar el
microcontrolador del mismo. Este mismo esquema de conexin ICSP es la que utiliza la
herramienta del tipo PICKit2 diseada por la firma edudevices
(www.edudevices.com.ar) para el mercado de Argentina. El lector podr observar,
luego con el uso, la velocidad que adquiere la depuracin de un cdigo utilizando este
tipo de herramientas y las bondades del entorno CCS.
Continuar .....
Aprendiendo a programar
Microcontroladores PIC en
Lenguaje C con CCS
Entrega N 9.
La secuencia de nuestro programa ser muy simple; leer los pulsadores y en funcin del
pulsador que accionemos, cambiaremos la funcin del dispositivo.
Las funciones de la aplicacin estarn controladas por 2 Flags (banderas) internos, los
cuales se implementan mediante la creacin de 2 variables de 1 bit, y a las que
llamaremos FLAG_RUN y FLAG_FWRW.
La aplicacin estar constituida por 2 rutinas o funciones del tipo void-void, que leern
el estado de los pulsadores (ScanKey) y controlaran el funcionamiento del motor
(MotorControl).
Para implementar el programa usaremos las funciones embebidas estudiadas
anteriormente y los recursos del lenguaje C tambin estudiados en los apartados
anteriores.
//Rutinas auxiliares:
void ScanKey(void)
{
if(input(BTN1))
//lee el estado del pulsador
{
//si el mismo est accionado
FlagRUN=!FlagRUN;//cambia el estado de FlagRUN
MotorControl();//llamada a la funcin que controla el motor
delay_ms(2);//espera para evitar leer el rebote al oprimir
while(input(BTN1));//re-lectura espera que se suelte
delay_ms(2);//espera para evitar leer el rebote al soltar
}
if(input(BTN2))
//lee el estado del pulsador
{
//si el mismo est accionado
FlagFWRW=!FlagFWRW;//cambia el estado de FlagFWRW
MotorControl();//llamada a la funcin que controla el motor
delay_ms(2);//espera para evitar leer el rebote al oprimer
while(input(BTN2));//re-lectura espera que se suelte
delay_ms(2);//espera para evitar leer el rebote al soltar
}
void MotorControl(void)
{
if(FlagRun==1)// FlagRUN=1 ?
output_high(RUN);//habilita el motor
else
{
output_low(RUN);//sino desactiva el L293
output_low(FW);//apagamos FW y RW
output_low(RW);
}
if(FlagRun==1)// FlagRUN=1 ?
{
if(FlagFWRW==1)// FlagFWRW=1?
{
output_low(RW); //apaga RW
delay_ms(50);
//espera
output_high(FW);//enciende
}
else
// Sino
{
output_low(FW);//apaga FW
delay_ms(50); //espera un
output_high(RW);//enciende
}
}
un tiempo
FW
tiempo
RW