Documentos de Académico
Documentos de Profesional
Documentos de Cultura
http://www.ccsinfo.com/ccsfreedemo.php
http://www.labcenter.co.uk/download/prod
emo_download.cfm
1
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Nos saldrá un cuadro de dialogo de guardar de Windows, donde le pondremos un nombre a nuestro
archivo y lo guardaremos. Tener cuidado de crear una nueva carpeta para cada proyecto que
hagamos; en el cual guardaremos el archivo.c del programa y el archivo.dsn del Proteus. Después
escribimos el código fuente que se muestra en la figura de abajo y guardamos el documento:
En primer lugar nos encontramos con tres directivas del prepocesador, las identificaremos porque
empiezan por el símbolo (#):
2
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
concreto se incluye el archivo <16F877A.h>,en este archivo se incluyen las definiciones de los
registros del PIC.
• #use delay (clock=4000000); directiva para el uso de retardos, entre paréntesis tenemos que
poner la frecuencia de reloj que vamos a utilizar.
En segundo y último lugar se encuentra la función main. Este es el núcleo del programa, el que va
a incluir todos los pasos a seguir durante su ejecución. En nuestro primer ejemplo solo contiene
una sentencia que hace una llamada a la función printf(), esta función se encarga de mostrar un
mensaje por el dispositivo de salida RS-232.
El mensaje que muestra la función printf es el que recibe como parámetro (el texto entre
paréntesis). Dicho mensaje es delimitado por las comillas dobles, que indican el principio y el fin
de una cadena de texto.
Vemos que el archivo de salida no nos ha producido ningún error. Por tanto el proyecto se ha
generado correctamente. Y si vamos a la carpeta donde habíamos guardado nuestro primer
ejemplo, tenemos todos los archivos que nos ha creado el IDE:
3
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
De todos estos archivos los que mas nos interesa son los que están marcados en la figura de
arriba. El archivo Primer_Programa.hex es el que tenemos que utilizar para programar el PIC y el
que termina con extensión .cof lo utilizaremos para cargarlo en el simulador Proteus y poder
simular el programa paso a paso, entre otras posibilidades muy útiles a la hora de depurar nuestro
código.
En la ventana que nos aparece en el campo Keywords escribimos el nombre de nuestro PIC.
4
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
simulador es capaz de hacer funcionar nuestro circuito sin algunos elementos que serían
necesarios si decidimos montar nuestro circuito en una placa real (por ejemplo la alimentación del
PIC y el cristal de cuarzo).
El pin del PIC que habíamos elegido como transmisión de datos en nuestro programa irá
conectado al terminal RXD de recepción de datos en el Terminal Virtual y viceversa. Una vez
terminado de colocar todos los componentes para la simulación, conviene grabar el archivo
poniéndole un nombre adecuado. Para nuestro caso lo llamaremos Programa1.dsn, luego de ello
solo nos queda cargar nuestro programa en el PIC para poder simularlo, para ello hacemos doble
clic sobre el PIC y nos aparecerá la ventana de la figura de abajo:
5
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Los valores que en un principio tenemos que introducir para que nuestra simulación funcione son
los que están señalados en la figura de arriba. En Program File pincharemos sobre la carpeta y
seleccionaremos el archivo con extensión .cof que se había creado al compilar nuestro programa,
si en vez de este seleccionamos el que tiene extensión .Hex funcionará igual pero no podremos
realizar la simulación paso a paso. El otro valor a tener en cuenta es que la frecuencia del reloj del
PIC debe coincidir con el valor que le habíamos puesto en el programa en nuestro caso 4 MHz.
Si ahora hacemos clic sobre el botón Play se nos abrirá una terminal al estilo
MSDOS donde nos mostrará la salida de nuestro programa:
Ahora si le damos al botón de simulación paso a paso podremos simular nuestro ejemplo paso a
paso desde cualquier momento o mejor si antes le damos STOP (para programa) y reanudamos la
simulación, peo esta vez presionando el botón STEP . Entonces nos aparecerá
la siguiente ventana donde podemos ver la ejecución del programa línea a línea o poner puntos de
interrupción en las partes del programa que nosotros queramos:
6
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Ejercicio de calentamiento:
Cambiar el PIC utilizado a PIC16F628A tanto en el compilador CCS como en el Simulador PROTEUS.
Lo que va entre corchetes es porque es opcional es decir, las variables se pueden inicializar ó no al
declararlas. Ejemplo de variable declarada:
int i;
En una misma línea se puede declarar más de una variable siguiendo el siguiente formato:
tipo nombre_variable1,nombre_variable2,....;
Hay que tener en cuenta que la línea tiene que acabar en punto y coma.
El tipo de datos es obligatorio ponerlo y le dice al compilador cuantas celdillas de memoria tiene que
reservar para almacenar el valor de la variable. Los tipos de datos pueden variar de un compilador a otro,
vamos a ver los tipos de datos que podemos usar con nuestro compilador CCS.
Los tipos de datos básicos que utiliza nuestro compilador son los siguientes:
7
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Vamos a agregar algunas variables al programa anterior para poder entender mejor como es que se
utilizan. Agregar las siguientes líneas de modo que quede como se ve:
short a=1;
int entero=255;
long largo=65535;
float flotante=3225.76;
char caracter='A';
void main()
{
printf("Hola Mundo, mi primer programa para PICS en Lenguaje C\r");
printf("variable short = %d\r", a);
printf("variable int = %u\r", entero);
printf("variable long = %lu\r", largo);
printf("variable float = %f\r", flotante);
printf("variable char = %c\r", caracter);
}
CONSIDERACIONES: Hay que intentar siempre utilizar el tipo de dato que menos memoria ocupe
dentro de los valores que pueda utilizar la variable. Si abusamos de los tipos grandes para almacenar
valores pequeños nos quedaremos sin memoria y en los programas grandes es un dato que tenemos
que tener en cuenta.
8
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
El LCD es usado para usado para representar caracteres alfanuméricos. Tiene una Memoria RAM de
pantalla (Display Data RAM: DDRAM) con un total de 80 posiciones. En los 8 bits se almacena el código del
carácter para un generador de caracteres ROM que dispone de 240 caracteres posibles y 8 posiciones
(dobles) para caracteres definibles por el usuario en una memoria CGRAM (caracteres gráficos).
Sólo son visibles 1 ó 2 líneas con 16 caracteres por línea. La DDRAM almacena el código de los caracteres
que están siendo visualizados o que se encuentran en posiciones no visibles debido a la posición de la
ventana de visualización.
9
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
La manera más sencilla de utilizar el LCD es utilizando un driver específico para ello proporcionado por
el mismo compilador CCS: el fichero lcd.c que define las funciones indicadas a continuación.
lcd_init ();
Debe llamarse antes que ninguna otra función del fichero lcd.c.
Tal y como aparece en el fichero, además de borrar el display, configura el LCD para trabajar como
sigue:
lcd_gotoxy (x , y);
Establece la posición del LCD a la que se debe acceder.
Recuérdese que la primera posición de la primera línea tiene coordenadas (1 , 1), y que la primera
posición de la segunda línea es la (1 , 2).
lcd_putc (dato);
Escribe dato en la posición a la que apunta el puntero de direcciones.
La variable dato es de tipo char, y se definen algunos caracteres especiales:
\f Borra el display
\n Se posiciona en el inicio de la segunda línea
\b Retrocede una posición
También pueden usarse las secuencias de escape disponibles para la función printf:
\r Retorno de carro
\t Tabulador
\' Comilla simple
\" Comillas dobles
\\ Barra invertida
\? Símbolo de interrogación
\0 Caracter nulo
\% Símbolo Tanto por ciento
10
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
lcd_getc (x , y);
Devuelve el carácter que ocupa la posición (x , y) del LCD.
Por defecto, este driver usa siete bits del puerto B para establecer la comunicación entre el LCD y el
microcontrolador.
Para enviar caracteres al LCD se utiliza la función PRINTF según la siguiente sintaxis:
Cadena: Cadena de caracteres que puede formarse usando el contenido de una o más variables.
Variables: Variables incluidas en la cadena (separadas por comas).
Para indicar la posición y el tipo de las variables a incluir en la cadena, se usa el formato %wt, donde w
es opcional.
Algunos ejemplos:
printf(lcd_putc , ”Hola”);
printf(lcd_putc , ”Tecla %c pulsada %u veces” , key , cont );
Ejercicio:
Después de conocer un poco sobre el LCD, ahora vamos a desarrollar el siguiente ejercicio:
Displayar los mensajes anterios en el LCD. Para esto antes haremos los cambios necesarios en el PROTEUS.
Después de hacer los cambios, la pantalla debe quedar como sigue:
11
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
#include <16F628A.h>
#use delay(clock=4000000)
//#use rs232 (baud=9600, parity=N, xmit=PIN_B2, rcv=PIN_B1)
short a=1;
int entero=255;
long largo=65535;
float flotante=3225.76;
char caracter='A';
void main()
{
lcd_init(); //inicializa lcd
El compilador de CCS incorpora una serie de funciones integradas orientadas a trabajar con los puertos E/S.
Los parámetros de tipo pin* se corresponden con identificadores definidos en el 16F84a.h cuyo formato es
PIN_Xn (X es el puerto y n es el número de pin).
Ejercicio:
Cree una nueva carpeta con el nombre ENVIO DE DATOS. Dentro del mismo simule el siguiente programa para
ver el uso de envio de datos a nivel de bits y bytes:
12
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
//PROGRAMA PRINCIPAL:
void main(void)
{
output_b(0b10101010);
delay_ms(1000);
output_b(0b01010101);
delay_ms(1000);
}
El lenguaje C define numerosos operadores mediante los cuales se construyen las expresiones
(combinación de operadores y operandos).
Operadores aritméticos
+ - * / % (resto de división de enteros)
Operadores relacionales
> >= < <= == !=
Operadores lógicos
13
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
7. SENTENCIAS REPETITIVAS
Son aquellas que ejecutan un bloque de sentencias mientras se cumpla una expresión lógica. Este bloque
de sentencias que se ejecuta repetidas veces, se denomina bucle, y cada ejecución se denomina iteración.
a. Sentencia WHILE
La sentencia while permite la ejecución de un bloque de sentencias si se evalúa como verdadera una
expresión lógica. La expresión lógica aparece al principio del bloque de sentencias.
El Pseudocódigo es una forma informal de representar la secuencia del programa, sin tener en cuenta
la sintaxis particular del lenguaje en que vayamos a programar y el diagrama de flujo es una
representación gráfica del Pseudocódigo.
El bloque delimitado por las llaves puede reducirse a una sentencia, y en este caso se suprimen las llaves.
La expresión lógica debe estar delimitada por paréntesis. Cuando el programa llega a una sentencia while,
sigue los siguientes pasos.
• Evalúa la expresión.
• Si es falsa, continua la ejecución tras el bloque de sentencias.
• Si es verdadera entra en el bloque de sentencias asociado al while.
• Ejecuta dicho bloque de sentencias, evaluando de nuevo la expresión y actuando en consecuencia.
b. Bucle for()
El bucle for permite indicar estos tres elementos en un solo lugar, al principio del bucle, facilitando así
la obtención de un código compacto, pero legible. Veamos cual es su sintaxis:
En un bucle for, el paréntesis que acompaña a la palabra reservada for generalmente contiene tres
expresiones: Expresión 1; inicializa la variable ó variables de control del bucle. Expresión 2; representa
la condición de continuación en el bucle. Expresión 3; modifica el valor de las variables de control en
cada iteración del bucle.
c. Bucle do-while()
A diferencia de los bucles for y while, que analizan la condición del bucle al principio del mismo, el
bucle do-while analiza la condición al final del bucle. Esto significa que el bucle do-while siempre se
ejecuta al menos una vez. La forma general del bucle do-while es la que se muestra en la figura de
abajo:
15
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
d. Sentencia IF
Vamos a empezar las sentencias condicionales, con la más simple de todas, la sentencia if. Si se evalúa
como cierta la expresión que hay entre paréntesis al principio de la sentencia if se ejecuta el bloque de
sentencias contenido entre las llaves y si se evalúa como falsa la condición, el programa se salta ese
bloque de instrucciones. En la figura de abajo tenéis la sintaxis de esta sentencia.
16
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
if (x=1)
e. Sentencia If…Else
Cuando el programa llega a una sentencia condicional del tipo If …Else, primero se evalúa una
expresión; si se cumple (es cierta) se ejecuta un bloque de sentencias y si es falsa se ejecuta otro
bloque.
d. Sentencia switch
La sentencia switch se compone de las siguientes palabras clave: switch, case, default y break. Lo que
hace está sentencia es comparar sucesivamente el valor de una expresión (dicha expresión tan solo puede
ser de tipo entero o de tipo carácter) con una lista de constantes enteras o de caracteres. Cuando la
expresión coincide con la constante, ejecuta las sentencias asociadas a ésta.
17
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
La sentencia break hace que el programa salte a la línea de código siguiente a la sentencia switch. Si se omite
se ejecutará el resto de casos case hasta encontrar el próximo break.
La sentencia default se ejecuta cuando no ha habido ninguna coincidencia. La parte default es opcional y, si no
aparece, no se lleva a cabo ninguna acción al fallar todas las pruebas y el programa seguirá a partir de la llave
que cierra la sentencia switch
En una sentencia switch No puede haber dos sentencias case con el mismo valor de constante. Una
constante char se convierte automáticamente a sus valores enteros.
Switch difiere del if en que switch solo puede comprobar la igualdad mientras que if puede evaluar
expresiones relacionales o lógicas. Además cuando la comparación se basa en variables o se trabaja con
expresiones que devuelven float deberemos usar el if-else.
Hay que decir que la secuencia de sentencias en un case no es un bloque (no tiene porque ir entre llaves).
Por lo tanto no podríamos definir una variable local en él. Mientras que la estructura switch global sí que es
un bloque.
18
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
EJEMPLO 1: Captura de Datos por el Puerto B y salida por el puerto A a través de Decodificador.
Objetivo del programa: El PIC simplemente captura los datos por el puerto B con el comando
input_b() y los envía por el puerto A con el comando output_a().
SIMULACION:
PROGRAMA:
//PROGRAMA
void main(void)
{
while(1)
{
numero = input_b();
output_a(numero);
}
}
EJERCICIO:
- Que la salida me muestre el doble del número ingresado.
- Que la salida me muestre la mitad del número ingresado.
- Que la salida me muestre el número ingresado mas 1.
SIMULACION:
19
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
PROGRAMA:
long tiempo=2500;
EJERCICIOS:
- Utilizar el comando output_high() y output_low() en lugar de output_bit()
- Que el temporizador se accione con flanco de subida (de 0 a 1)
SIMULACION:
U1 0
16 17
15
RA7/OSC1/CLKIN
RA6/OSC2/CLKOUT
RA0/AN0
RA1/AN1
18 0
1
4
RA5/MCLR
RA2/AN2/VREF
RA3/AN3/CMP1
2 0
3
RA4/T0CKI/CMP2
6
RB0/INT
7
RB1/RX/DT
8
RB2/TX/CK
9
RB3/CCP1
10 +88.8
RB4
11
RB5
12
RB6/T1OSO/T1CKI
13
RB7/T1OSI
PIC16F628A
PROGRAMA:
#include <16F628A.h>
#use delay(clock=4000000)
int retardo=10;
void main()
{
while(1)
{
while (input(PIN_A0))
{
output_b(0b00000001);
delay_ms(retardo);
output_b(0b00000010);
delay_ms(retardo);
output_b(0b00000100);
delay_ms(retardo);
output_b(0b00001000);
delay_ms(retardo);
}
20
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
while (input(PIN_A1))
{
output_b(0b00001000);
delay_ms(retardo);
output_b(0b00000100);
delay_ms(retardo);
output_b(0b00000010);
delay_ms(retardo);
output_b(0b00000001);
delay_ms(retardo);
}
}
}
EJERCICIOS:
- Cambiar el programa y la simulación para manejar un Motor PAP Bipolar
8. DISPLAY DE 7 SEGMENTOS
Los displays de 7 segmentos nos permiten mostrar información numérica y alfabética de forma muy eficaz,
con gran impacto visual y mucho más fácil de lo que puede parecer en un principio. Cada display de 7
segmentos está formado realmente por 8 leds, ya que además de cada una de las barritas que forman el
dígito numérico, hay un led adicional para el punto decimal. Cada segmento se suele nombrar con una
letra, según el siguiente diagrama:
En esta figura observamos que podemos encontrar dos configuraciones distintas de displays de 7
segmentos, que siendo idénticos externamente, son completamente distintos eléctricamente:
- Display de ánodo común: en este caso la parte común de los 8 leds es el ánodo, por lo que
habrá que alimentar el display de 7 segmentos con tensión positiva y encender cada segmento
tirando a masa su pin correspondiente.
- Display de cátodo común: en este caso la parte común de los 8 leds es el cátodo, por lo que
habrá que tirar a masa el punto común, y alimentar cada segmento con tensión por su pin
correspondiente.
SIMULACION:
21
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
PROGRAMA:
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
void main(void)
{
int i; //contador de visualizacion BETI
do{ //bucle...
for(i=0;i<15;i++)
{ //bucle visualizacion beti
output_a(0b00001110);
output_b(0b01111100); //1º 7seg on B
delay_ms(10);
output_a(0b00001101);
output_b(0b01111001); //2º 7seg on E
delay_ms(10);
output_a(0b00001011);
output_b(0b01111000); //3º 7seg on T
delay_ms(10);
output_a(0b00000111);
output_b(0b00110000); //4º 7seg on I
delay_ms(10);
}
output_b(0b00000000); //todo...
output_a(0b0000);
delay_ms(500); //...apagado durante 0,5s
}while(TRUE); //...infinito
}
EJERCICIOS:
- Cambiar el texto por “HOLA”
- Intercalar los ambos textos alternadamente.
22
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
9. Funciones
Las funciones son los bloques constructivos fundamentales en C. Todas las sentencias deben encontrarse
dentro de funciones. Las funciones deben ser definidas antes de ser utilizadas.
El tipo de dato devuelto se indica mediante tipo_dato. Si no se indica nada, se entiende que devuelve un
entero. Si no devuelve nada, debe incluirse una especificación tipo void.
La manera que tiene una función para devolver un valor es mediante la sentencia return.
La expresión debe proporcionar el mismo tipo de dato que el especificado en la función. Si no debe devolver
nada, se finaliza con return;
Cuando una función se encuentra con una sentencia return se vuelve a la rutina de llamada inmediatamente y
las sentencias posteriores a return no se ejecutan. Además de con las sentencia return, las funciones terminan
su ejecución y vuelven al lugar desde donde se les llamó cuando alcanzan la llave de cierre de función} tras
ejecutar la última sentencia de la misma.
Además de devolver valores, una función también puede recibir parámetros (denominados argumentos) según
se indicó en su definición.
Por ejemplo:
Los argumentos se pueden pasar a las funciones por valor o por referencia.
La llamada por valor copia el argumento de llamada en el parámetro formal de la función. No modifica su valor
en la función de partida. La llamada por referencia usa la dirección de la variable que se pasa a la función. Se
consigue usando punteros o arrays.
23
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
SIMULACION:
PROGRAMA:
EJERCICIOS:
- Crear una función para hallar el volumen de un cilindro
- Mostrar la salida en una pantalla LCD de 2x16 lineas
SIMULACION:
24
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
PROGRAMA:
#include <16f84a.h> //pic a utilizar
#use delay (clock=4000000) //Fosc=4Mhz
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001};
int conta,delay=5;
int h_digit,m_digit,l_digit;
int a,b;
void main(void)
{
conta=0;
while(1)
{
if(!input(PIN_A0))
{
++conta;
int2bcd(conta);
a=m_digit;
b=l_digit;
while(!input(PIN_A0))
{
vizu();
}
}
vizu();
}
}
void vizu(void)
{
output_b(tabBCD[a]| 0b11100000);
delay_ms(delay);
output_b(tabBCD[b]| 0b11010000);
delay_ms(delay);
}
EJERCICIOS:
- Cambiar para que cuente de 3 en 3
- Situar las funciones secundarias antes que la función principal
Muy utilizado para introducir información al microcontrolador. Los hay de varios tipos: de lámina flexible, de
efecto Hall, de efecto inductivo, de efecto capacitivo. Los más comunes son los de lámina flexible.
El problema de los rebotes. Debido al efecto muelle del pulsador, se producen oscilaciones en la señal tanto al
pulsar como al soltar la tecla.
25
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Teclados lineales
Muy sencillos, pero no permiten disponer de muchas teclas. De este modo, cuando el microcontrolador
detecte un “0” al final de la línea, se sabrá que se ha pulsado una tecla y, además, se sabrá cuál ha sido. Basta
con que el programa compruebe periódicamente el estado de las entradas a las que se ha conectado el
teclado.
Teclados matriciales
Varias teclas controladas con un número reducido de puertos E/S. La pulsación de una tecla se pone de
manifiesto en las entradas del microcontrolador conectadas al teclado.
En este ejemplo, se sabe que se ha pulsado una tecla de la tercera columna, pero no se sabe cuál. Se necesita
desarrollar algoritmos que permitan determinar cuál es la tecla que se ha pulsada.
26
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
El puerto B de los microcontroladores PIC está especialmente pensado para conectar un teclado matricial de
4x4 teclas.
SIMULACION:
+5v
U2
7 13
A QA
1 12
B QB
2 11
C QC
6 10
D QD
9
QE
3 15
LT QF
4 14
BI QG
5
LE/STB
4511
U1
16 17
OSC1/CLKIN RA0
15 18
OSC2/CLKOUT RA1
1
RA2
2
MCLR RA3
3
RA4/T0CKI
RB0/INT
6 R1 R2 R3 R4
7 220 220 220 220
RB1
8
RB2
9
RB3
10
RB4
11
RB5
12
RB6
RB7
13 D1 D2 D3 D4
LED-YELLOW
LED-YELLOW
LED-YELLOW
LED-YELLOW
PIC16F84A
1
A 1 2 3
B 4 5 6
C 7 8 9
D 0 #
PROGRAMA:
27
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
28
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
SIMULACION:
LCD1
LM016L
VDD
VSS
VEE
RW
RS
D0
D1
D2
D3
D4
D5
D6
D7
E
1
2
3
4
5
6
7
8
9
10
11
12
13
14
U1
30
RD7/PSP7
29
RD6/PSP6
28
RD5/PSP5
27
RD4/PSP4
22
RD3/PSP3
21
RD2/PSP2
20
RD1/PSP1
19
RD0/PSP0
26
RC7/RX/DT
25
RC6/TX/CK
1 24
MCLR/Vpp/THV RC5/SDO
23
RC4/SDI/SDA
10 18
RE2/AN7/CS RC3/SCK/SCL
9 17
RE1/AN6/WR RC2/CCP1
8 16
RE0/AN5/RD RC1/T1OSI/CCP2
15
RC0/T1OSO/T1CKI
7
RA5/AN4/SS/C2OUT
6 40
3
RA4/T0CKI/C1OUT RB7/PGD
5 39
RA3/AN3/VREF+ RB6/PGC
4
3
RA2/AN2/VREF-/CVREF
RA1/AN1
RB5
RB4
38
37
A 1 2 3
2 36
RA0/AN0 RB3/PGM
35
RB2
14
13
OSC2/CLKOUT
OSC1/CLKIN
RB1
RB0/INT
34
33
B 4 5 6
PIC16F877A
C 7 8 9
D 0 #
PROGRAMA:
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define use_portb_kbd TRUE
#include <lcd.c>
#include <kbd.c>
void main() {
char k;
lcd_init();
kbd_init();
port_b_pullups(TRUE);
lcd_putc("\fListo...\n");
while (TRUE)
{
k=kbd_getc();
if(k!=0)
if(k=='*')
lcd_putc('\f');
else
lcd_putc(k);
}
}
29
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
bit 7 RBPU
bit 6 INTEDG
bit 5 T0CS: Selección del reloj a utilizar
30
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
setup_timer_0 (modo);
modo:
RTCC_INTERNAL (OPTION_REG 00h)
RTCC_EXT_L_TO_H (OPTION_REG 20h)
RTCC_EXT_H_TO_L (OPTION_REG 30h)
RTCC_DIV_2 (OPTION_REG 00h)
RTCC_DIV_4 (OPTION_REG 01h)
RTCC_DIV_8 (OPTION_REG 02h)
RTCC_DIV_16 (OPTION_REG 03h)
RTCC_DIV_32 (OPTION_REG 04h)
RTCC_DIV_64 (OPTION_REG 05h)
RTCC_DIV_128 (OPTION_REG 06h)
RTCC_DIV_256 (OPTION_REG 07h)
Se pueden agrupar constantes de distintos grupos con |.
setup_wdt (modo);
modo:
WDT_18MS (OPTION_REG 08h)
WDT_36MS (OPTION_REG 09h)
WDT_72MS (OPTION_REG 0Ah)
WDT_144MS (OPTION_REG 0Bh)
WDT_288MS (OPTION_REG 0Ch)
WDT_576MS (OPTION_REG 0Dh)
WDT_1152MS (OPTION_REG 0Eh)
WDT_2304MS (OPTION_REG 0Fh)
rtcc:
prescaler:
31
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
set_timer0 (valor);
Valor: Entero de 8 bits. (TMR0 valor)
restart_wdt ();
No precisa ningún parámetro. (Equivale a CLRWDT)
Ejercicio10_ejemplo1:
//******************************************************************************
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#use standard_io(B)
#use standard_io(A)
//******************************************************************************
//Variables
//******************************************************************************
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001};
int a,b,c,d;
int min,seg;
32
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
int h_digit,m_digit,l_digit;
int delay=5,conta;
//******************************************************************************
//Funciones
//******************************************************************************
void vizu(void);
void int2bcd(int valor);
//******************************************************************************
//LLAMADA FUNCION INTERRUPCION
//******************************************************************************
#INT_TIMER0
void interrupcion()
{
++conta;
if(conta==250)
{
conta=0;
++seg;
if(seg==60)
{
++min;
seg=0;
if(min==60)
{
min=0;
}
}
}
}
/******************************************************************************/
/************************************************/
// Funcion que convierte de Entero a 3 x BCD
/************************************************/
void int2bcd(int valor)
{
h_digit = (int) valor / 100; // 1er Dígito o Centenas
valor -= h_digit * 100; // y se lo resto al valor
m_digit = (int) valor / 10; // 2do Dígito o Decenas
valor -= m_digit * 10; // y también se lo resto
l_digit = valor; // y por último solo me quedan las unidades
}
/******************************************************************************/
Ejercicio10_ejemplo2:
//******************************************************************************
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#use standard_io(A)
#use standard_io(B)
//******************************************************************************
//Variables
//******************************************************************************
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001};
int a,b,c,d;
int h_digit,m_digit,l_digit;
int delay=5,conta;
//******************************************************************************
//Funciones
//******************************************************************************
void vizu(void);
void int2bcd(int valor);
//******************************************************************************
///PROGRAMA
//******************************************************************************
void main(void)
{
setup_timer_0 (RTCC_EXT_H_TO_L );//configuracion interrupcion TMR0
setup_wdt (WDT_36MS );
set_timer0(0); //carga TMR0
disable_interrupts(INT_TIMER0);
disable_interrupts(GLOBAL); //activadas interrupciones
a=0,b=0,c=0,d=0;
while(1)
{
conta= get_timer0 ();
int2bcd(conta);
a=m_digit;
b=l_digit;
34
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
vizu();
}
}
/******************************************************************************/
void vizu(void)
{
output_b(tabBCD[a]| 0b11100000);
delay_ms(delay);
output_b(tabBCD[b]| 0b11010000);
delay_ms(delay);
output_b(tabBCD[c]| 0b10110000);
delay_ms(delay);
output_b(tabBCD[d]| 0b01110000);
delay_ms(delay);
}
/******************************************************************************/
/************************************************/
// Funcion que convierte de Entero a 3 x BCD
/************************************************/
void int2bcd(int valor)
{
h_digit = (int) valor / 100; // 1er Dígito o Centenas
valor -= h_digit * 100; // y se lo resto al valor
m_digit = (int) valor / 10; // 2do Dígito o Decenas
valor -= m_digit * 10; // y también se lo resto
l_digit = valor; // y por último solo me quedan las unidades
}
/******************************************************************************/
12. INTERRUPCIONES
Cuando se da un evento en un determinado módulo, el flag asociado se pone a 1 y, si las máscaras global (GIE)
están habilitadas, se acepta la interrupción.
El programador debe asegurarse de que el código se encarga de identificar la fuente de la interrupción,
guardar y recuperar el contexto existente antes de producirse la interrupción y poner a cero el flag asociado a
la misma para permitir posteriores identificaciones.
Estas tareas quedan enormemente simplificadas usando directivas y funciones del lenguaje C del compilador
de CCS.
La directiva #INT_DEFAULT
35
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Indica que la función que viene a continuación será llamada si se dispara una interrupción y ninguno de los
flags está activo.
La directiva #INT_GLOBAL
Indica que la función que va a continuación sustituye todas las acciones que inserta el compilador al aceptarse
una interrupción. Sólo se ejecuta lo que vaya en dicha función.
El compilador genera el código necesario para saltar a la función que va tras esta directiva en el momento de
la interrupción.
Indica que la función que viene a continuación será llamada si se dispara una interrupción y ninguno de los
flags está activo.
También genera código para salvar al principio y restituir al final el contexto, y borrará el flag que se activó con
la interrupción.
El programador debe seguir encargándose de habilitar las interrupciones.
enable_interrupts (nivel);
nivel es una constante definida en 16F84a.h y genera el código necesario para activar las máscaras necesarias.
Etiquetas de nivel definidas para el 16F84a:
GLOBAL
INT_RTCC
INT_RB
INT_EXT
INT_EEPROM
La mascara global (la que hace GIE=1) debe activarse de manera independiente. Las otras sólo activan la
máscara particular y el PEIE si es necesario.
disable_interrupts (nivel);
Hace la acción contraria a la función anterior, poniendo a 0 las máscaras relacionadas con la interrupción
indicada.
Existe también una función adicional destinada a configurar el flanco activo que genera la interrupción
externa (en RB0).
ext_int_edge (H_TO_L);
ext_int_edge (L_TO_H);
Selecciona flanco de subida para activar el flag INTF.
#INT_EXT
ext_isr() {
......}
/* Si entra una interrupción por flanco de bajada en RB0, se irá a la función que aparece tras la directiva
#INT_EXT */
Ejercicio11_ejemplo1:
Interrupción RB0:
//******************************************************************************
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#use standard_io(a)
#use standard_io(b)
//******************************************************************************
//VARIABLES GLOBALES
//******************************************************************************
int i=0; //contador para tabla BCD
int
tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001};//BCD 0-
9
//******************************************************************************
//LLAMADA FUNCION INTERRUPCION
//******************************************************************************
#INT_EXT
void IntRB0()
{
i++; //incremento contador indice tabBCD
if(i>9) //¿se ha mostrado digito 9?
i=0; //SI -> restaura valor indice(para mostrar digito 0)
output_a(tabBCD[ i ]); //muestra por porta digito 7 segmentos
}
//******************************************************************************
//PROGRAMA
//******************************************************************************
void main(void)
{
enable_interrupts(int_ext); //activar interrupcion externa
ext_int_edge(L_TO_H); //configuracion:interrupcion cuando señal esta en alta
enable_interrupts(GLOBAL); //todas las interrupciones desactivadas
while(1){}
}
//*******************************************************************************
37
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Ejercicio11_ejemplo2:
Interrupción RBI:
//******************************************************************************
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#use standard_io(a)
#use standard_io(b)
//******************************************************************************
//VARIABLES
//******************************************************************************
int i=0; //contador para tabla BCD
int
tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001};//BCD 0-
9
//******************************************************************************
//LLAMADA FUNCION INTERRUPCION
//******************************************************************************
#INT_RB
void IntPortB4_7( )
{
if(input(PIN_B7))
{
i++; //incremento contador indice tabBCD
if(i>9) //¿se ha mostrado digito 9?
i=0; //SI -> restaura valor indice(para mostrar digito 0)
output_a(tabBCD[ i ]); //muestra por porta digito 7 segmentos
}
/*if(!input(PIN_B7))
{
i++; //incremento contador indice tabBCD
if(i>9) //¿se ha mostrado digito 9?
i=0; //SI -> restaura valor indice(para mostrar digito 0)
output_a(tabBCD[ i ]); //muestra por porta digito 7 segmentos
}*/
}
//******************************************************************************
//PROGRAMA
//******************************************************************************
void main(void)
{
enable_interrupts(INT_RB); //activar interrupcion rb4:7
enable_interrupts(GLOBAL); //activar interrupciones
while(1){}
}
/******************************************************************************/
38
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Una manera de conectara dos dipositivos es mediante comunicaciones serie asíncronas. En ellas los bits de
datos se transmiten "en serie" (uno de trás de otro) y cada dispositivo realiza tiene su propio reloj.
Previamente se ha acordado que ambos dispositivos transmitirán datos a la misma velocidad.
En este cuaderno técnico se muestran los fundamentos de estas comunicaciones, los pines empleados y
ejemplos de circuitos para conectar el PC con un microcontrolador, además de mostrar los cables que se
pueden emplear.
Primero se envía un bit de start, a continuación los bits de datos (primero el bit de mayor peso) y finalmente
los bits de STOP.
El número de bits de datos y de bits de Stop es uno de los parámetros configurables, así como el criterio de
paridad par o impar para la detección de errores. Normalmente, las comunicaciones serie tienen los
siguientes parámetros: 1 bit de Start, 8 bits de Datos, 1 bit de Stop y sin paridad.
En esta figura se puede ver un ejemplo de la transmisión del dato binario 10011010. La línea en reposo está a
nivel alto:
Norma RS232
La Norma RS-232 fue definida para conectar un ordenador a un modem. Además de transmitirse los datos de
una forma serie asíncrona son necesarias una serie de señales adicionales, que se definen en la norma. Las
tensiones empleadas están comprendidas entre +15/-15 voltios.
Para conectar el PC a un microcontrolador por el puerto serie se utilizan las señales Tx, Rx y GND. El PC utiliza
la norma RS232, por lo que los niveles de tensión de los pines entán comprendidos entre +15 y -15 voltios. Los
microcontroladores normalmente trabajan con niveles TTL (0-5v). Es necesario por tanto intercalar un circuito
que adapte los niveles:
39
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
En los PCs hay conectores DB9 macho, de 9 pines, por el que se conectan los dispositivos al puerto serie. Los
conectores hembra que se enchufan tienen una colocación de pines diferente, de manera que se conectan el
pin 1 del macho con el pin 1 del hembra, el pin2 con el 2, etc...
Este chip permite adaptar los niveles RS232 y TTL, permitendo conectar un PC con un microcontrolador. Sólo
es necesario este chip y 4 condensadores electrolíticos de 22 micro-faradios. El esquema es el siguiente:
40
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Ejercicio12_ejemplo1:
Transmisión:
/******************************************************************************/
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#use rs232(baud=9600, xmit=PIN_A0, rcv=PIN_A1, bits=8)
#use standard_io(A)
#use fast_io(B)
//******************************************************************************
//VARIABLES
//******************************************************************************
char codigo;
//******************************************************************************
//FUNCIONES
//******************************************************************************
char explorar_teclado();
//******************************************************************************
///PROGRAMA
//******************************************************************************
41
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
void main(void)
{
set_tris_b(0xf0);
output_b(0);
output_a(0);
codigo=0;
port_b_pullups (true);
printf("TECLADO: "); //mensaje por v.terminal
while(true) // bucle de trabajo
{
codigo=explorar_teclado(); // explora si se presiona pulsador en teclado y lo muestra
en el puerto A
if(codigo != 15)
{
printf("\b" ); //retrocede una posicion(borra ultima tecla)
printf("%c",codigo); //mensaje por v.terminal
}
}
}
/******************************************************************************/
char explorar_teclado() // función que explora todo el teclado
{
output_b(0xfe); // verifica columna 1
if(input(PIN_B4)==0)
return '1';
if(input(PIN_B5)==0)
return '2';
if(input(PIN_B6)==0)
return '3';
if(input(PIN_B7)==0)
return 'C';
if(input_b()==0xf7)
return 15;
}
/******************************************************************************/
42
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Ejercicio12_ejemplo2:
Recepcion:
/******************************************************************************/
#include <16f84a.h> //pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_lcd TRUE //definir portb lcd
#include <lcd.c> //libreria manejo lcd
#use rs232(baud=9600, xmit=PIN_A0, rcv=PIN_A1, bits=8)
//******************************************************************************
//VARIABLES
//******************************************************************************
char codigo;
//******************************************************************************
///PROGRAMA
//******************************************************************************
void main(void)
{
lcd_init(); //inicializa lcd
while(1)
{
codigo=getc();
lcd_putc(codigo);
}
}
//******************************************************************************
43
Labelin Electronics EIRL PICS EN LENGUAJE C – GUIA RAPIDA E.M.P.
Este manual es de uso exclusivo para los cursos dictados por LABELIN ELECTRONICS EIRL.
Prohibida la Reproducción Total o Parcial.
44