Está en la página 1de 116

Curso Bsico de Lenguaje C Para

Microcontroladores Pic

Instructor :
Julio Marturet
Cel: 0412 179 5067

Compilador CCS

Winpic800

Caractersticas
Velocidad de operacin: Hasta 20 MHz de reloj
8K x 14 bits por palabra de memoria de programa
FLASH.
368 x 8 bytes de memoria de datos (RAM).
256 x 8 bytes de memoria de datos EEPROM.
14 fuentes de interrupciones

Caractersticas
Memoria de pila (stack) de 8 niveles de profundidad
Protecciones:
Power-on Reset (POR)
Power-up Timer (PWRT)
Oscillator Start-up Timer (OST)
Watchdog Timer (WDT) independiente del cristal

Caractersticas de
Perifricos
Timer 0: timer/counter de 8 bits con un pre-escalador de 8 valores.
Timer 1: 16-bit timer/counter con pre-escalador.
Timer 2: 8-bit timer/counter con registro de estado de 8-bit, preescalador y post-escalador.
Dos mdulos de Capture, Compare, PWM:
Capture es de 16-bit, max. resolucin es 12.5 ns.
Compare es de 16-bit, max. resolucin es 200 ns.
PWM max. resolucin de 10-bit.

Caractersticas de
Perifricos
Convertidor analgico a digital de 10-bit multi-canal.
Puerto serial sncrono (SSP) con SPI. (modo maestro) e
I2C (maestro/esclavo).
Transmisor-Receptor sncrono-asncrono universal
(USART/SCI) con 9-bit.
Puerto paralelo esclavo (PSP) con 8-bits de ancho, con
terminales de control RD, WR y CS.

Arquitectura Interna
Arquitectura HARVARD.
Buses separados (datos e instrucciones).
Memoria de programa : 14 bits.
Memoria de datos: 8 bits.
Recursos mapeados en memoria de datos.

Arquitectura Interna

Terminales Fsicas

Estructura de un
Programa en C
# Directivas del Preprocesador
// Declaracin del Prototipo de Funciones
// Declaracin de Variables Globales
// Definicin de Constantes
// Programa Principal (main)
main(){
Variables Locales;
Bloque de sentencias;
}

Directivas del
Preprocesador
#include <16f877.h>
Esta directiva nos permite cargar un archivo.h el cual contiene las
definiciones del microcontrolador a utilizar. En nuestro caso el pic 16f877.
#fuses opciones
Esta directiva define qu fusibles deben activarse en el dispositivo cuando
se programe. Esta directiva no afecta a la compilacin; sin embargo, esta
informacin es sumamente importante a la hora de quemar el pic.
Opciones que se pueden activar en el pic 16f877:
Tipo de Oscilador:
LP Low power osc < 200 khz.
XT Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD.
HS High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD).
RC Resistor/Capacitor Osc with CLKOUT.

Directivas del
Preprocesador
Wach Dog Timer (WDT):
NOWDT No Watch Dog Timer
WDT Watch Dog Timer
Power Up Timer (Retardo de encendido):
NOPUT No Power Up Timer
PUT Power Up Timer
Proteccin de Cdigo:
PROTECT Codigo protegido contra lectura
NOPROTECT Codigo no para lectura
Brown Out Reset:
NOBROWNOUT No brownout reset
BROWNOUT Reset when brownout detected
Programacin por bajo Voltaje:
NOLVP No low voltage programing
LVP Low Voltage Programming

Directivas del
Preprocesador
Proteccin de Cdigo EEPROM:
NOCPD No EE protection
CPD
Data EEPROM Code Protected
Proteccin de Memoria de Programa:
WRT_5% Lower 255 bytes of Program Memory is Write Protected
WRT_25% Lower quarter of Program Memory is Write Protected
WRT_50% Lower half of Program Memory is Write Protected
NOWRT Program memory not write protected
Modo de Depurador utilizando ICD:
NODEBUG No Debug mode for ICD
DEBUG Debug mode for use with ICD
Ejemplo:
#fuses XT,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP

Directivas del
Preprocesador
#use delay (clock=frecuencia)
Esta directiva indica al compilador la frecuencia del procesador, en ciclos por segundo,
a la vez que habilita el uso de las funciones delay_ms() y delay_us().
Ejemplo: #use delay (clock=4000000) // Definimos un cristal de 4MHz.
#use fast_io (puerto)
Esta directiva es una opcin que da el compilador y lo que hace es poner como salida
o como entrada un pin del puerto sin que se deba usar por programa el registro tris ya
que esto ocupa memoria de programa. El usuario debe asegurarse de que los registros
TRIS estn configurados adecuadamente antes de operar con los puertos. El puerto
puede ser A-G.
Ejemplo: #use fast_io(A)
#use standard_io (puerto)
Cada vez que se emplea una funcin output...() se inserta cdigo previo para forzar a
que el bit particular o el puerto completo sean de salida (mediante la carga del TRIS
correspondiente). Si se trata de una funcin input...() se carga cdigo para definir bit o
puerto completo como de entrada. sta es la opcin activa por defecto y usa mas
memoria que el fast_io. El puerto puede ser A-G.
Ejemplo: #use standard_io(A)
Estas son algunas de la muchas directivas del preprocesador, ojo no son todas, hay
muchas ms, pero estas son algunas de las mas importantes.

Operadores y
Expresiones
El lenguaje C de pic c dispone de una gran cantidad de
operadores empleados en la operacin de datos dentro de
un programa, su clasificacin es la siguiente: Aritmticos,
Relacionales, de asignacin, Lgicos, de Manejo de un solo
bit, de manejo de punteros, entre otros. Pero lo importante
no es saber a qu grupo pertenece cada operador, sino en
conocer la operacin que se puede realizar con cada uno de
ellos. Vamos a ver los operadores que nos permite utilizar
nuestro compilador CCS.

Operadores Aritmticos
(Operaciones Matemticas)

Operadores Relacionales
(Sentencias Condicionales)

Operadores de Asignacin
(Asignacin de Valores)

Operadores Lgicos y de
Manejo de Punteros
Operadores Lgicos

Manejo de Punteros

Operadores de Manejo
de Bits

Tipos de Variables

Declaracin de Variables
Variables Globales: Las variables de tipo global son aquellas que se
definen fuera de la funcin main (funcin principal) y de cualquier
otra funcin, la caracterstica de este tipo de variables es que pueden
ser llamadas desde cualquier punto del programa ya sea en la funcin
principal o en otras.
Variables Locales: Las variables de tipo local son las que se definen
dentro de una funcin especfica y su caracterstica es que solo
pueden ser utilizadas dentro de esa funcin, lo que permite que
puedan existir variables en distintas funciones con el mismo nombre.

Definicin de Variables
Las variables: Es el nombre que le damos

a una o varias

posiciones de memoria de la RAM de nuestro PIC en donde se


almacenan datos

y se realiza para llamar dichos datos por

nombres en el programa.
Ejemplos:
int i = 10; //la variable i es de 8 bits y vale 10
int j = -10; //la variable j es de 8 bits y vale -10
int p = 0; //la variable p es de 1bit y vale 0
Char c =a; //la variable c es un carcter y tendr un valor de 8
bits segn la tabla ascci.

Tabla de Cdigo ASCCI

Directivas que Permiten


Utilizar Variables
#bit identificador = x.y
Esta directiva crear un identificador "id" que puede utilizarse como cualquier short,
int (entero corto; de un bit). El identificador har referencia a un objeto en la
posicin de memoria x ms el bit de desplazamiento y.
Ejemplos:
#bit Led = PORTB.0 // Bit asignado a identificador Led
#bit ON = PORTB.1 // Bit asignado a identificador ON
#bit OFF = PORTB.2 // Bit asignado a identificador OFF
#byte identificador = x
Esta directiva crear un identificador id que puede utilizarse como cualquier INT
(un byte). El identificador
har referencia a un objeto en la posicin de memoria x, donde x puede ser una
constante u otro identificador. Si x es otro identificador, entonces ste estar
localizado en la misma direccin que el identificador id.
Ejemplos:
#byte PORTB=0x06 // Direccin del PortB
#byte TRISB=0x86
// Direccin del TrisB

Entrada Salida
Si deseamos configurar el puerto C con la siguiente asignacin:
RC0
RC1
RC2
RC3
RC4
RC5
RC6
RC7

entrada
entrada
entrada
entrada
salida
salida
salida
salida

Posibles instrucciones a utilizar


set_tris_b(0b00001111);
set_tris_b(0x0F);
set_tris_b(15);

//forma binaria
//forma hexadecimal
//forma decimal

Manejo de Entradas y
Salidas
Para el Manejo de un Bit:
Input(pin)
//Retorna el valor 0 1 del pin indicado.
Ejemplo: input( PIN_A0);
Output_bit(pin,valor) //Colocar el pin indicado a 0 1.
Ejemplo: output_bit(PIN_D1,1);
Output_high(pin) // Colocar el pin a estado alto 1.
Ejemplo: output_high(PIN_D0);
Output_low(pin) //Colocar el pin a estado bajo 0.
Ejemplo: output_low(PIN_D1);
Para el Manejo de un Byte:
input_x() // introduce el valor de un puerto x puede ser (A, B,...).
Ejemplo: input_b();
output_x(valor)// enviar valor por el puerto x, que puede(A, B,....).
Ejemplo: output_b();

Manipulacin de Bits y
de Bytes
Para el manejo de un Bit:
bit_clear(var,bit) // Borra el dgito especificado de la variable.
bit_set(var,bit) // Pone a uno el digito especificado de la variable.
bit_test(var,bit) // Retorna el valor del bit de la variable indicada.
Para el manejo de un Byte:
rotate_left (address,byte) //Rotar a la izquierda un bit de un array o una estructura. El
Bit Mas Significativo (MSB) pasa a ser el Bit Menos Significativo (LSB).
rotate_right (address,byte) // Rotar a la derecha un bit de un array o una estructura. El
bit LSB pasa a ser el MSB.
shift_left (addres,byte,value) // Desplaza hacia la izquierda un bit de un array o una
estructura. A diferencia de rotate aqu debemos especificar el valor (value) con el que
queremos que rellene los huecos desplazados y byte indica el nmero de bytes
implicados.
shift_right (addres,byte,value) // Desplaza hacia la derecha un bit de un array o una
estructura.
swap (value) // Intercambia el nible bajo con el nible alto del byte dado. No retorna
el resultado, lo deja en value.

Retardos por Software


delay_cycles (count) Realiza retardos de ciclos de instruccin segn el valor
indicado en count (1..255). Un ciclo de instruccin es igual a cuatro perodos de
reloj.
Ejemplo: delay_cycles(255); //retardo de 255 ciclos de maquina.
delay_us (time) Realiza retardos del valor especificado en microsegundos
(1..65535). Esta funcin no utiliza los timers internos pero es preciso utilizar la
directiva #use delay especificando la frecuencia del reloj.
Ejemplo: delay_us(1000) //retardo de 1000 microsegundos igual a 1 milisegundo
delay_ms (time) Realiza retardos especificando el valor en milisegundos
(1..65535). Esta funcin no utiliza los timers internos pero es preciso utilizar la
directiva #use delay especificando la frecuencia del reloj.
Ejemplo: delay_ms(1000) //retardo de 1000 milisegundos igual a 1 segundo

Bucle While()

Bucle For()

Bucle do-While()

Sentencia if()

Sentencia if-elfe

Sentencia Switch

AHORA SI, A PROGRAMAR

Encendido de LED
Crear un programa que encienda y apague un led,
ubicado en la terminal RB0 del puerto B.
El tiempo de encendido es de 1000 milisegundo y el
de apagado de 300 milisegundos.

Encendido de LED
(Algoritmo)
1. Configurar el bit 0 del puerto B como salida de datos.
2. Encendido del led.
3. Retardo por software de 1000 milisegundos.
4. Apagado del led.
5. Retardo por software de 300 milisegundos.
6. Repetir el paso 2.

Encendido de LED
(Diagrama de Flujo)
Led
Configura bit del
puerto como salida

Apaga bit

Enciende bit

Retardo de 300 ms

Retardo de 1000ms

Encendido de LED
(Esquemtico)

Encendido de LED
(Programa)
#include <16F877.h>

// PIC a utilizar
#FUSES XT
// Se define que se usa como oscilador para el pic un cristal
#FUSES NOWDT
// se define que no se usa el perro Guardin
#FUSES NOPUT
//se define que no se espera que se estabilice la tensin
#FUSES NOPROTECT // No protecccion de codigo para lectura
#FUSES NOLVP
// No programacin por bajo voltaje
#use delay(clock=4000000) // Oscilador a 4MHz
#byte PORTB=0x06
// Direccin del PortB
#bit led = PORTB.0
//Variable Global
// FUNCION PRINCIPAL
void main(void){
set_tris_b(0x00);
// Definimos el puerto b como salida
portb = 0x00;
// Limpiamos Puerto B
while(TRUE){
// Bucle infinito
led = 1;
// Se enciende el led
delay_ms(1000); //retardo de 1 segundo
led = 0;
//Se apaga el led
delay_ms(300); //retardo de 300 mili segundos
}
}

Encendido de LED
(Programa II)
#include <16F877A.h>
// PIC a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP //fuses
#use delay(clock=4000000) // se fija el oscilador externo
#byte PORTB=0x06
// Direccin del PortB
// FUNCION PRINCIPAL
void main(void){
set_tris_b(0x00); // Definimos el puerto b como salida
portb = 0x00;
// Limpiamos Puerto B
while(TRUE){
// Bucle infinito
output_high(PIN_B0);
delay_ms(1000);
output_low(PIN_B0);
delay_ms(300);
}
}

Tareas: parte I
1. Disear un programa que encienda un led en el pin RD6 durante 2

seg y lo apague durante 0.5 seg.


2. Disear un programa que encienda y apague un led en el pin RB7
durante 1 seg con las instrucciones,
bit_set(var,bit)
y
bit_clear(var,bit).
3. Disear un programa que encienda durante 2seg, 8 leds ubicados en
el puerto b y luego los apague durante 1 segundo pero todos deben
encender y apagar al mismo tiempo.
Nota: debe realizar como mnimo 2 de los 3 diseos. Los mismos deben de estar comentados en cada
lnea.

MANEJO DE PUERTOS

Manejo de las Funciones


input(pin) e input_x()
Input(pin): Esta instruccin lee el estado
0 o 1 del pin indicado. El valor de retorno
es un entero corto.
Input_x(): Esta instruccin lee un puerto
completo por ejemplo: input_a();

Funcin input (pin)


(Esquemtico)

Ejemplo de input (pin)


(Programa)
#include <16F877.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP
#use delay(clock=4000000)
#byte PORTB=0x06
int control;
//Se define una variable global
// FUNCIN PRINCIPAL
void main(){
set_tris_b(0x00);
portb = 0x00;
// Limpiamos Puerto B
While(TRUE){
// Bucle infinito
control = input(PIN_A0); //se almacena el valor ledo en la variable control
if(control==1)
//si control es 1 encender el led
{
output_high(PIN_B0);
}
else
//sino apagar el led
{
output_low(PIN_B0);
}
}
}

Funcin input_x()
(Esquemtico)

Ejemplo de input_x()
(Programa)
#include <16F877.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP
#use delay(clock=4000000)
#byte PORTB=0x06
#byte PORTD=0x08
int control;
//Se define una variable global
// FUNCIN PRINCIPAL
void main(){
set_tris_b(0xff);
set_tris_d(0x00);
portb = 0x00;
// Limpiamos Puerto B
portd = 0x00;
// Limpiamos Puerto D
While(TRUE){
// Bucle infinito
control = input_b();//se almacena el valor ledo en la variable control
if(control==0xff) //si control es 1 encender el led
{
output_high(PIN_D0);
}
if(control==0x00)
//sino apagar el led
{
output_low(PIN_D0);

}
}
}

Manejo de los timers del PIC.


Timer0, Timer1 y Timer2

TIMER0
El TIMER0 es un contador de 8 bits, incrementado por hardware y programable. La cuenta mxima
es 255(el incremento es constante e independiente). La frecuencia de conteo es una 4 parte de la
frecuencia del reloj (fosc/4).
El timer0 se puede emplear de 2 formas distintas:
Contador: cuenta eventos externos a travs del Pin RA4/TOCK1.
Temporizador: cuenta los pulsos internos del reloj.
Al TIMER0 se le puede agregar un prescaler, es decir, un divisor de frecuencia programable que
puede dividir por 2, 4, 8, 16, 32, 64, 128, 256.
Tiempo de desbordamiento del TIMER0 se calcula con la siguiente ecuacin:
T = (4/Fosc) * Prescaler * (256- Valor del TMR0).
Ejemplo: se desea realizar un retardo de 40mseg. Que valor del timer0 se debe cargar en la
programacin?
Valor del TMR0 = (-(Fosc * T / 4 * Prescaler) + 256)
Valor del TMR0 = (-(4Mhz * 40mseg/ (4 *256) ) + 256)
Valor del TMR0 = 99.75 = 100

TIMER0
Instrucciones del TIMER0 en C:
setup_timer_0 (modo);
Este funcin inicializa el timer0 en un modo determinado. Dichos modos
se encuentran definidos en el archivo 16f877.h.
Ejemplo: setup_timer_0(RTCC_EXT_H_TO_L|RTCC_DIV_1);//
//tmr0 con base de tiempo externa y Frecuencia interna /1.
Set_timer0(valor); //valor es un entero de 8 bits.
Ejemplo: set_timer0(255);//cargar el timer0 con 255 !mximo valor posible!
valor = get_timer0(); //guarda en un entero de 8 bits el valor del
Timer0.

TIMER1
El timer1 es otro temporizador y contador pero de 16 bits. Es decir, cuenta hasta 65536. Al TIMER1
tiene un prescaler, divisor de frecuencia programable que puede dividir por 1, 2, 4, 8.
El timer1 se puede emplear de 3 formas distintas:
Temporizador: cuenta los pulsos internos del reloj.
Contador asncrono: como contador de pulsos externos.
Contador sncrono: para la generar de un disparo especial en el modulo ccp.
Tiempo de desbordamiento del TIMER1 se calcula con la siguiente ecuacin:
T = (4/Fosc) * Prescaler * (65536- Valor del TMR1).
Ejemplo: se desea realizar un retardo de 40mseg. Que valor del timer1 se debe cargar en la
programacin?
Valor del TMR1 = (-(Fosc * T / 4 * Prescaler) + 65536)
Valor del TMR1 = (-(4Mhz * 40mseg/ 4 *8) + 65536)
Valor del TMR1 = 60536

TIMER1
Instrucciones del TIMER1 en C:
setup_timer_1 (modo);
Este funcin inicializa el timer1 en un modo determinado. Dichos modos
se encuentran definidos en el archivo 16f877.h.
Ejemplo: setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);//
//timer1 con base de tiempo interna y prescaler de 8.
Set_timer1(valor); //valor es un entero de 16 bits.
Ejemplo: set_timer1(65536);//cargado con el mximo valor posible.
valor = get_timer1(); //guarda en un entero de 16 bits el valor del
Timer1.

TIMER2
El timer2 Es un temporizador especial y posee las siguientes caractersticas:
Temporizacin: de 8 bits
Prescaler : programable por programa y puede ser de 1, 4, 16.
Postcaler: programable por programa y puede ser un valor del 1 al 16.
El timer2 es utilizado por el modulo ssp para generar la seal de reloj, adems es
empleado como base de tiempos para la modulacin por ancho de pulso (PWM).
Tiempo de desbordamiento del TIMER2 se calcula con la siguiente ecuacin:
Tiempo = (4/Fosc) *[ Prescaler * (Valor del PR2 + 1) * Postcaler]
Ejemplo: se desea realizar un retardo de 40mseg. Que valor del timer2 se debe cargar
en la programacin?
Valor del PR2 = ((Tiempo * Fosc )/ (4 * Prescaler * Postcaler) )-1
Valor del PR2 = ((40mseg * 4Mhz) /( 4 *16 * 16) ) -1
Valor del PR2 = 155.25 = 155

TIMER2
Instrucciones del TIMER1 en C:
setup_timer_2(modo, periodo, postcaler);
Este funcin inicializa el timer2 en un modo determinado. Dichos modos se
encuentran definidos en el archivo 16f877.h. En modo se fija el prescaler, periodo
es el valor del timer2 y postcaler puede valer de 0 a 16 como ya se mencion.
Ejemplo: setup_timer_2(T1_DIV_BY_1, 255,16);//timer2 con prescaler de 1,valor del
PR2 es 255 y postcaler de 16. Esto generara un tiempo de 4.096mseg con cristal de
4Mhz.
Set_timer2(valor); //valor es un entero de 8 bits.
Ejemplo: set_timer1(255);//cargado con el mximo valor posible.
valor = get_timer2(); //guarda en un entero de 8 bits el valor del Timer2.

Contador (Esquemtico)

Contador (Programa)
#include <16F877.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay(clock=4000000)
int control;
#bit c1 = control.1
void main()
{
//Timer cero como base de tiempo externa y divisor de frecuencia 1
setup_timer_0 (RTCC_EXT_L_TO_H|RTCC_DIV_1);
c1 = 1;
//variable que nos permitir detectar si esta encendido o apagado el led
output_high(pin_B0);
//encendemos el led
set_timer0(0);
while(1)
{
if(get_timer0()==5)
//si se ha pulsado 5 veces
{
if(c1==1)
//si el led esta encendido?
{
output_low(pin_B0);
//apagar el led
c1 = 0;
//indicar que el led esta apagado
}
else
//si el led esta apagado?
{
output_high(pin_B0); //encender el led
c1 = 1;
//indicar que el led esta encendido
}
set_timer0(0);
//reiniciar el conteo del timer0
}
}
}

Temporizador (Esquemtico)

Temporizador (Programa)
//ESTE PROGRAMA GENERA UNA SEAL DE 1KHZ EN EL PIN RB0
//la ecuacion empleada es la del tmr0
#include <16f877.h>
#fuses xt,nolvp,noprotect,nowdt
#use delay(clock=4000000)
#int_TIMER0
//atiende la interrupcin del timer0
void TIMER0_isr(void){
output_toggle(PIN_B0);
//colocar al pin B0 a conmutar
set_timer0(0x6);
//se carga un calor de 6 en el tmr0 este valor fue calculado
}
void main(){
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);//configuracin del tmro como temporizador
set_timer0(0x6);
//se carga un valor de 6 al timer0
enable_interrupts(global);
//habilita las interrupciones globales
enable_interrupts(INT_TIMER0); //habilita la interrupcin del timer0
while(1);
//importante para que el programa siempre este repitindose.
}

Tareas: Parte II
4. Disear un programa que encienda un led en el pin RD4 cuando el
valor de entrada en el puerto b sea mayor a 7.
5. Disear un programa que mantenga un led encendido en el pin RD7 y
si se pulsa un botn en el pin RB0 se apague el led. Conecte el botn de
modo que siempre llegue un nivel alto en B0.
6. Disear un programa que genera una seal cuadrada de 2khz
empleando el timer 0.
Nota: debe realizar como mnimo 2 de los 3 diseos. Los mismos deben de estar comentados en cada
lnea.

MANEJO DE DISPLAY 7
SEGMENTOS

Manejo del Display


7 Segmentos
Es

un

conjunto

de

leds

conectados

posicionados

apropiadamente. Cada segmento esta designado con una letra.


Existen 2 tipos de display 7 segmentos los nodo comn y los
ctodo comn.
La figura muestra el orden
de los 7 segmentos en el
Display y la representacin
real del encapsulado.

Manejo del Display


7 Segmentos
Un display lo empleamos para mostrar un numero del 0 al 9.
En la electrnica moderna, mostrar caracteres alfanumricos es una
exigencia muy corriente, los relojes digitales, las calculadoras de
bolsillo, los multmetros digitales y los medidores de frecuencias
son todos ellos ejemplos de dispositivos que utilizan tales tipos de
display.
Pero, Como podemos controlar un display con un PIC?

Manejo del Display


7 Segmentos

Manejo del Display


7 Segmentos (Esquemtico)

Manejo del Display


7 Segmentos (Programa I)
#include <16F877.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP
#use delay(clock=4000000)
#byte PORTB=0x06
// FUNCIN PRINCIPAL
void main(void){
set_tris_b(0x00);
// Definimos el Puerto B como salida
portb = 0x00;
// Limpiamos Puerto B
While(TRUE){
// Bucle infinito
portb = 0b00111111;
// Digito 0
delay_ms(1000);
// Espero 1s.
portb = 0b00000110;
// Digito 1
delay_ms(1000);
// Espero 1s.
portb = 0b01011011;
// Digito 2
delay_ms(1000);
// Espero 1s.
portb = 0b01001111; // Digito 3
delay_ms(1000);
// Espero 1s.
portb = 0b01100110;
// Digito 4
delay_ms(1000);
// Espero 1s.
portb = 0b01101101;
// Digito 5
delay_ms(1000);
// Espero 1s.
portb = 0b01111101;
// Digito 6
delay_ms(1000);
// Espero 1s.
portb = 0b00000111;
// Digito 7
delay_ms(1000);
// Espero 1s.
portb = 0b01111111;
// Digito 8
delay_ms(1000);
// Espero 1s.
portb = 0b01100111;
// Digito 9
delay_ms(1000);
// Espero 1s.
}
}

Arreglos
(Definiciones)
#define
int

MAX 50
vector_one[10];

//arreglo de 10 enteros

Se define un arreglo de 10 valores en hexadecimal para ser mostrado en el


display
int tab7seg[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67};
Se define un arreglo de 10 valores en decimal para ser mostrado en el display
int Tab7Seg[10]={63,6,91,79,102,109,125,7,127,111};
Se forma se define un arreglo de 10 caracteres para ser mostrado en una lcd
Char tabNum[10]={'0' ,'1','2','3','4','5','6','7','8','9'};
unsigned peso[7];
unsigned short d[3];

Ejemplo de Manejo de Display


(Programa II)
#include <16f877.h>
//pic a utilizar
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP //ordenes para el programador
#use delay (clock=4000000)
//Fosc=4Mhz
#use standard_io(B)
///PROGRAMA PRINCIPAL
void main(void)
{
char i=0;
//contador para tabla 7 seg
int tab7seg[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67}; //7seg hex 0-9
do{
output_b(tab7seg[ i ]);
delay_ms(500);
i++;
if(i>9)
{
i=0;
}
}While(TRUE);
}

//bucle...
//muestra por portb digito 7 segmentos
//incremento contador para visualizar siguiente digito
//ya se ha mostrado el digito 9?
//SI -> vuelve a empezar(digito 0)
//...infinito

MANEJO DE PANTALLA LCD


2X16

Manejo de Pantalla
LCD 2x16
Es una pantalla de cristal lquido con una matriz de 2 filas por 16 columnas. contando adems
con un microcontrolador (generalmente el Hitachi HD44780) que lo gobierna el cual posee una
interfaz de 8 o 4 bits, con 3 seales de control. Su bus de conexin puede ser de 4 u 8 bits.

Manejar la Pantalla
LCD 2x16
Manejar la librera LCD.c de Pic C:
Esta librera posee 4 funciones que se pueden llamar desde la programacin y son las
siguientes:
lcd_init ();
Esta funcin debe llamarse antes que ninguna otra funcin del fichero lcd.c. Debido a
que esta inicializa la pantalla.
Como se puede observar el fichero LCD.c, esta instruccin adems de borrar el display,
configura el LCD para trabajar de la siguiente manera:
En formato de 4 bits, con dos lneas y con caracteres de 58 puntos.
Con display encendido, cursor apagado y sin parpadeo.
Con autoincremento del puntero de direcciones y sin desplazamiento del display real.
lcd_gotoxy (x , y);
Esta funcin nos permite escoger la posicin del LCD en la que se desea escribir un dato
La x son las columnas por lo que este valor puede variar desde 1 a 16
La y son las filas por lo que este valor puede variar entre 1 primera fila y 2 segunda fila

Manejar la Pantalla
LCD 2x16
lcd_putc (dato);
Escribe dato en la posicin 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 lnea
\b Retrocede una posicin
lcd_getc (x , y);
Devuelve el carcter que ocupa la posicin (x , y) del LCD.
Por defecto, este driver usa siete bits del puerto D para establecer a comunicacin
entre el LCD y el
Microcontrolador.
D0 Enable
D1 RS
D2 R/W
D3 D4 Bit de datos D4
D5 Bit de datos D5
D6 Bit de datos D6
D7 Bit de datos D7

Manejo de Pantalla
LCD 2x16
Funcin printf(lcd_putc,string,vars);
String: Cadena de caracteres que puede formarse usando el contenido de una o ms
variables.
vars: Variables incluidas en la cadena (separadas por comas).
La funcin de impresin formateada PRINTF saca una cadena de caracteres al
estndar serie RS-232 o a una funcin especificada. El formato est relacionado con
el argumento que ponemos dentro de la cadena (string).
Cuando se usan variables, string debe ser una constante. El carcter % se pone dentro
de string para indicar un valor variable, seguido de uno o ms caracteres que dan
formato al tipo de informacin a representar.
Si ponemos %% obtenemos a la salida un solo %. El formato tiene la forma genrica
%wt, donde w es optativo y puede ser 1,2,...,9. Esto es para especificar cuntos
carcteres son representados; si elegimos el formato 01,...,09 indicamos ceros a la
izquierda, o tambin 1.1 a 9.9 para representacin en punto flotante.

Manejo de Pantalla
LCD 2x16
t es el tipo de formato y puede ser uno de los siguientes:

Manejo de Pantalla LCD


2x16 (Esquemtico)

Manejo de Pantalla
LCD 2x16 (Programa)
#include <16F877.h>
/// libreria para el manejo del pic16f877
#use delay(clock=4000000)
// declara la frecuencia del cristal
#FUSES XT,PUT,nolvp
#include <lcd.c>
// Librera para el manejo del
#define use_portd_lcd TRUE
#byte portd= 0x08
char letra;
//definimos una variable de tipo caracter
void main(void)
{
lcd_init(); // Antes de usar el lcd,hay que inicializarlo
lcd_gotoxy(1,2);
//
lcd_putc("Curso de Picc"); // Escribes en la lcd
letra=lcd_getc(1,2);
//almaceno la letra C en la variable letra
lcd_gotoxy(1,1);
//eligo la posicin donde escribire
printf(lcd_putc,"%c Letra de abajo",letra) ;//imprimo en la lcd la variable letra
}

MANEJO DE TECLADO
MATRICIAL 4X4

Manejo de Teclado
4x4
Los teclados matriciales son muy utilizados, pues permiten mayor cantidad de teclas con
menos lneas de control, pero requiere un proceso de bsqueda y traduccin de tecla. Este
teclado posee un arreglo de 4 filas por 4 columnas y la cantidad de pines empleados para
controlar dicho teclado es la suma de las filas y las columnas. Por lo general suele
emplearse el puerto b para conectar el teclado al pic.
El valor generado por una tecla presionada, se obtiene de la combinacin de la lectura de
las filas y las columnas.
El compilador posee dentro de sus libreras una dedicada al manejo de Teclados
matriciales, dicho archivo lleva el nombre de KBD.c alguna de sus caractersticas son:

Permite manejar un teclado de 3x3


Puede trabajar con los puertos B y D.

En nuestro caso debemos emplear una librera que maneje un teclado 4x4 y esta se obtiene
haciendo algunas modificaciones a la librera anterioresta nueva librera se llamara
KBD4X4.c.

Manejo de Teclado
4x4
En este caso esta librera no requiere ser inicializada.
kbd_getc();
Es la funcin que retorna el valor presionado en el Teclado, este puede ser guardado
en una variable de tipo char.
Ejemplo: Tecla = kbd_getc();
Por defecto, este driver usa el puerto B para establecer a comunicacin entre el
Teclado y el microcontrolador.
Pines utilizados para el Teclado:
B0 -> Columna 1
B1 -> Columna 2
B2 -> Columna 3
B3 -> Columna 4
B4 -> Fila 1
B5 -> Fila 2
B6 -> Fila 3
B7 -> Fila 4

Manejo de Teclado
4x4 (Esquemtico)

Manejo de Teclado
4x4 (Programa)
#include <16F877.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT //ordenes para el programador
#use delay (clock=4000000) //Fosc=4Mhz
#define use_portb_kbd TRUE
#include <KBD4x4.c> //libreria manejo keypad
#include <lcd.c> //libreria para el manejo de lcd
char c; //variable en la que se almacena la tecla pulsada
void main(void)
{
lcd_init(); //inicializa pantalla lcd
port_b_pullups(TRUE); //necesario para teclado
lcd_putc("\fEscribeme...\n");// escribir "Escribeme" en la pantalla
while (TRUE)
{
c=kbd_getc();// guardar en c la tecla pulsada
if(c!=0)
if(c=='#')//si se presiona la tecla numeral
lcd_putc('\f');//borra la pantalla
else// sino
lcd_putc(c);//se presenta en la lcd la tecla pulsada
}
}

Tareas: Parte III


7. Disear un programa que represente los 16 dgitos del sistema
hexadecimal en un display nodo comn.
8. Disear un programa que represente su nombre y apellido en la
primera fila de la lcd y su cdula en la segunda lnea.
9. Disear un programa que emplee un teclado y una lcd y que al pulsar
una tecla, se muestre la letra en la segunda fila y 8 columna de la lcd y
siempre se escriba en la misma posicin.
Nota: debe realizar como mnimo 2 de los 3 diseos. Los mismos deben de estar comentados en cada
lnea.

MANEJO DEL CONVERSOR


ANALGICO DIGITAL

Manejo del Conversor


Analgico Digital

Manejo del Conversor


Analgico Digital

Manejo del Conversor


Analgico Digital
Secuencia para el manejo del Conversor Analgico digital en el
compilador:
Se asignan los pines del pic que se emplearn para recibir
seales analgicas o digitales.
setup_adc_ports (value).// Inicializa los pines del PuertoA y/o
PuertoE como seales de entrada digital/analgica. Las distintas
formas en la que se pueden configurar los pines esta definida en
el archivo 16f877.h.
Ejemplo:
setup_adc_ports(RA0_ANALOG);//selecciona al pin RA0 como
entrada de seal analgica.

Manejo del Conversor


Analgico Digital
Se activa el adc y se selecciona la frecuencia de muestreo del
Conversor Analgico Digital.
setup_adc(value). Con esta instruccin activamos o
desactivamos al cad, tambin selecciona el tiempo de
conversin. El valor de (value) se emplea para seleccionar el
tiempo de conversin del adc y sus diferentes formas estn
definidas en el archivo 16f877.h
Ejemplo:
setup_adc(adc_clock_internal);//seleccionamos el reloj interno del
pic.
Se define el canal de entrada.
Se realiza un retardo de tiempo para esperar que se realice la
conversin.
Se lee el valor de la conversin.

Manejo del Conversor


Analgico Digital
Se define el canal de entrada:
set_adc_channel(chan).Con esta instruccin se selecciona el
canal y se arranca la conversin. (chan) tendr el valor del canal
usado. Si se usa el pin RA0 el canal usado es 0 y chan debe valer 0.
Ejemplo:
set_adc_channel(0); //se selecciona el canal 0 para la conversin
Retardo para esperar el proceso de conversin:
Ejemplo: delay_us(20);
Lectura del dato digital
valor = read_adc(). Esta instruccin guarda en la variable valor de
8 bits o 16 bits el valor digital de la conversin. valor debe ser
previamente definida.
Ejemplo: valor = read_adc();

Conversor Analgico
Digital (Esquemtico)

Conversor Analgico
Digital (Programa)
#include <16F877.h>
//cabecera del programa
#device adc=8
//se define la cantidad de bits a usar en el adc
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOLVP//se activan los fusibles internos del pic
#use delay(clock=4000000)
//se fija el oscilador externo a 4Mhz
#include <lcd.c>
//Librera para el manejo del lcd
#byte porta= 0x05
//se define la direccion de los puertos
#byte portd= 0x08
int8 valor;
//se define la constante de 8 bits
float temperatura;
// se define la flotante
void main()
{
lcd_init();
//inicializar la pantalla
lcd_putc("Temperatura:");
//imprimir Temperatura en la lcd
set_tris_a(255);
//colocar a todo el puerto a como entrada
set_tris_d(0);
//colocar a todo el puerto d como salida
setup_adc_ports(RA0_ANALOG);
//solo se asigna el pin RA0 como entrada analogica
setup_adc(adc_clock_internal);
//Se seleciona la frecuencia de muestreo
while(1)
//bucle: while significa mientras
{
set_adc_channel(0);
//definir el canal de entrada (RA0)
delay_us(20);
//retardo de 20 microsegundo
valor=read_adc();
//el valor digital de la conversin se guarda en valor
temperatura = valor*((5.0)/255)*30;
//el resultado se multiplica por 30 para alcanzar 150 grados
lcd_gotoxy(1,2);
printf(lcd_putc,"%3.1f C
",temperatura);//imprimir el valor de la flotante
delay_ms(1);
//un retardo de 1 mili segundo
}
}

MANEJO DE MEMORIA EEPROM


INTERNA

Manejo de la Memoria
EEPROM Interna
La memoria eeprom interna del pic 16f877 es de 256Bytes, es decir, posee
256 posiciones y cada una tiene un espacio de 8 bits, en los cuales se pueden
almacenar variables que se desea que siempre esten en el pic y no se puedan
borrar.
Instrucciones para el manejo de la memoria EEPROM:
READ_CALIBRATION(n);
Esta funcin lee "n" posiciones de la memoria de calibracin de un 14000.
Ejemplo:
Fin = read_calibration(16

Manejo de la Memoria
EEPROM Interna
READ_EEPROM(address);
Esta funcin lee un byte en la direccin (address) de Eeprom
especificada. La direccin puede ser 0-255.
Ejemplo:
for(h=0;h<=15;h++){
Dato = read_eeprom(h);//se guarda lo que este en esa direccin
en //la variable dato. Dato y h deben haber sido previamente
//definidas
}

Manejo de la Memoria
EEPROM Interna
WRITE_EEPROM (address, value)
Esta funcin escribe un byte de datos en la direccin de memoria
EEPROM especificada, address puede valer 0-255; value es el byte de
datos a escribir; Esta funcin puede tardar varios milisegundos para
ejecutarse.
Ejemplo:
Char Texto[]=" Curso de PICC JM FUNDATELECOM";
for(h=0;h<=31;h++){
write_eeprom(h,Texto[h]);
}

Manejo de la Memoria
EEPROM Interna
(Esquemtico)

Manejo de la Memoria
EEPROM Interna
(Programa)
#include <16F877.h>
#FUSES XT,PUT,BROWNOUT,NOPROTECT,WDT,NOLVP,NODEBUG
#use delay(clock=4000000)
#include <LCD.c>
int h,c;
char Dato;
char Texto[]=" Curso de PICC JM FUNDATELECOM";//arreglo de caracteres
// FUNCION PRINCIPAL
void main(void){
lcd_init();
for(h=0;h<=31;h++){
write_eeprom(h,Texto[h]); // Cargamos Texto en la EEPROM interna
}
while(TRUE){
c=1; //variable empleada para inr moviendo el curso horizontalmete en la lcd
for(h=0;h<=15;h++){
Dato = read_eeprom(h);
lcd_gotoxy(c,1);
printf(lcd_putc,"%c",Dato); // Visualizamos 1ra Lnea en LCD
c++;
}
delay_ms(1000);
c=1; // variable empleada para inr moviendo el curso horizontalmete en la lcd
for(h=16;h<=31;h++){
Dato = read_eeprom(h);
lcd_gotoxy(c,2);
printf(lcd_putc,"%c",Dato); // Visualizamos 2da Lnea en LCD
c++;
}
delay_ms(2000);
lcd_putc("\f");
}
}

Tareas: Parte IV
10. Disear un programa que realice una conversin analgica digital
de 10bits de un sensor de temperatura y la muestre en la lcd.
11. Disear un programa que escriba el nombre, apellido y cedula de
identidad en la memoria eeprom interna del pic y luego muestre todo
en la lcd. El nombre y apellido en la primera fila y la cedula en la
segunda fila.
Nota: debe realizar los 2 diseos. Los mismos deben de estar comentados en cada lnea.

MANEJO DE LA COMUNICACIN
SERIAL

Comunicacin Serial PC
a PIC

Comunicacin Serial
entre PICs

Comunicacin Serial
COMUNICACIN SERIE ASNCRONA en PIC C
Para configurar al PIC para comunicarse serialmente se debe configurar
la directiva #use rs232(). La forma de configuracin es la siguiente:
BAUD = x. Donde x es la velocidad de la comunicacin en baudios.
Antes de esto se debe haber colocado antes la directiva #use
delay(clock=frecuencia).
Ejemplo: baud=9600.
BITS = x. Donde x es el tamao en bits de los datos que sern
enviados. Puede tener valores entre 5 y 9.
Ejemplo: bits =8.
PARITY= x. Con esta opcin se especifica el empleo de paridad para
la comprobacin del dato. X puede ser: N (none: sin), O (odd: impar) o E
(even: par).
Ejemplo: parity =N.

Comunicacin Serial
XMIT= PIN_x. x es el pin que se va a utilizar para la transmisin.
Ejemplo: xmit=PIN_C6.
RCV=PIN_x. x es el pin que se va a utilizar para la recepcin.
Ejemplo: rcv=PIN_C7.
ERRORS. Si se emplea esta opcin, el compilador define una
variable llamada RS232_ERRORS que recoge los errores en cada
recepcin y los resetea despus de que stos se produzcan.
Ejemplo:
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)
NOTA: Estas no son todas las opciones de la directiva rs232 existen
ms, pero estas son las ms empleadas. Para ms informacin ver el
manual serie_asincrona_en _c.

Comunicacin Serial
Las funciones integradas del compilador ms usadas para
comunicacin serie asncrona a las que afecta la directiva rs232
son las siguientes:
Para configuracin:
set_uart_speed(baudios). Esta funcion slo se puede emplear
en aquellos dispositivos que utilizan el mdulo SCI (USART)
interno hardware. La funcin se emplea para cambiar la
velocidad de transmisin/recepcin en tiempo de ejecucin (no
en la compilacin).
Ejemplo:
switch( input_d() & 0x03)
{
case 0: set_uart_speed(2400);
break;
case 1: set_uart_speed(4800);
break;
}

Comunicacin Serial
Para la transmisin:
putc() putchar() (son idnticas) putc(caracter).
Se enva un carcter a travs del pin especificado
para envo (XMIT) en la directiva #USE RS232.
Ejemplo: char mensaje[10];
putc(*);
for(i=0;i<10;i++) putc(mensaje[i]);
puts() Llamada puts(tira_caracteres). Envia una
tira de caracteres.
Ejemplo: puts (Hola curso de PIC C);

Comunicacin Serial
Printf()
printf(tira_caracteres)
printf(tira_car_constantes,Valores...)
printf(Funcin, tira_car_constantes, Valores...)
Esta funcin saca, mediante la Funcin de salida especificada, los
caracteres y los valores para su representacin. Valores son
variables en una lista separadas por comas Funcin es el nombre de
la funcin que se debe emplear para sacar los caracteres (si no se
especifica nada es la putc() por defecto).
Ejemplo: printf("voltage: %f\r",voltio);//voltio es una flotante.

Comunicacin Serial
Para la recepcin:
getc() getch() getchar() (son idnticas).
Esta funcin cuando se le llama, espera por la llegada de un byte en
el pin de recepcin RCV especificado en la directiva #USE RS232
y devuelve dicho byte como resultado para guardarlo en una
variable definida como carcter.
Ejemplo: valor =getc();
Para evitar que el microcontrolador quede colgado esperando de
manera indefinida la recepcin de un byte que no llega, se debera
usar la funcin kbhit() para verificar si ha llegado un carcter y est
disponible.

Comunicacin Serial
kbhit()
Esta funcin devuelve TRUE si el byte ha sido recibido y
est disponible en el buffer para ser ledo mediante getc().
Ejemplo:
if(kbhit()){ //se ha recibido un caracter?
disable_interrupts(INT_RDA);
//-------------------------------switch(getc()){
case 'a': output_high(PIN_C0); //poner en alto pin C0
break;
//-------------------------------case 'b': output_low(PIN_C0);//poner en bajo el pin C0
break;
}
}

Comunicacin Serial
PIC a Virtual Terminal
(Programa)

#include <16f877.h>
#fuses xt,nolvp,noput,noprotect,nowdt
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)
void main()
{
int i1;
printf(" Tabla de Multiplicar del 5\r");
While (i1<=10){
printf(" 5 x %d = %d\r",i1,i1*5);
i1++;
delay_ms(1000);
}
printf(" Termino la multiplicacion\r");
}

Comunicacin Serial
PIC a Virtual Terminal
(Esquemtico)

Comunicacin Serial PIC a


Hyperterminal(Programa)
#include <16f877.h>
#use delay(clock=4000000)
#fuses xt,nolvp,noprotect,nowrt
#use rs232(baud=9600, bits=8, stop=1, parity=N, xmit=PIN_C6, rcv=PIN_C7)
void main(){
int i1;
printf(" Tabla de multiplicar del 4 \n\r");
While (i1<=10){
printf(" 4 x %d = %d \n\r",i1,i1*4);
i1++;
delay_ms(1000);
}
printf(" Termino la multiplicacion \n\r");
}

Comunicacin Serial
PIC a HyperTerminal
(Esquemtico)

Comunicacin Serial
PIC a PIC (Programa)
Cuando se realiza una transmisin serial de
PIC a PIC se debe activar una interrupcin
en el PIC que se configure como receptor. O
en ambos, en caso de que la transmisin sea
full_duplex.
Anlisis de los programas:
TX serial.c
RX serial.c

Tareas: Parte V
12. Disear un programa que muestre en el virtual terminal de
proteus. Su nombre completo, cedula, nivel de instruccin, y su
opinin sobre el curso. La transmisin serial deber hacerla a
2400Baudios.

Nota: Los mismos deben de estar comentados en cada lnea.

GRACIAS

También podría gustarte