Vous êtes sur la page 1sur 78

Cursillo en C

Hola a todos en vista que estn comenzando con este Proyecto nuevo en este foro pues aqu va mi
aporte pequeo pero con la intencin de que sea de utilidad para muchos que comienzan y
aquellos que ya estn en el mundo de la programacin de microcontroladores PIC de la casa de
Microchip.

Aclaro no me considero un experto pero la intencin es poder dar a conocer lo aprendido nada
mas, cualquier comentario o idea ser bienvenida.

INDICE

I. Introduccin
-Estructura de un Programa
-Directivas del Preprocesador
II. Introduccin
-Definicin de constantes
-Declaracin de variables
-Programa principal
III. Introduccin
-Operadores y Expresiones
-Estructuras de control
-Comentarios
IV. Introduccin
-E/S Discreta
-Manipulacin de bit
-Manipulacin de byte
-Retardos
1. Creando proyectos con el Compilador
2. Ejemplo 1: Encender y apagar un Led manera cclica.
3. Ejemplo 2: Realizar un programa para generar 8 salidas secuenciales
4. Ejemplo 3: Realizar un programa para encender y apagar un Led a travs de dos entradas
digitales
5. Ejemplo 4: Manejo de Visualizador de 7 Segmentos
6. Ejemplo 5: Manejo de Visualizador de 7 Segmentos y entradas digitales
7. Ejemplo 6: Contador de 0~99 con un Visualizador de 7 Segmentos
8. Ejemplo 7: Contador ascendente-descendente de dos dgitos con un Visualizador de 7
Segmentos
9. Ejemplo 8: Mostrando texto en Visualizador de 7 Segmentos
10. Ejemplo 9: Pantallas de Cristal Lquido (LCD)
11. Ejemplo 10: Teclados Matriciales
12. Lectura y escritura de la memoria de datos EEPROM
-Ejemplo 11: Guardar una secuencia de datos en la memoria EEPROM del PIC con la directiva
# rom

HERRAMIENTAS

Las herramientas a utilizar son:

MPLab IDE (Entorno de trabajo)
http://www.microchip.com/
CCS Plug-in MPLab (Integrar compilador CCS con MPLab)
http://www.ccsinfo.com/downloads.php
CCS PCWHC v4.xxx (Compilador utilizado y Manuales)
http://www.ccsinfo.com/downloads.php
Manual CCS (Manual compilador en castellano)
http://www.cursos.ucv.cl/eie48700/referencias/CCS_C_Manual.pdf
Proteus v7.x SPx
http://www.labcenter.co.uk/
Microcontrolador PIC 16F877A
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010242
ltima modificacin: Mayo 19, 2009, 02:16:52 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #1 en: Abril 16, 2009, 09:21:13
INTRODUCCION

El microcontrolador PIC16F877A de Microchip pertenece a una gran familia de microcontroladores
de 8 bits (bus de datos) que tienen las siguientes caractersticas generales que los distinguen de
otras familias:

- Arquitectura Harvard
- Tecnologa RISC
- Tecnologa CMOS

Estas caractersticas se conjugan para lograr un dispositivo altamente eficiente en el uso de la
memoria de datos y programa y por lo tanto en la velocidad de ejecucin.

CARACTERISTICAS MICROCONTROLADOR PIC 16F877A

CPU RISC
Slo 35 instrucciones que aprender
Todas las instrucciones se ejecutan en un ciclo de reloj, excepto los saltos que requieren dos
Frecuencia de operacin de 0 a 20 MHz (DC a 200 nseg de ciclo de instruccin)
Hasta 8k x 14 bits de memoria Flash de programa
Hasta 368 bytes de memoria de datos (RAM)
Hasta 256 bytes de memoria de datos EEPROM
Hasta 4 fuentes de interrupcin
Stack de hardware de 8 niveles
Reset de encendido (POR)
Timer de encendido (PWRT)
Timer de arranque del oscilador (OST)
Sistema de vigilancia Watchdog timer.
Proteccin programable de cdigo
Modo SEP de bajo consumo de energa
Opciones de seleccin del oscilador
Programacin y depuracin serie In-Circuit (ICSP) a travs de dos patitas
Lectura/escritura de la CPU a la memoria flash de programa
Rango de voltaje de operacin de 2.0 a 5.5 volts
Alta disipacin de corriente de la fuente: 25mA
Rangos de temperatura: Comercial, Industrial y Extendido
33 pines de Entrada/Salida
Encapsulado: 40 pines DIP, 44 pines PLCC y 44 pines TQFP
Bajo consumo de potencia:
- Menos de 0.6mA a 3V, 4MHz
- 20 A a 3V, 32 Khz
- Menos de 1A corriente de standby

PERIFERICOS

Timer0: Contador/Temporizador de 8 bits con pre-escalador de 8 bits
Timer1: Contador/Temporizador de 16 bits con pre-escalador
Timer0: Contador/Temporizador de 8 bits con pre-escalador y post-escalador de 8 bits y
registro de periodo.
Dos mdulos de Captura, Comparacin y PWM
Convertidor Analgico/Digital: de 10 bits, hasta 8 canales
Puerto Serie Sncrono (SSP)
Puerto Serie Universal (USART/SCI)
Puerto Paralelo Esclavo (PSP): de 8 bits con lneas de protocolo




Podra existir la interrogante de el porqu se utiliza este micro y no otro, pues la razn es sencilla
ya que son los micros que mas tengo por el momento y que fcilmente satisfacen las cosas que
pienso plantear.

Bueno considerando que ya hayan ledo el Manual en Castellano pues ahora si podemos continuar
con seguridad.

Para empezar vamos a dar algunos conceptos sobre el Lenguaje a utilizar y algunas cosas que
servirn en los futuros programas que realicemos.

ESTRUCTURA DE UN PROGRAMA EN CCS

En la estructura de un programa en C pues existen ciertos bloques fundamentales que hacen un
programa entre estos podemos mencionar:

# Directivas del Preprocesador
// Declaracin del Prototipo de Funciones
// Declaracin de Variables Globales
// Definicin de Constantes

// Programa Principal (main)
main(){
Varibles Locales;
Bloque de sentencias;
Llamadas a funciones;

..
.

}

// Definicin de Funciones
Funcin () {
Variables Locales Funcin;
Bloque de Sentencias;

..
.
}

En lneas generales esta es la estructura bsica de un programa en C, podemos decir que CCS
difiere un poco del clsico ANSI C notaran eso aquellos que programan en C.

Bueno para continuar vamos a dar algunos conceptos de la estructura de un programa en C.

Directivas del Preprocesador

Todas las directivas del preprocesador comienzan con el carcter # seguido por un comando
especfico. Algunas de estas directivas son extensiones del C estndar. El C proporciona una
directiva del preprocesador, que los compiladores aceptan, y que permite ignorar o actuar sobre
los datos que siguen. El compilador de CCS admite cualquier directiva del preprocesador que
comience con PRAGMA, lo que asegura la compatibilidad con otros compiladores.

A continuacin se describen algunas directivas del compilador que se emplearn para programar
los microcontroladores PIC en estas prcticas.

#include <archivo>
#include archivo

Directiva que permite cargar un archivo con las definiciones del microcontrolador a utilizar, donde
pueden encontrarse informacin referente a: funciones, argumentos, disposicin de pines y otros.

Ejm: #include <PIC16F877A.h>

#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 necesaria para algunos
programadores de dispositivos. Las opciones que existen para el PIC16F877A son:

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

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 Code protected from reads
NOPROTECT Code not protected from reading

Brown Out Reset:
NOBROWNOUT No brownout reset
BROWNOUT Reset when brownout detected

Programacin por Vajo Voltaje:
NOLVP No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
LVP Low Voltage Programming on B3(PIC16) or B5(PIC18)

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

Ejm: #FUSES XT,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP


#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().

Ejm:
#USE DELAY (CLOCK=4000000) // Definimos un cristal de 4MHz


#USE FAST_IO (puerto)

Esta directiva afecta al cdigo que el compilador generar para las instrucciones de entrada y
salida. Este mtodo rpido de hacer I/O ocasiona que el compilador realice I/O sin programar el
registro de direccin TRIS por lo tanto consume menos 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.

Ejm: #use fast_io(A)


#USE FIXED_IO (puerto_OUTPUTS=pin_x#, pin_x#...)

Se genera cdigo relativo a la direccin de los datos de manera previa cada vez que aparece una
funcin integrada del tipo input( ) output( ), pero los pines se configuran de acuerdo con la
informacin que acompaa a la directiva (slo se indican los pines de salida) y no dependiendo de
que la operacin sea de entrada o de salida. Usa mas memoria que el fast_io. USE FIXED_IO
(B_OUTPUTS = PIN_B2 , PIN_B3)

Ejm: #use fixed_io(a_outputs=PIN_A2, PIN_A3)


#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.

Ejm: #use standard_io(A)

Estas son algunas de la muchas directivas del preprocesador, ojo no son todas pero considero que
por ahora son las importantes a futuro estudiaremos algunas ms que sern de utilidad.

ltima modificacin: Mayo 19, 2009, 02:02:39 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #2 en: Abril 16, 2009, 09:25:56
DEFINICION DE CONSTANTES

La directiva #DEFINE viene del ANSI C y est presente en el CCS, es muy til ya que podemos
predefinir algunos valores que sean necesarios en nuestro programa, permitiendo tener un
programa mejor estructurado.

Ejm:
#define pi 3.1415
#define BITS 8
a=a+BITS; //Lo mismo que a=a+8;
#define hi(x) (x<<4)
a=hi(a); //Lo mismo que a=(a<<4);

Algunas otras directivas que permiten utilizar o controlar variables son:

#BIT identificador = x.y

Esta directiva crear un identificador "id" que puede utilizarse como cualquier SHORT INT (entero
corto; un bit). El identificador har referencia a un objeto en la posicin de memoria x ms el bit
de desplazamiento y.

Ejm:
#bit CALEFACTOR = PORTB.0 // Bit de control Calefactor
#bit VENTILADOR = PORTB.1 // Bit de control Ventilador


#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.

Ejm:
#byte PORTB=0x06 // Direccin del PortB
#byte TRISB=0x86 // Direccin del TrisB

DECLARACION DE VARIABLES

En el ANSI C y en CCS existen dos tipos de variables las globales y locales que a continuacin
explicaremos:

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.

A continuacin conoceremos algunos tipos de variables:

unsigned define un nmero de 8 bits sin signo
unsigned int define un nmero de 8 bits sin signo
int define un nmero de 8 bits sin signo
char define un nmero de 8 bits sin signo
long define un nmero de 16 bits sin signo
long int define un nmero de 16 bits sin signo
signed define un nmero de 8 bits con signo
signed int define un nmero de 8 bits con signo
signed long define un nmero de 16 bits con signo
float define un nmero de 32 bits en punto flotante
short define un bit
short int define un bit
int1 define una variable de 1 bit
int8 define una variable de 8 bits
int16 define una variable de 16 bits
int32 define una variable de 32 bits
void sin valor

Ejm:
int aux;
char nombre;
float contador;

PROGRAMA PRINCIPAL (main)

La funcin main es la contiene las instrucciones o ordenes se ejecutaran a fututo en nuestro
programa, encargada de gestionar el llamado a las interrupciones y funciones que se tengan.

Como esta funcin no retorna ningn valor alguno posee el tipo de variable void y al no poseer
argumentos es de tipo void, la declaracin de esta funcin es la siguiente:

void main (void) {
// Variables locales;
// Bloque de sentencias;
// Llamada a funciones
}

Siempre el cuerpo de cualquier funcin est entre llaves {}.

ltima modificacin: Mayo 19, 2009, 02:10:08 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #3 en: Abril 16, 2009, 09:30:44
OPERADORES Y EXPRESIONES

Una expresin de asignacin tradicional es de la forma expr1 = expr1 operador expr2, pero
tambin puede ser representada por otra ms corta expr1 operador = expr2. En la siguiente tabla
se resumen los operadores de asignacin compuesta y su significado:

Operador Descripcin
+= Asignacin de suma
-= Asignacin de resta
*= Asignacin de multiplicacin
/= Asignacin de divisin
%= Asignacin de resto de divisin
<<= Asignacin de desplazamiento a la izquierda
>>= Asignacin de desplazamiento a la derecha
&= Asignacin de AND de bits
|= Asignacin de OR de bits
^= Asignacin de OR exclusivo de bits
~= Asignacin de negacin de bits
++ Incremento
-- Decremento

Los operadores aritmticos para realizar operaciones matemticas son:

Operador Descripcin Ejemplo

+ Suma (enteros o reales) resul = var1 + var2
- Resta (enteros o reales) resul = var1 - var2
* Multiplicacin (enteros o reales) resul = var1 * var2
/ Divisin (enteros o reales) resul = var1 / var2
- Cambio de signo en enteros o reales -var1
% Mdulo; rango = n [A1]% 256

Los operadores relaciones tienen como objetivo comparar dos operandos y dar un resultado
entero, 1 si es verdadero y 0 si es falso.

Operador Descripcin
< Menor que
> Mayor que
<= Menor o igual que
>= Mayor o igual que
== Igual a
!= Distinto de

Los operadores lgicos, al igual que los operadores relacionales, devuelve 1 o 0 tras la evaluacin
de sus operandos.

Operador Descripcin
! No lgico (NOT)
&& Y lgico (AND)
|| O lgico (OR)

Existen tambin los llamados operadores de manejo de bits que permiten actuar sobre los
operandos a nivel de bits y solo pueden ser de tipo entero incluyendo el tipo char.

Operador Descripcin
~ Negacin de bits (complemento a 1)
& Y de bits (AND)
^ O exclusivo de bits (EXOR)
| O de bits (OR)
>> Desplazamiento a la derecha
<< Desplazamiento a la izquierda

Las expresiones empleadas habitualmente son las siguientes:

Constantes
123 Decimal
0123 Octal
0x123 Hex
0b010010 Binario
x Carcter
\010 Carcter Octal
\x Carcter especial; x puede ser: n,t,b,r,f,,\d,v?
abcdef Cadena (el carcter nulo se agrega al final)

ESTRUCTURAS DE CONTROL

Sentencia if

Se ejecuta una sentencia o bloque de cdigo si la expresin que acompaa al if tiene un valor
distinto a cero (verdadero). Si es cero (falso) contina sin ejecutar la sentencia o bloque de
sentencias.

if (expresin)
sentencia;

if (expresin) {
sentencia 1;
sentencia 2;
...
}


Sentencia if-else

Se evala una expresin y, si es cierta, se ejecuta el primer bloque de cdigo (o sentencia 1). Si es
falsa, se ejecuta el segundo.

if (expresin)
sentencia 1;
else
sentencia 2;


Sentencia switch

Substituye a if-else cuando se realiza una seleccin mltiple que compara una expresin con una
lista de constantes enteras o caracteres. Cuando se da una coincidencia, el cuerpo de sentencias
asociadas a esa constante se ejecuta hasta que aparezca break.

switch (expresin){

case constante 1:
grupo 1 de sentencias;
break;
case constante 2:
grupo 2 de sentencias;
break;
...
default:
grupo n de sentencias;
}

default es opcional y el bloque asociado se ejecuta slo si no hay ninguna coincidencia con las
constantes especificadas.


Sentencia de bucle for

Se emplea para repetir una sentencia o bloque de sentencias.

for (inicializacin ; condicin ; incremento){
sentencia(s);
}

En la inicializacin se le asigna un valor inicial a una variable que se emplea para el control de la
repeticin del bucle.

La condicin se evala antes de ejecutar la sentencia. Si es cierta, se ejecuta el bucle. Si no, se sale
del mismo.

El incremento establece cmo cambia la variable de control cada vez que se repite el bucle.

Es posible anidar bucles for para modificar dos o ms variables de control.


Sentencia de bucle while

La repeticin se lleva a cabo mientras sea cierta una expresin.

while (expresin){
sentencia(s);
}

La expresin se evala antes de cualquier iteracin. Si es falsa, ya no se ejecuta la sentencia o
bloque de sentencias.


Sentencia de bucle do-while

do{
sentencia(s);
}while (expresin);

Las sentencias se ejecutan antes de que se evale la expresin, por lo que el bucle se ejecuta
siempre al menos una vez.

COMENTARIOS

Los comentarios se incluyen en el cdigo fuente para explicar el sentido y la intencin del cdigo al
que acompaan. Son ignorados por el compilador y no afectan a la longitud ni rapidez de
ejecucin del cdigo final.

Hay dos formatos posibles para los comentarios.

Formato 1. Empiezan por // y finalizan con el final de la lnea.
// Esto es un comentario.

Formato 2. Empiezan por /* y finalizan por */. No es posible anidar comentarios con este formato.
/* Esto tambin es un comentario */

Un comentario se puede colocan en cualquier lugar del programa y pueden tener la longitud y el
nmero de lneas que se quiera.

ltima modificacin: Abril 17, 2009, 09:16:19 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #4 en: Abril 17, 2009, 09:24:29
E/S DISCRETA

Las funciones que manejan un bit son:

input(pin) Retorna el valor 0 1 del pin indicado.
output_bit(pin,valor) Colocar el pin indicado a 0 1.
output_high(pin) Colocar el pin a estado alto 1.
output_low(pin) Colocar el pin a estado bajo 0.

Las que manejan un byte son:

input_x() Donde x es el nombre del puerto (A, B,...). int de 8 bits.
output_x(valor) Sacar el valor por el puerto X (A, B,....).

Nota: Estas funciones aparecen en el manual pero no son reconocidas por el compilador, si
queremos leer o escribir bytes deberemos utilizar la directiva #byte PUERTO = dir. Puerto

Ejm: #BYTE PORTB = 0x06

Las que configuran los pines:
port_b_pullups(value) Activamos o desactivamos las Rpull-up del puerto B.
set_tris_x(valor) Permite configurar los puertos X (A, B,...) para que sus pines sean
entradas o salidas. Un 1 indica entrada y un 0 salida.


MANIPULACIN DE BIT

Para manipular un bit podemos encontrarnos con:
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.


MANIPULACIN DE BYTE

rotate_left (address,byte) Rotar a la izquierda un bit de un array o una estructura. El bit MSB
pasa a ser el 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

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.

delay_us (time) Realiza retardos del valor especificado en milcrosegundos (1..65535). Esta funcin
no utiliza los timers internos pero es preciso utilizar la directiva #use delay especificando la
frecuencia del reloj.

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.
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #5 en: Abril 17, 2009, 09:32:38
Creando proyectos con el Compilador

Ahora si con todo lo avanzado creo solo queda comenzar, a utilizar el compilador CCS.

Para eso vamos a explicar cmo crear un nuevo proyecto en CCS, aqu van los pasos a seguir:

1.- Paso:
Abrir compilador CCS, seguidamente seleccionamos la pestaa Project luego hacemos click en PIC
Wizard y guardamos el proyecto con el nombre que se quiere.


2.- Paso: A continuacin seleccionamos el microcontrolador a utilizar y seleccionar los parmetros
que se requieran.




3.- Paso: Luego de pulsar OK, se tendr la siguiente ventana con los valores seleccionados.


4.- Podemos ver en la 1ra lnea de cdigo una directiva donde se llama a un archivo en este caso
Ejemplo 1.h dicho archivo contiene los siguientes datos:
Cdigo: [Seleccionar]
#include <16F877A.h>
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz
to 10 mhz for PCD
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected

#use delay(clock=4000000)

Como podemos ver los datos no son otra cosa que los definidos previamente en la creacin del
proyecto, la verdad es indistinto que estos parmetros estn fuera o dentro del archivo fuente,
entonces para comodidad tal vez, podramos copiar todo el contenido del archivo.
Con eso el archivo quedara de la siguiente manera:


Ahora podemos hacer algunos ejemplos algo sencillos.......
ltima modificacin: Mayo 19, 2009, 02:17:16 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #6 en: Abril 17, 2009, 09:41:25
Ejemplo 1:

Comencemos con algo bsico y sencillo que ser el primer ejemplo a realizar, y paso a explicar el
problema y en lo que consistir el programa.



Problema: Encender y apagar un Led con un periodo de 500ms de manera cclica.
Recursos a Utilizar: Salida de Led Puerto B, Pin RBO.

Primero definimos las directivas de control:
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz
En este caso optamos por etiquetar la direccin del puerto B y tambin el Bit RB0 con los nombres
de PORTB y Led respectivamente como sigue a continuacin:
Cdigo: (c) [Seleccionar]
#byte PORTB=0x06 // Direccin del PortB

#bit Led = PORTB.0 // Bit asignada a identificador Led
Luego iniciamos con la funcin principal (main), y seguidamente es aqu donde definimos el puerto
a utilizar y declarar sus estados ya sean salida o entrada, como en el ejemplo solo se requiere una
salida y las pueden ser entradas o salidas se opto por que todo el puerto trabaje como salidas, eso
depender de las necesidades que se tengan.

SET_TRIS_X(value) // Donde X puede tomar los valores de A,B,C,D,E

Estas funciones permiten escribir directamente los registros tri-estado para la configuracin de los
puertos. Cada bit de value representa una patilla. Un '1' indica que la patilla es de entrada y un '0'
que es de salida.

Ejm:
set_tris_b(0x00); // Notacin en Hex
set_tris_b(0b00000000); // Notacin Binaria
set_tris_b(0); // Notacin Decimal
Cdigo: (c) [Seleccionar]
// 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 = 0; // Apago el LED
delay_ms(500); // Espero 500ms.
Led = 1; // Enciendo el LED
delay_ms(500); // Espero 500ms.
}
}
Como podemos ver en el resto del cdigo luego de definir el puerto a utilizar limpiamos dicho
puerto con la nica finalidad de que no haya ningn dato indeseable a la salida del puerto B.

Luego ingresamos al bucle infinito, en cual introducimos el cdigo para la tarea a realizar, como ya
etiquetamos el bit RB0 pues solo basta con llamar al nombre y asignarle el estado que deseamos a
su salida.

Algunas consideraciones que se deben tomar a la hora de programar en C son:

- Siempre el finalizar una instruccin o llamada a funcin acabar con el ;.
- En la funcin principal no olvidar abrir y cerrar llaves ({}).
- Lo mismo para el bucle While deben abrir y cerrar llaves ({}).
- Considerar que en el C se distinguen maysculas de minsculas sea no es lo mismo Led = 0;
que LED = 0; en el primer caso no habr problemas pero el segundo si ya que es una variable que
no est definida el programa.

Perdn por ser tan extenso en las explicaciones pero creo cuando uno comienza es necesario
despejar dudas, ya que se entiende que esta es una gua bsica de programacin y no un curso
avanzado, a futuro vamos a reducir las explicaciones y proponer mas cdigo que sea de utilidad.

Este primer programa se puede hacer de diversas formas utilizando otras funciones, entonces
hagamos un par de ellas y luego pasamos a otro ejemplo.

Ejemplo 1v1: Ac utilizamos la funcin output_bit(pin,valor)
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#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_Bit(PIN_B0,0);// Apago el LED
delay_ms(500); // Espero 500ms.
output_Bit(PIN_B0,1);// Enciendo el LED
delay_ms(500); // Espero 500ms.
}
}
Ejemplo 1v2: En este caso son dos funciones output_low(pin) y output_high(pin)
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#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_low(PIN_B0); // Apago el LED
delay_ms(500); // Espero 500ms.
output_high(PIN_B0); // Enciendo el LED
delay_ms(500); // Espero 500ms.
}
}
Ejemplo 1v3: Este es un poco ms corto ya que solo negamos la salida y obtenemos ambos
estados.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB

#bit Led = PORTB.0 // Bit asignada a identificador Led

// 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 = ~ Led; // Apago y Encendido del LED
delay_ms(500); // Espero 500ms.
}
}
Viendo los ejemplos anteriores podemos decir hay mil un maneras de llegar a la solucin y eso
solo depender de cada programador y la visin que tenga sobre la posible solucin.
ltima modificacin: Mayo 02, 2009, 08:48:40 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #7 en: Abril 18, 2009, 08:25:07
Ejemplo 2:



Problema: Realizar un programa para generar 8 salidas secuenciales, por los menos que tengan
tres secuencias con un periodo de 750ms de manera cclica.

Recursos a Utilizar: Salida del Puerto B.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#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
// Secuencia #1
PORTB = 0b00000001;
delay_ms(750); // Retardo 750ms.
PORTB = 0b00000010;
delay_ms(750);
PORTB = 0b00000100;
delay_ms(750);
PORTB = 0b00001000;
delay_ms(750);
PORTB = 0b00010000;
delay_ms(750);
PORTB = 0b00100000;
delay_ms(750);
PORTB = 0b01000000;
delay_ms(750);
PORTB = 0b10000000;
delay_ms(750);

PORTB = 0b00000000; // Limpiamos Secuencia anterior
delay_ms(3000); // Retardo 3s.

// Secuencia #2
PORTB = 0b11100111;
delay_ms(750);
PORTB = 0b11000011;
delay_ms(750);
PORTB = 0b10000001;
delay_ms(750);
PORTB = 0b10000001;
delay_ms(750);
PORTB = 0b11000011;
delay_ms(750);
PORTB = 0b11100111;
delay_ms(750);

PORTB = 0b00000000; // Limpiamos Secuencia anterior
delay_ms(3000); // Retardo 3s.

// Secuencia #3
PORTB = 0b10000001;
delay_ms(750);
PORTB = 0b01000010;
delay_ms(750);
PORTB = 0b00100100;
delay_ms(750);
PORTB = 0b00011000;
delay_ms(750);
PORTB = 0b00011000;
delay_ms(750);
PORTB = 0b00100100;
delay_ms(750);
PORTB = 0b01000010;
delay_ms(750);
PORTB = 0b10000001;
delay_ms(750);

PORTB = 0b00000000; // Limpiamos Secuencia anterior
delay_ms(3000); // Retardo 3s.
}
}
Esta es una posible solucin al problema planteado, podra ser una mejor opcin el utilizar
vectores o arrays, yo los conozco como vectores unidimensionales, ac un ejemplo como seria
utilizando vectores.

Ejemplo 2v1: En este ejemplo utilizamos vectores unidimensionales.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB

int Secuencia1[8]={1,2,4,8,16,32,64,128};
int Secuencia2[6]={231,195,129,129,195,231};
int Secuencia3[8]={129,66,36,24,24,36,66,129};

// FUNCION PRINCIPAL
void main(void){
int i;
set_tris_b(0x00); // Definimos el Puerto B como salida
PORTB = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
// Secuencia #1
for(i=0;i<=7;i++){
PORTB = Secuencia1[i]; // Cargamos dato en PORTB en la posicin
i
delay_ms(750); // Retardo 750ms.
}
PORTB = 0b00000000; // Limpiamos Secuencia anterior
delay_ms(3000); // Retardo 3s.

// Secuencia #2
for(i=0;i<=5;i++){
PORTB = Secuencia2[i]; // Cargamos dato en PORTB en la posicin
i
delay_ms(750); // Retardo 750ms.
}
PORTB = 0b00000000; // Limpiamos Secuencia anterior
delay_ms(3000); // Retardo 3s.

// Secuencia #3
for(i=0;i<=7;i++){
PORTB = Secuencia3[i]; // Cargamos dato en PORTB en la posicin
i
delay_ms(750); // Retardo 750ms.
}
PORTB = 0b00000000; // Limpiamos Secuencia anterior
delay_ms(3000); // Retardo 3s.
}
}
Este es ms corto en cdigo que el anterior, bueno haber si alguien se anima a poner otra posible
solucin.

Si hay alguna duda con respecto a los ejemplos propuestos pues pregunten que con gusto
despajamos cualquier duda.
ltima modificacin: Mayo 02, 2009, 08:50:24 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #8 en: Abril 18, 2009, 08:34:30
Ejemplo 3:

Ahora como ya sabemos manejar un poco las salidas pues combinmoslas con el manejo de
entradas digitales.



Problema: Realizar un programa para encender y apagar un Led a travs de dos entradas digitales.

Recursos a Utilizar: RB0 (Salida Led), RB1, RB2 (Entradas digitales).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB

#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

// FUNCION PRINCIPAL
void main(void){
set_tris_b(0b00000010); // Definimos Bit RB1 como entrada y el resto
como salida
portb = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
if(ON == 1){ // Opcion cuando pulsador Boton ON
Led = 1; // Enciendo el LED
}
if(OFF == 1){ // Opcion cuando pulsador Boton OFF
Led = 0; // Apago el LED
}
}
}
Ejemplo 3v1: Otra forma cmo podramos hacerlo, utilizando las funciones input(pin) y
output_bit(pin, valor).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB

// FUNCION PRINCIPAL
void main(void){
set_tris_b(0b00000010); // Definimos Bit RB1 como entrada y el
resto como salida
portb = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
if(input(PIN_B1)){ // Opcion cuando pulsador Boton ON
output_bit(PIN_B0,1); // Enciendo el LED
}
if(input(PIN_B2)){ // Opcion cuando pulsador Boton OFF
output_bit(PIN_B0,0); // Apago el LED
}
}
}
ltima modificacin: Mayo 02, 2009, 08:51:50 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #9 en: Abril 20, 2009, 07:24:35
Ejemplo 4:


Manejo de Visualizador de 7 Segmentos

En realidad estn formados por ocho LED (siete segmentos y un punto decimal), puede mostrar
cualquier nmero desde 0 hasta 9.

Existen dos tipos de configuraciones en estos visualizadores de LED de 7 segmentos, uno nodo
Comn y otro Ctodo Comn como a continuacin se muestra:


Tabla con los nmeros a utilizar en configuracin Ctodo Comn:





Problema: Realizar un contador decimal que se exhiba en un display de 7 segmentos, cada
nmero deber estar exhibido durante un segundo.

Recursos a Utilizar: RB0 (Salida Display 7 Segmentos).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#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
// Utilizando valores DEC(63,6,91,79,102,109,125,7,127,111)
portb = 63; // Digito 0
delay_ms(1000); // Espero 1s.
portb = 6; // Digito 1
delay_ms(1000); // Espero 1s.
portb = 91; // Digito 2
delay_ms(1000); // Espero 1s.
portb = 79; // Digito 3
delay_ms(1000); // Espero 1s.
portb = 102; // Digito 4
delay_ms(1000); // Espero 1s.
portb = 109; // Digito 5
delay_ms(1000); // Espero 1s.
portb = 125; // Digito 6
delay_ms(1000); // Espero 1s.
portb = 7; // Digito 7
delay_ms(1000); // Espero 1s.
portb = 127; // Digito 8
delay_ms(1000); // Espero 1s.
portb = 111; // Digito 9
delay_ms(1000); // Espero 1s.

// Utilizando valores HEX(3F,06,5B,4F,66,6D,7D,07,7F,6F)
portb = 0x3F; // Digito 0
delay_ms(1000); // Espero 1s.
portb = 0x06; // Digito 1
delay_ms(1000); // Espero 1s.
portb = 0x5B; // Digito 2
delay_ms(1000); // Espero 1s.
portb = 0x4F; // Digito 3
delay_ms(1000); // Espero 1s.
portb = 0x66; // Digito 4
delay_ms(1000); // Espero 1s.
portb = 0x6D; // Digito 5
delay_ms(1000); // Espero 1s.
portb = 0x7D; // Digito 6
delay_ms(1000); // Espero 1s.
portb = 0x07; // Digito 7
delay_ms(1000); // Espero 1s.
portb = 0x7F; // Digito 8
delay_ms(1000); // Espero 1s.
portb = 0x6F; // Digito 9
delay_ms(1000); // Espero 1s.
}
}
Ejemplo 4v1: Otra forma cmo podramos hacerlo, utilizando vectores.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB

int Tab7Seg[10]={63,6,91,79,102,109,125,7,127,111};

// FUNCION PRINCIPAL
void main(void){
int i=0;
set_tris_b(0x00); // Definimos el Puerto B como salida
portb = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
PORTB = Tab7Seg[i]; // Digito en variable 7Seg
delay_ms(1000); // Espero 1s.
i++; // Incrementamos variable i que seria igual a:
i=i+1;
if(i == 10) i = 0; // Pregunta si i=10 entonces a i se le asigna
0
}
}


ltima modificacin: Mayo 02, 2009, 08:54:08 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #10 en: Abril 20, 2009, 07:29:38
Ejemplo 5:

Manejo de Visualizador de 7 Segmentos y entradas digitales



Problema: Realizar un programa que visualice en el Display el valor introducido por el puerto A,
por ejemplo si tenemos un en el puerto A de 0110 en el Display se cera 5.

Recursos a Utilizar: RB0 (Salida Display 7 Segmentos), RC0~RC3 (Entradas digitales).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB
#byte PORTC=0x07 // Direccin del PortC

int Tab7Seg[10]={63,6,91,79,102,109,125,7,127,111};

// FUNCION PRINCIPAL
void main(void){
int dato;
set_tris_b(0x00); // Definimos el Puerto B como
salida
set_tris_c(0xFF); // Definimos el Puerto C como
entrada
portb = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
dato = PORTC; // Guardamos el valor del PORTA en
la variable dato
switch(dato){
case 0: PORTB = Tab7Seg[0]; // Digito en variable 7Seg
break;
case 1: PORTB = Tab7Seg[1]; // Digito en variable 7Seg
break;
case 2: PORTB = Tab7Seg[2]; // Digito en variable 7Seg
break;
case 3: PORTB = Tab7Seg[3]; // Digito en variable 7Seg
break;
case 4: PORTB = Tab7Seg[4]; // Digito en variable 7Seg
break;
case 5: PORTB = Tab7Seg[5]; // Digito en variable 7Seg
break;
case 6: PORTB = Tab7Seg[6]; // Digito en variable 7Seg
break;
case 7: PORTB = Tab7Seg[7]; // Digito en variable 7Seg
break;
case 8: PORTB = Tab7Seg[8]; // Digito en variable 7Seg
break;
case 9: PORTB = Tab7Seg[9]; // Digito en variable 7Seg
break;
default:PORTB = 0x00; // Opcion cuando el dato no esta
en el rango de 0~9
break;
}
}
}
En programa realizado utilizamos la sentencia Switch-Case como se puede ver es muy sencillo de
implementarlo.

ltima modificacin: Mayo 02, 2009, 08:57:10 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #11 en: Abril 23, 2009, 08:49:13
Ejemplo 6:

Contador de 0~99 con un Visualizador de 7 Segmentos



Problema: Realizar un programa que visualice en el Display un contador del 0 al 99.

Recursos a Utilizar: RB0 (Salida Display 7 Segmentos), RC0~RC1 (Salida Bit control de Display).

El hecho de visualizar datos en display de 7 segmentos de la forma en que se muestra en el
esquema anterior, obliga a interconectar entre si los pines correspondientes a los segmentos del
dgito 1 con los pines de los segmentos del dgito 2, de esta manera se ahorran lneas de conexin.

El mtodo utilizado para la visualizacin dnamica consiste en visualizar cada dgito durante un
instante de tiempo y a una velocidad tal que gracias a la persistencia del ojo el efecto final es que
todos los dgitos estn encendidos al mismo tiempo.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB
#byte PORTC=0x07 // Direccin del PortC

#bit Unidad = PORTC.0 // Bit asignada a identificador Unidad
#bit Decena = PORTC.1 // Bit asignada a identificador Decena

int Tab7Seg[10]={63,6,91,79,102,109,125,7,127,111};

// FUNCION PRINCIPAL
void main(void){
int uni=0,dec=0;
set_tris_b(0x00); // Definimos el Puerto B como
salida
set_tris_c(0x00); // Definimos el Puerto C como
Salida
portb = 0x00; // Limpiamos Puerto B
portc = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
PORTB = Tab7Seg[dec]; // Enva decenas
Unidad = 0; // Habilita el display de decenas
delay_ms(60);
Unidad = 1;
PORTB = Tab7Seg[uni]; // Enva unidades
Decena = 0; // Habilita el display de unidades
delay_ms(60);
Decena = 1;
uni++; // Incrementa unidades
if ( uni > 9 ){
uni = 0; // Reinicia unidades
dec++; // Incrementa decenas
if ( dec > 9 ){
dec = 0; // Reinicie decenas
}
}
}
}

A futuro cuando toquemos el tema de Interrupciones, sera bueno realizar el mismo ejemplo pero
utilizando un Timer (Temporizador).
ltima modificacin: Abril 23, 2009, 09:10:43 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #12 en: Abril 23, 2009, 08:55:25
Ejemplo 7:

Contador ascendente-descendente de dos dgitos con un Visualizador de 7 Segmentos



Problema: Realizar un programa que visualice en el Display un contador ascendente-descendente
de dos dgitos con un Visualizador de 7 Segmentos.

Recursos a Utilizar: RB0 (Salida Display 7 Segmentos), RC0~RC1 (Salida Bit control de Display),
RA0(Bit que determina modo contador).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB
#byte PORTC=0x07 // Direccin del PortC

#bit Unidad = PORTC.0 // Bit asignada a identificador Unidad
#bit Decena = PORTC.1 // Bit asignada a identificador Decena
#bit Opcion = PORTC.2 // Bit asignada a identificador Opcin

int Tab7Sega[10]={63,6,91,79,102,109,125,7,127,111};
int Tab7Segd[10]={111,127,7,125,109,102,79,91,6,63};

// FUNCION PRINCIPAL
void main(void){
int uni=0,dec=0;
set_tris_b(0x00); // Definimos el Puerto B como salida
set_tris_c(0xFC); // Definimos el Puerto C Bits 0,1 como
Salida y el resto Entrada
portb = 0x00; // Limpiamos Puerto B
portc = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
if(Opcion == 1){ // Conteo Ascendente
PORTB = Tab7Sega[dec]; // Enva decenas
Unidad = 0; // Habilita el display de decenas
delay_ms(50);
Unidad = 1;
PORTB = Tab7Sega[uni]; // Enva unidades
Decena = 0; // Habilita el display de unidades
delay_ms(50);
Decena = 1;
uni++; // Incrementa unidades
if ( uni > 9 ){
uni = 0; // Reinicia unidades
dec++; // Incrementa decenas
if ( dec > 9 ){
dec = 0; // Reinicie decenas
}
}
}
if(Opcion == 0){ // Conteo Ascendente
PORTB = Tab7Segd[dec]; // Enva decenas
Unidad = 0; // Habilita el display de decenas
delay_ms(50);
Unidad = 1;
PORTB = Tab7Segd[uni]; // Enva unidades
Decena = 0; // Habilita el display de unidades
delay_ms(50);
Decena = 1;
uni++; // Incrementa unidades
if ( uni > 9 ){
uni = 0; // Reinicia unidades
dec++; // Incrementa decenas
if ( dec > 9 ){
dec = 0; // Reinicie decenas
}
}
}
}
}
ltima modificacin: Abril 23, 2009, 09:12:09 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #13 en: Abril 23, 2009, 09:01:32
Ejemplo 8:

Mostrando texto en Visualizador de 7 Segmentos



Problema: Ahora utilizamos 4 Display multiplexados para generar un texto en este caso HOLA.

Recursos a Utilizar: RB0 (Salida Display 7 Segmentos), RC0~RC3 (Salida Bit control de Display).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB
#byte PORTC=0x07 // Direccin del PortC

void tiempo(){
delay_ms(1);
PORTB=0;
PORTC=0;
delay_ms(1);
}

// FUNCION PRINCIPAL
void main(void){
set_tris_b(0x00); // Definimos el Puerto B como salida
set_tris_c(0x00); // Definimos el Puerto C como Salida
portb = 0x00; // Limpiamos Puerto B
portc = 0x00; // Limpiamos Puerto B
while(TRUE){ // Bucle infinito
PORTB=0b11110110; // Caracter H
PORTC=0b00001110; // Habilitamos 1 Display
tiempo();
PORTB=0b10111111; // Caracter O
PORTC=0b00001101; // Habilitamos 2 Display
tiempo();
PORTB=0b10111000; // Caracter L
PORTC=0b00001011; // Habilitamos 3 Display
tiempo();
PORTB=0b11110111; // Caracter A
PORTC=0b00000111; // Habilitamos 4 Display
tiempo();
}
}
ltima modificacin: Abril 23, 2009, 09:13:47 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el
resto."
Re: Cursillo de CCS para PIC's
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's
Respuesta #14 en: Abril 23, 2009, 09:07:28
Ejemplo 9:

Pantallas de Cristal Lquido (LCD)

Es comn cuando se comienza el manejo de LCD desplegar el mensaje HOLA, pues este ejemplo
no va ser la excepcin.



Una LCD estndar es una pantalla de cristal lquido con una matriz de 16, 32, 40 u 80 caracteres de
5x7 pixeles, contando adems con un microcontrolador (generalmente el Hitachi 44780) que lo
gobierna el cual posee una interfaz de 8 o 4 bits, con 3 seales de control. Normalmente cada lnea
contiene entre 8 y 80 caracteres, y suelen ser capaces de mostrar caracteres ASCII, japoneses,
griegos...; o smbolos matemticos. Su bus de conexin puede ser de 4 u 8 bits.

El consumo de este tipo de mdulos es muy bajo (75mW), y, gracias a su sencillo manejo, son
ideales para dispositivos que requieren una visualizacin pequea o media.

En este caso utilizaremos un LCD 2 x 16, eso significa de dos filas y 16 columnas, para esto se
requiere asignar un puerto del PIC como bus de datos entre el LCD y el PIC, adems un bus de
control con el cual se realiza la gestin del LCD.

En el circuito utilizado, se empleara el puerto D para enviar los datos de 4 bits al modulo
LCD, adems se utiliza tres lneas del puerto D como bus de control. El potencimetro adicional
nos sirve para aumentar o disminuir el contraste del LCD.



Para realizar el control desde el PIC, primeramente se debe llamar a la librera LCD.c en el cual se
encuentran todas las rutinas para el trabajo del LCD.

En dicho archivo podemos encontrar las siguientes funciones para el manejo de LCD:

lcd_init ();

Debe llamarse antes que ninguna otra funcin del fichero lcd.c.

Tal y como aparece en el fichero, adems de borrar el display, configura el LCD para trabajar como
sigue:

a) En formato de 4 bits, con dos lneas y con caracteres de 58 puntos.
b) Con display encendido, cursor apagado y sin parpadeo.
c) Con autoincremento del puntero de direcciones y sin desplazamiento del display real.

lcd_gotoxy (x , y);

Establece la posicin del LCD a la que se debe acceder.

Recurdese que la primera posicin de la primera lnea tiene coordenadas
(1 , 1), y que la primera posicin de la segunda lnea es la (1 , 2).

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

Para utilizar el puerto D es necesario colocar una lnea de cdigo antes del llamado a la librera
LCd.c, dicho cdigo indica en la misma librera LCD.c.

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

Para el puerto B sigue de la siguiente manera:

#define use_portb_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

NOTA.- Ojo solo est permitido utilizar los puertos B y D.

Bueno con todo lo visto ahora podemos realizar el primer programa para el manejo del LCD.

Problema: Desplegar un mansaje en la pantalla de cristal liquido (LCD).

Recursos a Utilizar: RD (Puerto a utilizar).
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

// FUNCION PRINCIPAL
void main(void){
lcd_init(); // Iniciamos LCD
lcd_putc('\f'); // Limpiamos LCD
while(TRUE){ // Bucle infinito
lcd_gotoxy(6,1); // Linea 1 y Columna 6
lcd_putc("Hola");
lcd_gotoxy(2,2); // Linea 2 y Columna 2
lcd_putc("Foro Mikropic");
}
}

Ejemplo 9v1: El mismo ejemplo pero utilizando el carcter especial (\n) Salto al comienzo de la
segunda lnea.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

// FUNCION PRINCIPAL
void main(void){
lcd_init(); // Iniciamos LCD
lcd_putc('\f'); // Limpiamos LCD
while(TRUE){ // Bucle infinito
lcd_putc(" Hola \n Foro Mikropic ");
}
}

Ejemplo 9v2: Ahora utilizando vectores.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

// FUNCION PRINCIPAL
void main(void){
char Linea1[4]={'H','o','l','a'};
char Linea2[13]={'F','o','r','o',' ','M','i','k','r','o','p','i','c'};
int i;
lcd_init(); // Iniciamos LCD
lcd_putc('\f'); // Limpiamos LCD
while(TRUE){ // Bucle infinito
lcd_gotoxy(6,1); // Linea 1 y Columna 6
for(i=0;i<=3;i++){
lcd_putc(Linea1[i]); // Visualizamos el contenido en el vector
Linea1
}
lcd_gotoxy(2,2); // Linea 2 y Columna 2
for(i=0;i<=12;i++){
lcd_putc(Linea2[i]); // Visualizamos el contenido en el vector
Linea2
}
}
}

Realicemos el mismo ejemplo pero utilizando la funcin printf(); que creo a futuro ser de mucha
utilidad.
Para quienes vienen del viejo y conocido ANCI C sabrn como funciona, pero para quienes recin
comienzan, aqu algo de teora sobre esta funcin:

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.

t es el tipo de formato y puede ser uno de los siguientes:



Ejemplo 9v3: Ahora utilizando vectores.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

// FUNCION PRINCIPAL
void main(void){
lcd_init(); // Iniciamos LCD
lcd_putc('\f'); // Limpiamos LCD
while(TRUE){ // Bucle infinito
lcd_gotoxy(6,1); // Linea 1 y Columna 6
printf(lcd_putc,"Hola");
lcd_gotoxy(2,2); // Linea 2 y Columna 2
printf(lcd_putc,"Foro Mikropic");
}
}
ltima modificacin: Abril 30, 2009, 07:23:42 por Erick
En lnea
Ejemplo 10:

Teclados Matriciales

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. El
arreglo matricial permite T teclas segn T = L x C donde L es el nmero de lneas y C el
nmero de columnas, la cantidad de pines utilizados son L + C.





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.

Dado que el circuito propuesto se tiene un teclado de 4x4, se tuvo que realizar ciertas
modificaciones al archivo original KBD.c para su correcto funcionamiento.

El archivo nuevo posee el nombre de Tec4x4.c esto para evitar posibles confusiones o
reemplazos con el original. En dicho archivo podemos encontrar las siguientes funciones
para el manejo del Teclado matricial:

kbd_init ();

Debe llamarse antes que ninguna otra funcin del fichero Tec4x4.c.

kbd_getc();

Funcin que retorna el valor presionado en el Teclado, este puede guardado en una variable
de tipo char.

Ejm: Tecla=kbd_getc();

Por defecto, este driver usa el puerto D para establecer a comunicacin entre el Teclado y
el microcontrolador.

Pines utilizados para el Teclado:
B0 D0 -> Columna 1
B1 D1 -> Columna 2
B2 D2 -> Columna 3
B3 D3 -> Columna 4
B4 D4 -> Fila 1
B5 D5 -> Fila 2
B6 D6 -> Fila 3
B7 D7 -> Fila 4

Para utilizar el puerto B es necesario colocar una lnea de cdigo antes del llamado a la
librera Tec4x4.c, dicho cdigo indica en la misma librera Tec4x4.c.

#define use_portb_lcd TRUE // Puerto a utilizar para el LCD
#include Tec4x4.c // Libreria para el manejo del LCD a utilizar

NOTA.- Ojo solo est permitido utilizar los puertos B y D.

Problema: Mostrar en un LCD la te tecla pulsada de un Teclado matricial 4x4.

Recursos a Utilizar: RD (LCD), RB (Teclado 4x4).

El siguiente programa lee el teclado, y espera que un valor sea introducido, si es as, lo
imprime en pantalla y espera a que se suelte el botn para evitar imprimir dos veces.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portb_kbd TRUE // Puerto B, a utilizar para el Teclado
Matricial
#include "Tec4x4.c" // Libreria para el manejo del Teclado
Matricial a utilizar

#define use_portd_lcd TRUE // Puerto D, a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

// FUNCION PRINCIPAL
void main(void){
char c=0; // Variable donde se almacena tecla
pulsada
lcd_init(); // Iniciamos LCD
kbd_init();
lcd_putc('\f'); // Limpiamos LCD
lcd_gotoxy(4,1); // Linea 1 y Columna 6
printf(lcd_putc,"Mikropic");
lcd_gotoxy(1,2); // Linea 2 y Columna 2
printf(lcd_putc,"Tecla Pulsada:");
while(TRUE){ // Bucle infinito
do{ // Espera hasta...
c=kbd_getc();
}while(c==0); //...pulsar una tecla
lcd_putc(c); // Muestra tecla pulsada en lcd
lcd_putc("\b"); // Retrocede una posicion(escribe encima
de la ultima tecla mostrada)
}
}

Ejemplo 10v1: Propongo un cdigo que realiza el mismo proceso pero este es por barrido,
lo bueno sera implementarlo para verificar su correcto funcionamiento.

Este cdigo trabaja bajo la siguiente explicacin. Para leer el teclado se debe preguntar
cada fila, colocando en una fila en particular un 0 y en las otras 1. Si se presiona una tecla
de esa fila, se introduce un 0 al microcontrolador, en otro caso un 1. Al ir verificando la
presencia de un 0 en la bsqueda podemos retornar algn valor diferente si es que no se
ha presionado ninguna tecla. Sino retornar el valor asignado a esa tecla.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#byte PORTB=0x06 // Direccin del PortB

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

#define Col_1 0b11111110
#define Col_2 0b11111101
#define Col_3 0b11111011
#define Col_4 0b11110111

char var=0;

void Teclado(){
PORTB=Col_1;
if(PORTB==0b11101110) var='1';
if(PORTB==0b11011110) var='4';
if(PORTB==0b10111110) var='7';
if(PORTB==0b01111110) var='*';

PORTB=Col_2;
if(PORTB==0b11101101) var='2';
if(PORTB==0b11011101) var='5';
if(PORTB==0b10111101) var='8';
if(PORTB==0b01111101) var='0';

PORTB=Col_3;
if(PORTB==0b11101011) var='3';
if(PORTB==0b11011011) var='6';
if(PORTB==0b10111011) var='9';
if(PORTB==0b01111011) var='#';

PORTB=Col_4;
if(PORTB==0b11100111) var='A';
if(PORTB==0b11010111) var='B';
if(PORTB==0b10110111) var='C';
if(PORTB==0b01110111) var='D';
}

// FUNCION PRINCIPAL
void main(void){
set_tris_b(0xF0); // Definimos Parte alta entrada parte baja
salida
lcd_init(); // Iniciamos LCD
PORTB=0x00;
lcd_putc('\f'); // Limpiamos LCD
lcd_gotoxy(4,1); // Linea 1 y Columna 6
printf(lcd_putc,"Mikropic");
lcd_gotoxy(1,2); // Linea 2 y Columna 2
printf(lcd_putc,"Tecla Pulsada:");
while(TRUE){ // Bucle infinito
Teclado();
lcd_putc(var); // Muestra tecla pulsada en lcd
lcd_putc("\b"); // Retrocede una posicion(escribe encima
de la ultima tecla mostrada)
}
}
ltima modificacin: Mayo 18, 2009, 08:19:03 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el resto."

RE: CURSILLO DE CCS PARA PIC'S (EN CONSTRUCCIN)
Erick
Moderador


Mensajes: 57
Sexo:

o

Re: Cursillo de CCS para PIC's (En Construccin)
Respuesta #16 en: Mayo 11, 2009, 08:05:55
Lectura y escritura de la memoria de datos EEPROM

En la familia de microcontroladores 16F87X tanto la memoria EEPROM de datos como la
memoria de programa FLASH puede ser modificada sin necesidad de utilizar un
programador exterior.

Se dispone de seis registros de SFR para leer y escribir sobre la memoria no voltil, estos
registros son: EECON1, EECON2, EEDATA, EEDATH, EEADR y EEADRH. Para direccionar las
256 posiciones de la memoria EEPROM del PIC16F876 y 16F877 basta con 8 bit, por ello
para escribir o leer solo hacen falta el registro EEADR para direccionar la posicin y el
registro EEDATA para colocar el dato ledo o escrito. Sin embargo para poder escribir o leer
datos en la memoria FLASH que puede tener hasta 8K palabras de 14 bits hacen falta dos
registros para direccionar la posicin de memoria, por ello se utiliza el registro EEADR
concatenado con el registro EEADRH que contiene la parte alta de la palabra de
direccionamiento de memoria. De forma similar se utilizan los registros EEDATA
concatenado con el registro EEADRH que contiene los 6 bit de mayor peso de las palabras
de 14 bits.

Adems para controlar el proceso de lectura y escritura de la memoria EEPROM y FLASH se
dispone de dos registros: el EECON1 y el EECON2.



Lectura de la memoria de datos

Para leer un dato de la EEPROM, el registro EEADR es cargado con la direccin de la
EEPROM donde se encuentra el dato y luego el microcontrolador copia el dato de dicha
posicin a EEDATA. A continuacin hay que poner a 0 el bit EEPGD (EECON1<7>), para
apuntar a la memoria de datos EEPROM. Una vez que se ponga a 1 la bandera RD
(EECON1<0>), el dato estar disponible en el registro EEDATA, donde permanecer hasta
la siguiente escritura o lectura.

Escritura de la memoria de datos

La escritura, que es en realidad una programacin, es ms compleja por razones de
seguridad. Antes de escribir un dato en la EEPROM, debe ponerse a 1 la bandera de
activacin de escritura WR (EECON1<1>). Para transferir el dato desde el registro EEDATA
a la direccin de la EEPROM a la que apunta EEADR, debe ejecutarse una secuencia
obligatoria indicada por el fabricante. Posteriormente, cuando se ha realizado con xito la
operacin de la bandera EEIF (PIR1<7>) se pone a 1. Si no lo hace, el almacenamiento ha
sido incorrecto y no se ha realizado.

Funciones para el manejo de la Eeprom interna en CCS

READ_CALIBRATION(n)
Esta funcin lee "n" posiciones de la memoria de calibracin de un 14000.

Ejemplo:
Cdigo: (c) [Seleccionar]
Fin = read_calibration(16);
READ_EEPROM(address)

Esta funcin lee un byte en la direccin (address) de Eeprom especificada. La direccin
puede ser 0-63.

Ejemplo:
Cdigo: (c) [Seleccionar]
#define
LAST_VOLUME 10
volume = read_EEPROM (LAST_VOLUME );
NOTA.- Segn el manual de CCS lee la ubicacin de memoria de eeprom de datos (8 bits o
16 bit dependiendo del dispositivo).

WRITE_EEPROM(address, value)

Esta funcin escribe un byte de datos en la direccin de memoria EEPROM especificada,
address puede valer 0-63; value es el byte de datos a escribir; Esta funcin puede tardar
varios milisegundos para ejecutarse.

Ejemplo:
Cdigo: (c) [Seleccionar]
#define
LAST_VOLUME 10
volume++;

write_eeprom(LAST_VOLUME,volume);
Preprocesador relevante:

#La direccin de ROM = {lista};

Tambin podemos utilizar una directiva de preprocesador para poner los datos en la
memoria eeprom.

Ejemplo:
Cdigo: (c) [Seleccionar]
#rom 0x1100={1,2,3,4,5,6,7,8}; // Datos a guardar en la EEPROM
Interrupciones relevantes:
INT_EEPROM

Esta es instruccin es utiliza cuando la escritura de la EEPROM est completa por tanto
produce una interrupcin en el microcontrolador a futuro profundizaremos sobre el tema de
las Interrupciones en los microcontroladores PIC y en especifico este caso.

Ejemplo 11:


Con todo lo visto anteriormente ahora podemos hacer algunos ejemplos sencillos.

La memoria de datos EEPROM posee 256 bytes en el PIC16F877A donde puede
almacenar de forma indefinida cualquier dato que se desee retener, ya que estos datos
guardados estarn presentes cuando se apague la alimentacin.

Para poner en prctica la programacin de la memoria EEPROM, y aprovechando que se
conoce ya como mostrar datos en la pantalla LCD, se va a realizar un programa que
permita visualizar los valores en el mismo.

Problema: Guardar una secuencia de datos en la memoria EEPROM del PIC con la directiva
# rom.

Recursos a Utilizar: Memoria EEPROM del PIC y RD (LCD).

En la primera imagen podemos apreciar los datos que se tienen en la memoria EEPROM del
PIC, como podemos ver todos los datos son FF.



Esto es antes de aplicar la lnea de cdigo:
Cdigo: (c) [Seleccionar]
#rom 0x2100={1,2,3,4,5,6,7,8}; // Datos a guardar en la EEPROM
Una vez aplicado el cdigo en nuestro programa tendremos el siguiente cambio en la
memoria EEPROM del PIC, como podemos ver en la siguiente imagen:



Ahora que tenemos los datos guardamos en la EEPROM, visualicmoslo en el LCD.


Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

int i,Datos[8];

// FUNCION PRINCIPAL
void main(void){
//#rom 0x2100={255,255,255,255,255,255,255,255}; // Datos para
restablecer a valores iniciales la EEPROM del PIC
#rom 0x2100={1,2,3,4,5,6,7,8}; // Datos a guardar en la EEPROM del
PIC
lcd_init(); // Iniciamos LCD
lcd_putc('\f'); // Limpiamos LCD
lcd_gotoxy(1,1);
printf(lcd_putc," EEPROM Interna ");
lcd_gotoxy(1,2);
printf(lcd_putc," Foro Mikropic ");
delay_ms(3000);

while(TRUE){
lcd_gotoxy(1,1);
printf(lcd_putc,"DATOS: ");
for(i=0;i<=7;i++){
Datos[i]=read_eeprom(i);
printf(lcd_putc,"%i",Datos[i]);
}
}
}

Ejemplo 11v1: Utilizaremos las funciones read_eeprom() y write_eeprom(), en este caso
vamos a almacenar un mensaje para luego visualizarlo en el LCD.
Cdigo: (c) [Seleccionar]
#include <16F877A.h> // PIC a utilizar
#FUSES XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to
10 mhz for PCD
#FUSES NOWDT // No Watch Dog Timer
#FUSES NOPUT // No Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES NOBROWNOUT // No brownout reset
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or
B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected

#use delay(clock=4000000) // Oscilador a 4MHz

#define use_portd_lcd TRUE // Puerto a utilizar para el LCD
#include <LCD.c> // Libreria para el manejo del LCD a utilizar

// FUNCION PRINCIPAL
void main(void){
int i,c;
char Dato;
char Texto[]=" EEPROM Interna Foro Mikropic ";
lcd_init();
// Cargamos Texto en la EEPROM interna
for(i=0;i<=31;i++){
write_eeprom(i,Texto[i]);
}
while(TRUE){
c=1;
for(i=0;i<=15;i++){
Dato = read_eeprom(i);
lcd_gotoxy(c,1);
printf(lcd_putc,"%c",Dato); // Visualizamos 1ra Lnea en LCD
c++;
}
c=1;
for(i=16;i<=31;i++){
Dato = read_eeprom(i);
lcd_gotoxy(c,2);
printf(lcd_putc,"%c",Dato); // Visualizamos 2da Lnea en LCD
c++;
}
}
}

A continuacin una vista de la EEPROM en el PIC, claramente se ve el texto introducido.


ltima modificacin: Mayo 11, 2009, 08:15:12 por Erick
En lnea
Saludos - Erick

"La imaginacin es ms rica que el lenguaje... sugiere con palabras, la imaginacin podr hacer el resto."