SlideShare una empresa de Scribd logo
1 de 23
Descargar para leer sin conexión
Este proyecto es muy interesante ya que pone
a prueba dos interrupciones por TIMERS al
mismo tiempo. El proyecto consta de:
Cantidad Componente
6 Display de 7 seg (An)
6
1 PIC18F2550
3 Microinterruptores
4
7 Resis 330R
Antes de empezar a programar debemos de
tener algunos criterios definidos.
¿Cómo hacer prender 6 Display con
circuito integrado?
Si usted es un electrónico, recordara que
existen algunos circuitos especialmente para
realizar dicha acción, como es el 7490 que nos
cuenta los pulsos que son ingresado a el y
después empieza a contar en forma binaria.
ste proyecto es muy interesante ya que pone
a prueba dos interrupciones por TIMERS al
El proyecto consta de:
Componente
Display de 7 seg (An)
2N2222A
PIC18F2550
Microinterruptores
Resis 10K
Resis 330R
Antes de empezar a programar debemos de
tener algunos criterios definidos.
hacer prender 6 Display con un solo
Si usted es un electrónico, recordara que
especialmente para
realizar dicha acción, como es el 7490 que nos
cuenta los pulsos que son ingresado a el y
después empieza a contar en forma binaria.
Circuito esquemático de un 7490
El conteo lo hace de 0 a 9, pero esto
que está listo para visualizarse a un display de 7
segmentos, ya que tiene que pasar por un
decodificador para ahora si usar un display de 7
segmentos.
Un ejemplo sencillo para entender este
funcionamiento lo podemos ver en seguida:
Consta de simplemente de un CI 7490 y un
7447, unas cuantas resistencias de 330 ohms y
un display de 7 seg.
Construiremos un circuito que maneje 6
display de 7 segmentos, para Visualizar
el valor de una lectura de ADC.
Circuito esquemático de un 7490
El conteo lo hace de 0 a 9, pero esto no significa
visualizarse a un display de 7
segmentos, ya que tiene que pasar por un
decodificador para ahora si usar un display de 7
Un ejemplo sencillo para entender este
funcionamiento lo podemos ver en seguida:
Consta de simplemente de un CI 7490 y un
7447, unas cuantas resistencias de 330 ohms y
Construiremos un circuito que maneje 6
display de 7 segmentos, para Visualizar
el valor de una lectura de ADC.
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 86
Es una forma muy fácil, pero cuando se trata de
utilizar más de 1 display se vuelve una tarea
muy tediosa, llegando ser no muy complejo
pero demasiado grande para poder
desarrollarlo en poco tiempo, por eso hay
técnicas muy eficientes para ahorrar muchos
circuitos y a la vez hacer más fácil de
desarrollar.
La técnica más usada para usar menos circuitos
y realizar la misma tarea es la Multiplexor, esta
técnica trata de encender cada display en un
periodo de tiempo definido y cada vez que uno
es encendido se da el dato a visualizar y
después apagada para encender el siguiente.
Esta técnica se puede utilizar con lógica TTL
pero la desventaja de usar compuertas,
decodificadores, multiplexores se vuelve un
poco caro, ya que eleva la eficiencia pero a un
costo, que al fin al cabo costara más que hacer
uno tradicional.
Un esquema de ejemplo se puede apreciar
enseguida:
Esquema de dos Display multiplexados
Entonces se llega a una conclusión de que
utilizando lógica TTL es eficiente pero conlleva
un costo.
Entonces para realizar lo misma función y tener
la misma eficiencia pero mucho menor costo,
es utilizar un microcontrolador para que realice
todas las tareas y hasta mas.
Nuestra tarea consiste en usar 6 display de 7
segmentos a la vez, y leer la entrada análoga y
visualizarla en los display.
Se oye una tarea muy tediosa pero los
microcontroladores va ser muy sencillo, ya que
usaremos un PIC18F2550 que es muy eficiente
en todos los aspectos.
Esquema de un contador simple
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 87
Para hacer el Multiplexor con un
microcontrolador es muy sencillo,
simplemente usamos un puerto completo para
visualizar el número y otros pines que
depende de cuantos display se quiera visualizar,
en este caso para llevar a cabo el proyecto se
tiene 6 Display, se usaran 6 pines del
microcontrolador para hacer el switcheo.
Cada 3.33mS surgirá una interrupción por
TIMER0 y cambiara de pin llegando hasta el
máximo que son 6, y así será el ciclo de
Multiplexor.
Como hablamos de que cada 3.33mS que
corresponden a cada display de encendido,
entonces si son 6 tendremos una frecuencia
total en cada uno de ellos de:
݂ =
1
‫݋݀݋݅ݎ݁݌‬ ∗ ܰ݀݅‫ݕ݈ܽ݌ݏ‬
݂ =
1
3.33݉ܵ ∗ 6
≅ 50 ‫ݖܪ‬
Suficiente para desaparecer el parpadeo, para
configurar el TIMER0 se debe de utilizar la
formula:
ܶ‫0ܴܯ‬ = 65535 − ൤
‫݁݉݅ݐ‬ ∗ ܱ‫ܿݏ‬
ሺ4 ∗ ‫ݎ݈ܽܿݏ݁ݎ݌‬ሻ
൨
ܶ‫0ܴܯ‬ = 65535 − ൤
3.33݉ܵ − 8‫ܯ‬ℎ‫ݖ‬
4 ∗ 1
൨
ܶ‫0ܴܯ‬ = 58875
El valor obtenido se debe de cargar cada vez
que surja la interrupción por timer0.
La configuración del timer0 al inicio del nuestro
programa es el siguiente:
Como el Microcontrolador PIC18F2550 cuenta
tan solo de 3 Puerto completo y uno lo vamos a
usar para Mostrar los números en cada display
correspondiente, y otro para hacer el
Multiplexor.
Pero como los pines que están dedicados al USB
no se puede configurar como salida, entonces
perdemos un par de pines, por eso se adopto
por usar solo tres pines del PUERTO C y tres del
PUERTO A.
Para hacer el corrimiento en tales pines se
usara la siguiente lógica de programación:
Se usa una variable ‘flag’ para hacer el cambio
de puerto, cuando el corrimiento del PUERTO C
termine cambia rápidamente al PUERTO A, al
finalizar empezara otra vez el ciclo.
OpenTimer0(TIMER_INT_ON &//Interrupción activada
T0_16BIT &//valor de 16 bit
T0_SOURCE_INT &//oscilador principal
T0_PS_1_1); //Preescalar de 16
if(flag==0){
LATC<<=1;//Recorre un bit a la Izquierda
if(LATC==0){//A recorrido los tres bit?
flag=1; //Cambia de puerto
LATA=0x02;//Empieza en el puerto A
}
}else{
LATA<<=1;//Recorre un bit a la Izquierda
if(LATA>=16){//Ha llegado al limite
flag=0; //Cambia de Puerto
LATC=0x01;//Inicia otra vez el ciclo
}
}
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 88
Ahora bien tenemos 3.33mS de retardo para
poder visualizar el numero en el display
correspondiente, entonces cuando la
interrupción por timer0 termine, regresa al loop
principal, donde colocaremos las
comparaciones de cada pin, para cuando se
cumpla uno de ellos entre al proceso que es
visualizar el numero.
Se usa una variable de tipo array donde
contiene los datos en la memoria ROM, que
corresponde a cada número para mostrar en los
display.
Ahora bien como se desea tener una lectura del
convertidor Análogo-Digital, pero sin
interrumpir el Multiplexor, recuerde que el
microcontrolador hace las tareas línea tras línea
no en forma paralela, si se sabe que estamos
trabajando a una frecuencia 50Hz que para
nosotros es muy rápido, pero a nivel de
procesador es muy lento, ya que podemos
hacer lo que necesitamos en menos de 3.33mS.
Vallamos por pasos debemos de configurar
primero que nada la entrada análoga. Por eso
vamos a usar el PINA0 como una entrada
análoga, 10bit a una tasa de adquisición de 20
Tad, con valor de referencia de la fuente de
alimentación a tierra (+5v, gnd).
Al tener configurado el Convertidor AD,
debemos de configurar el TIMER1 como
temporizador y que surja una interrupción por
desbordamiento cada 100mS, haciendo de que
cada vez que entre a la interrupción por TIMER1
empiece la conversión a análoga-digital, lo
guarde en una
variable de tipo
int al tener
guardado el dato
análogo, se pasa
por un proceso
de conversión de
numero a BCD, esto quiere decir que separara
cada numero para ser guardado en variables,
que solo contenga el numero que debe de
visualizarse en cada display.
Por ejemplo:
Si hemos realizado una
lectura de 1023 que es
el valor máximo de 10-
bit , al pasar por el proceso de conversión de
numero a BCD, tendremos en cuatro variables
de tipo char
M=1
C=0
D=2
U=3
Para hacer este proceso de conversión se usa
una técnica muy sencilla, es hacer una pregunta
antes de entrar al ciclo de restar con relación al
valor tenido.
while(1){
if(LATC==0x01) {LATB=mostrar[0];}//Simplemente Muestra 0
else if(LATC==0x02) {LATB=mostrar[0];}//Simplemente Muestra 0
else if(LATC==0x04) {LATB=mostrar[M];}//Simplemente Muestra Milesimas
else if(LATA==0X02) {LATB=mostrar[C];}//Simplemente Muestra Centecimas
else if(LATA==0X04) {LATB=mostrar[D];}//Simplemente Muestra Decimas
else if(LATA==0X08) {LATB=mostrar[U];}//Simplemente Muestra Unidades
}
const unsigned char
mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,
0b10010010,0b10000011,0b11111000,0b00000000,0b00011000};
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 89
DATO=ReadADC()
;
DATO>=1000?
DATO>=100?
DATO>=10?
DATO>0?
DATO-=1000;
M++;
DATO-=100;
C++;
DATO-=10;
D++;
U=DATO;
U=DATO;
Regresa
al
programa
si
si
si
si
no
no
no
no
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 90
Ahora bien si se desea una interrupción por overflow del TIMER1 se debe de configurar de la siguiente
manera y cargar al timer1 cada vez que surja la interrupción por el valor de:
Cada display debe de tener un transistor para que la corriente no caiga en el pin del microcontrolador y
así hace que el display ilumine un poco más.
Las conexiones de los 7 segmentos se debe de unirse todos y tener un solo
en común, y este será conectado al PUERTO B
del microcontrolador.
Entonces usaremos seis Transistores para
poder manejar los seis display.
En la base del transistor se debe de
conectar una resistencia de 1Kohm
aproximadamente para que limite al
microcontrolador salga más corriente.
Podemos realizar la conexión de todos
los Display y transistores en un solo
Protoboard, dejando el
microcontrolador en otro Protoboard
para poner más adelante mas
circuitería si queremos:
//////////////////////////////////////////////////////////////////////
// Configuración de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer1(TIMER_INT_ON & //Interrupción Desactivada
T1_16BIT_RW & //valor de 16 bit
T1_SOURCE_INT & //Corriente desde el oscilador principal
T1_PS_1_8 & //Preescalar de 8
T1_OSC1EN_OFF &
T1_SYNC_EXT_OFF &
T1_SOURCE_CCP); //Sincronismo desactivado
/*---------------------Fin de Conf. TIMER1--------------------------*/
WriteTimer1(40535);//Valor para tener una interrupción cada 100ms
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 91
Imagen fisica de nuestro Proyecto
Como no tenía un potenciómetro a la mano use una fotoresistencia, para hacer el cambio de Voltaje y
así para poder apreciar el descenso de la lectura por ADC.
Imagen Completa de nuestro Proyecto
Fotoresistencia
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 92
Diagrama a Manejar:
Como podemos notar los microcontroladores nos ahorran pero mucho a desarrollar cosas más
complejas a comparación de usar la lógica TTL de los circuito discretos de la seria 74XXXX, aunque para
empezar se recomienda empezar por lo difícil jeje.
Este circuito utiliza un voltaje total de 5 Volts, para usar mas voltaje y regularlo, siempre es
recomendable usar un regulador de voltaje de 7805, ya que puede regular hasta 24 volts a 5 volts
continuo.
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 93
El programa es el siguiente:
////////////////////////////////////////////////////////
// USO DE ADC Y DISPLAY 7 SEG ////
//Autor: george.manson.69 ////
//Lugar: Mexico ////
//Compilador: HI TECH PIC18 (LITE MODE) ////
////////////////////////////////////////////////////////
#include<htc.h>
/////////////////////////////////////////////////////////////
//Configuracion para trabajar Con oscilador interno de 8Mhz
__CONFIG(1,INTIO & FCMDIS & IESODIS & PLLDIV5 & PLLPOSTDIV2 & CPUDIV1 & USBOSC);
/////////////////////////////////////////////////////////////
__CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BORV45 & WDTPS32K);
__CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN);
__CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);
//////////////////////////////
//Frecuencia FOSC 8Mhz
//////////////////////////////
#define _XTAL_FREQ 8000000
/////////////////////////////
//VARIABLES
/////////////////////////////
const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,
0b10010010,0b10000011,0b11111000,0b00000000,0b00011000};
unsigned int adc;
unsigned char M,C,D,U;
unsigned char flag=0;
/////////////////////////////////////////////////
//Funcion de interrupcion
//Si no se usa simplemente no hacemos nada...
//Esto sirve para direccionar lo los datos
//en un lugar muy cercano al Inicio de la memoria
//de datos
////////////////////////////////////////////////
static void interrupt
isr(void){
/////////////////////////////////////////////////////////////////////////
// INTERRUPCION POT TIMER0 ///
//CADA 3.33mS habra una interrupcion que hara que corra un bit hacia ///
//la IZQUIERDA para encender el siguiente DISPLAY ///
//Cuando surga la interrupcion por TIMER1 no entrara aqui ///
/////////////////////////////////////////////////////////////////////////
if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO INT. POR TIMER0?
if(flag==0){
LATC<<=1; //Recorre un bit a la Izquierda
if(LATC==0){//A recorrido los tres bit?
flag=1; //Cambia de puerto
LATA=0x02;//Empieza en el puerto A
}
}else{
LATA<<=1;//Recorre un bit a la Izquierda
if(LATA>=16){//Ha llegado al limite
flag=0; //Cambia de Puerto
LATC=0x01;//Inicia otra vez el ciclo
}
}
TMR0IF=0;//Reset flag
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 94
WriteTimer0(58875);//carga nuevamente el valor
}
/*---------------------Fin de INT. TIMER0---------------------------*/
//////////////////////////////////////////////////////////////////////
// INTERRUPCION POT TIMER1 ///
//Al entrar aqui, inicializa las variables a cero desactiva ///
//Interrupcion por TIMER0 y empieza el convertidor ///
//Cuando tengamos el valor analogo, debemos de sacar las Milesimas ///
//Centecimas, Decimas y Unidades. ///
//Esta interrupcion surgira cada 100mS ///
//////////////////////////////////////////////////////////////////////
if(TMR1IF){
M=C=D=U=0;//Inicializa variables
TMR0IE=0; //Desactiva INT por timer0
ConvertADC();//Empieza la conversion Analoga
while(BusyADC());//Ha terminado?
adc=ReadADC();//Lee el dato
while(adc>=1000){//Es mayor de 1000?
adc-=1000; //Resta 1000
M++; //Incrementa 1
}
while(adc>=100){ //Es mayor de 100?
adc-=100; //Resta 100
C++; //Incrementa 1
}
while(adc>=10){ //Es mayor de 10?
adc-=10; //resta 10
D++; //Incrementa 1
}
if(adc>0){ //Es mayor de 0?
U=adc; //Toma el valor ultimo
}else{
U=0; //Sino,valor a Cero
}
TMR1IF=0; //Reset timer1
TMR0IE=1; //Activa Timer0
WriteTimer1(40535);//Carga el valor nuevamente.
}
/*---------------------Fin de INT. TIMER1---------------------------*/
}
//////////////////////////////
//FUNCION PRINCIPAL
//////////////////////////////
void main(void){
OSCCON=0x70;
NOP();NOP();NOP();NOP();
//////////////////////////////////////////////////////////////////////
// Configuracion de Puertos ///
//////////////////////////////////////////////////////////////////////
TRISB=0x00;//Puerto B como salida
TRISC=0x00;//Puerto C como salida
TRISA=0x01;//Pin A0 como entrada analoga
CMCON=0x07;
/*---------------------Fin de Conf. Puertos-------------------------*/
//////////////////////////////////////////////////////////////////////
// Configuracion de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer0(TIMER_INT_ON & //Interrupcion activada
T0_16BIT & //valor de 16 bit
T0_SOURCE_INT & //Corriente desde el oscilador principal
T0_PS_1_1); //Preescalar de 16
/*---------------------Fin de Conf. TIMER1--------------------------*/
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 95
//////////////////////////////////////////////////////////////////////
// Configuracion de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer1(TIMER_INT_ON & //Interrupcion Desactivada
T1_16BIT_RW & //valor de 16 bit
T1_SOURCE_INT & //Corriente desde el oscilador principal
T1_PS_1_8 & //Preescalar de 8
T1_OSC1EN_OFF &
T1_SYNC_EXT_OFF &
T1_SOURCE_CCP); //Sincronismo desactivado
/*---------------------Fin de Conf. TIMER1--------------------------*/
//////////////////////////////////////////////////////////////////////
// Configuracion de ADC ///
//////////////////////////////////////////////////////////////////////
OpenADC(ADC_FOSC_RC &//Internal Oscilador Interno
ADC_RIGHT_JUST &//Justificacion a la derecha (10-bit)
ADC_20_TAD, //Tiempo de Adquisicion (TAD)
ADC_CH0 &//CANAL 3 analogo
ADC_INT_OFF &//Interrupcion por ADC APAGDO
ADC_REF_VDD_VSS, //V+ref=VCC,V-ref=GND
ADC_CH0); //AN4=analogo,resto digitales
/*---------------------Fin de Conf. ADC------------------------------*/
INTCON|=0b00100000;//Para activar interrupcion por timer0
WriteTimer0(58875);//Valor para tener una interrupcion cada 3.33 mS
WriteTimer1(40535);//Valor para tener una interrupcion cada 100ms
GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS
PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICOS
PORTB=0x00;//Inicializa PUERTO B como apagado
LATC=0x01;
LATA=0x00;
while(1){
if(LATC==0x01) {LATB=mostrar[0];}//Simplemente Muestra 0
else if(LATC==0x02) {LATB=mostrar[0];}//Simplemente Muestra 0
else if(LATC==0x04) {LATB=mostrar[M];}//Simplemente Muestra Milesimas
else if(LATA==0X02) {LATB=mostrar[C];}//Simplemente Muestra Centecimas
else if(LATA==0X04) {LATB=mostrar[D];}//Simplemente Muestra Decimas
else if(LATA==0X08) {LATB=mostrar[U];}//Simplemente Muestra Unidades
}
}
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 96
Para seguir con nuestro circuito ya armado, y
no desperdiciar más cables, se propone realizar
un contador de eventos, en este caso se tiene
en lugar de una entrada análoga, una entrada
digital, que cada vez que se detecte un pulso
este empiece a incrementar las variables que se
mostraran en los display.
El programa a manejar es muy parecido del
anterior, ya que solo se modifico, dos cosas.
Una solo se removió la opción del convertidor
análogo digital dejando solo entradas digitales
en el PINA0. Dos se quito la lógica de
programación del convertidor de número a BCD
en la interrupción y se modifico.
Ahora como hemos de realizar un contador con
un push botón, hay que tener en cuenta
algunos aspectos, cada vez que presionamos el
botón puede surgir los rebotes, se le dice
rebotes de corriente, ya que al presionar el
botón, abra picos de voltaje que pueden
producir información de pulsaciones erróneas,
causando que cuente más de lo previsto.
Para la solución de este problema se adopto por
realizar lo siguiente: Crear una variable que
cuente 3 interrupción por timer1 que
corresponden a una temporización de 300mS, al
llegar al máximo de pulsos, pregunta si se ha
presionado el botón, si es así, incrementara la
variable U, cuando dicha variable llega al valor
máximo que es 10, se resetea e incrementa la
siguiente variable que es D y así sucesivamente
hasta llegar a la variable M.
El botón puede ser un pulsador, conectado a
+5v y el otro extremo a una resistencia de 10k
hacia tierra.
Siguiendo con nuestro
circuito armado de 6
display. Para contar
eventos con un botón.
ET
Sin tiempo
Con tiempo
antirepote
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 97
Podemos apreciar el diagrama a manejar:
El Programa que contiene el microcontrolador es el siguiente:
////////////////////////////////////////////////////////
// Contador ////
//Autor: george.manson.69 ////
//Lugar: Mexico ////
//Compilador: HI TECH PIC18 (LITE MODE) ////
////////////////////////////////////////////////////////
#include<htc.h>
/////////////////////////////////////////////////////////////
//Configuracion para trabajar Con oscilador interno de 8Mhz
__CONFIG(1,INTIO & FCMDIS & IESODIS & PLLDIV5 & PLLPOSTDIV2 & CPUDIV1 & USBOSC);
/////////////////////////////////////////////////////////////
__CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BORV45 & WDTPS32K);
__CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN);
__CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);
//////////////////////////////
//Frecuencia FOSC 8Mhz
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 98
//////////////////////////////
#define _XTAL_FREQ 8000000
/////////////////////////////
//VARIABLES
/////////////////////////////
const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,
0b10010010,0b10000011,0b11111000,0b00000000,0b00011000};
unsigned int adc;
unsigned char M,C,D,U;
unsigned char flag=0;
unsigned char var;
/////////////////////////////////////////////////
//Funcion de interrupcion
//Si no se usa simplemente no hacemos nada...
//Esto sirve para direccionar lo los datos
//en un lugar muy cercano al Inicio de la memoria
//de datos
////////////////////////////////////////////////
static void interrupt
isr(void){
/////////////////////////////////////////////////////////////////////////
// INTERRUPCION POT TIMER0 ///
//CADA 3.33mS habra una interrupcion que hara que corra un bit hacia ///
//la IZQUIERDA para encender el siguiente DISPLAY ///
//Cuando surga la interrupcion por TIMER1 no entrara aqui ///
/////////////////////////////////////////////////////////////////////////
if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO INT. POR TIMER0?
if(flag==0){
LATC<<=1; //Recorre un bit a la Izquierda
if(LATC==0){//A recorrido los tres bit?
flag=1; //Cambia de puerto
LATA=0x02;//Empieza en el puerto A
}
}else{
LATA<<=1;//Recorre un bit a la Izquierda
if(LATA>=16){//Ha llegado al limite
flag=0; //Cambia de Puerto
LATC=0x01;//Inicia otra vez el ciclo
}
}
TMR0IF=0;//Reset flag
WriteTimer0(58875);//carga nuevamente el valor
}
/*---------------------Fin de INT. TIMER0---------------------------*/
//////////////////////////////////////////////////////////////////////
// INTERRUPCION POT TIMER1 ///
//Cheka cada 300mS el switch, si esta presionado suma 1 ///
//A la variable que corresponda.
//////////////////////////////////////////////////////////////////////
if(TMR1IF){
TMR0IE=0; //Desactiva INT por timer0
var++;
if(var>3){
var=0;
if(RA0){
U++;
if(U>=10){
U=0;
D++;
if(D>=10){
D=0;
C++;
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 99
if(C>=10){
C=0;
M++;
if(M>=10){
M=0;
}
}
}
}
}
}
TMR1IF=0; //Reset timer1
TMR0IE=1; //Activa Timer0
WriteTimer1(41035);//Valor para tener una interrupcion cada 100ms
}
}
/*---------------------Fin de INT. TIMER1---------------------------*/
//////////////////////////////
//FUNCION PRINCIPAL
//////////////////////////////
void main(void){
OSCCON=0x70;
NOP();NOP();NOP();NOP();
//////////////////////////////////////////////////////////////////////
// Configuración de Puertos ///
//////////////////////////////////////////////////////////////////////
TRISB=0x00;//Puerto B como salida
TRISC=0x00;//Puerto C como salida
TRISA=0x01;//Pin A0 como entrada digital
ADCON1=0x0F;
CMCON=0x07;
/*---------------------Fin de Conf. Puertos-------------------------*/
//////////////////////////////////////////////////////////////////////
// Configuración de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer0(TIMER_INT_ON & //Interrupción activada
T0_16BIT & //valor de 16 bit
T0_SOURCE_INT & //Corriente desde el oscilador principal
T0_PS_1_1); //Preescalar de 16
/*---------------------Fin de Conf. TIMER1--------------------------*/
//////////////////////////////////////////////////////////////////////
// Configuración de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer1(TIMER_INT_ON & //Interrupción Desactivada
T1_16BIT_RW & //valor de 16 bit
T1_SOURCE_INT & //Corriente desde el oscilador principal
T1_PS_1_8 & //Preescalar de 8
T1_OSC1EN_OFF &
T1_SYNC_EXT_OFF &
T1_SOURCE_CCP); //Sincronismo desactivado
/*---------------------Fin de Conf. TIMER1--------------------------*/
INTCON|=0b00100000;//Para activar interrupción por timer0
WriteTimer0(58875);//Valor para tener una interrupción cada 3.33 mS
WriteTimer1(41035);//Valor para tener una interrupción cada 100ms
GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS
PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICOS
PORTB=0x00; //Inicializa PUERTO B como apagado
LATC=0x01;
LATA=0x00;
while(1){
if(LATC==0x01) {LATB=mostrar[0];}//Simplemente Muestra 0
else if(LATC==0x02) {LATB=mostrar[0];}//Simplemente Muestra 0
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 100
else if(LATC==0x04) {LATB=mostrar[M];}//Simplemente Muestra Milesimas
else if(LATA==0X02) {LATB=mostrar[C];}//Simplemente Muestra Centecimas
else if(LATA==0X04) {LATB=mostrar[D];}//Simplemente Muestra Decimas
else if(LATA==0X08) {LATB=mostrar[U];}//Simplemente Muestra Unidades
}
}
Algunas imágenes del Contador:
Recuerde siempre alimentar al circuito coin un voltaje de 5 Volts.
Boton
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 101
Algunas veces en nuestra vida como
electrónicos, o simplemente como hobbystas,
se nos pasa por la mente realizar un reloj con
display, como podemos realizarlos de distintas
formas como usando lógica TTL, o pasando ya a
usar cosas más avanzadas como los
microcontroladores, pues ¿Porque no
realizarlo?, ya que tenemos el circuito armado
con los 6 display, ahorraremos mucho tiempo
para desarrollarlo, simplemente necesitamos
colocar 3 pulsadores y realizar otra tipo de
lógica de programación en nuestro PIC y hemos
realizado nuestro reloj.
La idea es tener tres pulsadores de cual un
servirá para controlar los demás.
Por ejemplo llamemos a uno como SET, a otro
botón como HORAS, y el último como
MINUTOS, cuando el botón SET no esté
presionado, el microcontrolador no hará caso
los botones de HORAS y MINUTOS, pero si
tenemos lo contrario que el botón SET este
presionado mientras este así, podemos cambiar
o presionar los botones HORAS y MINUTOS.
Teniendo ya establecido las condiciones del los
pulsadores ya podemos empezar a programar,
lo único que cambiaremos de del programa
anterior es algunas variables y solo
cambiaremos la función de interrupción del
TIMER1, ya que la interrupción por TIMER0 es
ya es de ley tenerla. Lo que cambiaremos de la
interrupción del TIMER1 es como se debe de
comportar al presionar un botón, pero a la vez
no interrumpir el proceso de contar los
segundos ya que si hacemos que los pulsadores
corten la sincronía del tiempo, podemos
adelantar o retrasar nuestro reloj.
Como sabemos que la configuración de
interrupción del TIMER1 surge cada 100mS
teniendo que realizar 10 veces dicha
interrupción para tener aproximadamente un
segundo, crearemos una variable que cuente las
interrupciones y al llegar a la decima
interrupción sume a otra variable +1.
Se han creado 6 variables para que cada una de
ellas corresponda a cada display, por ejemplo:
H2 H1 M2 M1 S2 S1
La variable que se le sumara uno cuando las 10
interrupciones pasen, es “S1” ya que esta
variable es la que corresponde al primer display
de Derecha a Izquierda, cuando la variable “S1”
llegue al máximo en este caso a 10, “S1=0” y
suma uno a la siguiente variable “S2” pero esta
Aun siguiendo con nuestro
circuito armado para realizar
un reloj simple.
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 102
variable no debe de llegar hasta 10 sino a 6, ya
que debemos de contar solo 60 segundos,
cuando la variable “S2” llegue a 6 se volverá a
cero, y sumara uno a la variable M1, y así
sucesivamente pero si deseamos realizar que
las horas solo cuente hasta 24, se realiza la
siguiente lógica:
Ya tenemos la lógica de cómo realizar la
sumatoria de las variables con respecto al
tiempo, pero aun no tenemos como poner la
lógica de introducir los botones sin afectar el
conteo de segundos y aparte de no afectar con
rebotes al presionar dicho botón.
Bueno para solucionar los rebotes al presionar
cualquier botón, se debe de esperar 300mS
para que entre o compare si se ha presionado el
botón de SET, se usa la comparación:
If((var%3)==1);
Esta comparación hace que cada 300mS entre y
vea que si se ha presionado el botón de SET, ya
que:
1%3 No es múltiplo de tres entrega 0
2%3 No es múltiplo de tres entrega 0
3%3 Es múltiplo de tres entrega 1
4%3 No es múltiplo de tres entrega 0
5%3 No es múltiplo de tres entrega 0
6%3 3 Es múltiplo de tres entrega 1
….
Al entrar a esta comparación ahora veremos si
se ha presionado el botón SET
Ahora si cada vez que pase 300mS se podrá
checar el pulsador SET pero sin afectar el
tiempo de los segundos.
Pero recuerde que los segundos pueden ser
afectados a la acumulación de instrucciones de
nuestro programa porque recuerde que el
lenguaje C esta hecho por macros es decir que
contiene líneas de lenguaje ensamblador pero
todo el conjunto de una sola instrucción está
dirigido simplemente a una línea en C.
Por ejemplo:
TRISB=0x00 ;No se ejecuta en un ciclo maquina
sino lo transformamos a lo que es realmente en
ensamblador y tenemos que:
Bcf STATUS,5
Movlw 0x00
Movwf TRISB
H1++;
if(H1==10 && H2<2){
H1=0;
H2++;
}else if(H1==4 && H2==2){
H2=H1=0;
}
else if((var%3)==1){
if(SET){
if(HORAS){
H1++;
if(H1==10 && H2<2){
H1=0;
H2++;
}else if(H1==4 && H2==2){
H2=H1=0;
}
}
if(MINUTOS){
M1++;
if(M1>=10){
M1=0;
M2++;
if(M2>=6){
M2=0;
}
}
}
}
}
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 103
En realidad se ejecuta en tres ciclos maquina, esto lo menciono para que tenga una idea de cómo debe
de optimizar los códigos para que realice lo mismo pero consuma menos tiempo maquina.
Y nuestro proyecto es afectado por los términos anteriores, y podría retrasarse unos segundos cada
cuatro u ocho días, se recomienda realizar una buena lógica de programación para solucionar o hacer
mucho más pequeño el lapso de tiempo perdido.
El circuito a Manejar es el siguiente;
Como vemos no se ha cambiado en absoluto la configuración de los transistores, ni los display solo
hemos puesto 2 pulsadores extras para cambiar la HORA y MINUTOS.
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 104
El programa se muestra a continuación:
////////////////////////////////////////////////////////
// Contador ////
//Autor: george.manson.69 ////
//Lugar: Mexico ////
//Compilador: HI TECH PIC18 (LITE MODE) ////
////////////////////////////////////////////////////////
#include<htc.h>
/////////////////////////////////////////////////////////////
//Configuracion para trabajar Con oscilador interno de 8Mhz
__CONFIG(1,INTIO & FCMDIS & IESODIS & PLLDIV5 & PLLPOSTDIV2 & CPUDIV1 & USBOSC);
/////////////////////////////////////////////////////////////
__CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BORV45 & WDTPS32K);
__CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN);
__CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);
//////////////////////////////
//Frecuencia FOSC 8Mhz
//////////////////////////////
#define _XTAL_FREQ 8000000
//////////////////////////////
//Definiciones Globales
//////////////////////////////
#define SET RA0
#define HORAS RC6
#define MINUTOS RC7
/////////////////////////////
//VARIABLES
/////////////////////////////
const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,
0b10010010,0b10000011,0b11111000,0b00000000,0b00011000};
unsigned int adc;
unsigned char H2,H1,M2,M1,S2,S1;
unsigned char flag=0;
unsigned char var;
/////////////////////////////////////////////////
//Funcion de interrupcion
//Si no se usa simplemente no hacemos nada...
//Esto sirve para direccionar lo los datos
//en un lugar muy cercano al Inicio de la memoria
//de datos
////////////////////////////////////////////////
static void interrupt
isr(void){
/////////////////////////////////////////////////////////////////////////
// INTERRUPCION POT TIMER0 ///
//CADA 3.33mS habra una interrupcion que hara que corra un bit hacia ///
//la IZQUIERDA para encender el siguiente DISPLAY ///
//Cuando surga la interrupcion por TIMER1 no entrara aqui ///
/////////////////////////////////////////////////////////////////////////
if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO INT. POR TIMER0?
if(flag==0){
LATC<<=1; //Recorre un bit a la Izquierda
if(LATC==0){//A recorrido los tres bit?
flag=1; //Cambia de puerto
LATA=0x02;//Empieza en el puerto A
}
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 105
}else{
LATA<<=1;//Recorre un bit a la Izquierda
if(LATA>=16){//Ha llegado al limite
flag=0; //Cambia de Puerto
LATC=0x01;//Inicia otra vez el ciclo
}
}
TMR0IF=0;//Reset flag
WriteTimer0(58875);//carga nuevamente el valor
}
/*---------------------Fin de INT. TIMER0---------------------------*/
//////////////////////////////////////////////////////////////////////
// INTERRUPCION POT TIMER1 ///
//Cheka cada 300mS el switch, si esta presionado suma 1 ///
//A la variable que corresponda.
//////////////////////////////////////////////////////////////////////
if(TMR1IF){
TMR0IE=0; //Desactiva INT por timer0
/*CODIGO PRINCIPAL*/
//Segundos jamas se interrupe//
var++;
if(var>=10){
var=0;
S1++;
if(S1==10){
S1=0;
S2++;
if(S2==6){
S2=0;
M1++;
if(M1==10){
M1=0;
M2++;
if(M2==6){
M2=0;
H1++;
if(H1==10 && H2<2){
H1=0;
H2++;
}else if(H1==4 && H2==2){
H2=H1=0;
}
}
}
}
}
}
else if((var%3)==1){
if(SET){
if(HORAS){
H1++;
if(H1==10 && H2<2){
H1=0;
H2++;
}else if(H1==4 && H2==2){
H2=H1=0;
}
}
if(MINUTOS){
M1++;
if(M1>=10){
M1=0;
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 106
M2++;
if(M2>=6){
M2=0;
}
}
}
}
}
/*******************/
TMR1IF=0; //Reset timer1
TMR0IE=1; //Activa Timer0
WriteTimer1(41900);//Valor para tener una interrupcion cada 100ms
}
}
/*---------------------Fin de INT. TIMER1---------------------------*/
//////////////////////////////
//FUNCION PRINCIPAL
//////////////////////////////
void main(void){
OSCCON=0x70;
NOP();NOP();NOP();NOP();
//////////////////////////////////////////////////////////////////////
// Configuracion de Puertos ///
//////////////////////////////////////////////////////////////////////
TRISB=0x00;//Puerto B como salida
TRISC=0xD0;//Puerto C como salida
TRISA=0x01;//Pin A0 como entrada digital
ADCON1=0x0F;
CMCON=0x07;
/*---------------------Fin de Conf. Puertos-------------------------*/
//////////////////////////////////////////////////////////////////////
// Configuracion de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer0(TIMER_INT_ON & //Interrupcion activada
T0_16BIT & //valor de 16 bit
T0_SOURCE_INT & //Corriente desde el oscilador principal
T0_PS_1_1); //Preescalar de 16
/*---------------------Fin de Conf. TIMER1--------------------------*/
//////////////////////////////////////////////////////////////////////
// Configuracion de Timer1 ///
//////////////////////////////////////////////////////////////////////
OpenTimer1(TIMER_INT_ON & //Interrupcion Desactivada
T1_16BIT_RW & //valor de 16 bit
T1_SOURCE_INT & //Corriente desde el oscilador principal
T1_PS_1_8 & //Preescalar de 8
T1_OSC1EN_OFF &
T1_SYNC_EXT_OFF &
T1_SOURCE_CCP); //Sincronismo desactivado
/*---------------------Fin de Conf. TIMER1--------------------------*/
INTCON|=0b00100000;//Para activar interrupcion por timer0
WriteTimer0(58875);//Valor para tener una interrupcion cada 3.33 mS
WriteTimer1(41900);//Valor para tener una interrupcion cada 100ms
GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS
PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICOS
PORTB=0x00;//Inicializa PUERTO B como apagado
LATC=0x01;
LATA=0x00;
while(1){
if(LATC==0x01) {LATB=mostrar[H2];}//Simplemente Muestra 0
else if(LATC==0x02) {LATB=mostrar[H1];}//Simplemente Muestra 0
else if(LATC==0x04) {LATB=mostrar[M2];}//Simplemente Muestra Milesimas
else if(LATA==0X02) {LATB=mostrar[M1];}//Simplemente Muestra Centecimas
[PROYECTO #1] 13 de enero de 2011
Usando Display de 7 segmentos Página 107
else if(LATA==0X04) {LATB=mostrar[S2];}//Simplemente Muestra Decimas
else if(LATA==0X08) {LATB=mostrar[S1];}//Simplemente Muestra Unidades
}
}
Algunas fotos del Reloj:
Foto de reloj
SET

Más contenido relacionado

La actualidad más candente

Curso de microcontroladores capitulo 03
Curso de microcontroladores capitulo 03Curso de microcontroladores capitulo 03
Curso de microcontroladores capitulo 03Hamiltonn Casallas
 
Curso de microcontroladores capitulo 06
Curso de microcontroladores capitulo 06Curso de microcontroladores capitulo 06
Curso de microcontroladores capitulo 06Hamiltonn Casallas
 
Curso de microcontroladores capitulo 07
Curso de microcontroladores capitulo 07Curso de microcontroladores capitulo 07
Curso de microcontroladores capitulo 07Hamiltonn Casallas
 
Curso de microcontroladores capitulo 04
Curso de microcontroladores capitulo 04Curso de microcontroladores capitulo 04
Curso de microcontroladores capitulo 04Hamiltonn Casallas
 
Curso de microcontroladores capitulo 08
Curso de microcontroladores capitulo 08Curso de microcontroladores capitulo 08
Curso de microcontroladores capitulo 08Hamiltonn Casallas
 
Curso de microcontroladores capitulo 02
Curso de microcontroladores capitulo 02Curso de microcontroladores capitulo 02
Curso de microcontroladores capitulo 02Hamiltonn Casallas
 
Curso Micro Tema 1
Curso Micro Tema 1Curso Micro Tema 1
Curso Micro Tema 1Luis Zurita
 
Curso de microcontroladores capitulo 01
Curso de microcontroladores capitulo 01Curso de microcontroladores capitulo 01
Curso de microcontroladores capitulo 01Hamiltonn Casallas
 
Curso de microcontroladores capitulo 05
Curso de microcontroladores capitulo 05Curso de microcontroladores capitulo 05
Curso de microcontroladores capitulo 05Hamiltonn Casallas
 
Curso de microcontroladores capitulo 12
Curso de microcontroladores capitulo 12Curso de microcontroladores capitulo 12
Curso de microcontroladores capitulo 12Hamiltonn Casallas
 
programacion con microcontrolador pic 16f84
programacion con microcontrolador pic 16f84programacion con microcontrolador pic 16f84
programacion con microcontrolador pic 16f84guestf09168b
 
Curso de microcontroladores capitulo 09
Curso de microcontroladores capitulo 09Curso de microcontroladores capitulo 09
Curso de microcontroladores capitulo 09Hamiltonn Casallas
 

La actualidad más candente (20)

Proyecto4
Proyecto4Proyecto4
Proyecto4
 
Adc y usart pic16 f887
Adc y usart pic16 f887Adc y usart pic16 f887
Adc y usart pic16 f887
 
Taxímetro con Pic16F887
Taxímetro con Pic16F887Taxímetro con Pic16F887
Taxímetro con Pic16F887
 
Ejemplos pic c
Ejemplos pic cEjemplos pic c
Ejemplos pic c
 
Micro2 tema 5
Micro2 tema 5Micro2 tema 5
Micro2 tema 5
 
Curso de microcontroladores capitulo 03
Curso de microcontroladores capitulo 03Curso de microcontroladores capitulo 03
Curso de microcontroladores capitulo 03
 
PROYECTOS CON PIC 16F84
PROYECTOS CON PIC 16F84PROYECTOS CON PIC 16F84
PROYECTOS CON PIC 16F84
 
Curso de microcontroladores capitulo 06
Curso de microcontroladores capitulo 06Curso de microcontroladores capitulo 06
Curso de microcontroladores capitulo 06
 
Curso de microcontroladores capitulo 07
Curso de microcontroladores capitulo 07Curso de microcontroladores capitulo 07
Curso de microcontroladores capitulo 07
 
Curso de microcontroladores capitulo 04
Curso de microcontroladores capitulo 04Curso de microcontroladores capitulo 04
Curso de microcontroladores capitulo 04
 
Curso de microcontroladores capitulo 08
Curso de microcontroladores capitulo 08Curso de microcontroladores capitulo 08
Curso de microcontroladores capitulo 08
 
Curso de microcontroladores capitulo 02
Curso de microcontroladores capitulo 02Curso de microcontroladores capitulo 02
Curso de microcontroladores capitulo 02
 
Curso Micro Tema 1
Curso Micro Tema 1Curso Micro Tema 1
Curso Micro Tema 1
 
Micro2 tema 3
Micro2 tema 3Micro2 tema 3
Micro2 tema 3
 
Curso de microcontroladores capitulo 01
Curso de microcontroladores capitulo 01Curso de microcontroladores capitulo 01
Curso de microcontroladores capitulo 01
 
Curso de microcontroladores capitulo 05
Curso de microcontroladores capitulo 05Curso de microcontroladores capitulo 05
Curso de microcontroladores capitulo 05
 
Curso de microcontroladores capitulo 12
Curso de microcontroladores capitulo 12Curso de microcontroladores capitulo 12
Curso de microcontroladores capitulo 12
 
programacion con microcontrolador pic 16f84
programacion con microcontrolador pic 16f84programacion con microcontrolador pic 16f84
programacion con microcontrolador pic 16f84
 
Curso de microcontroladores capitulo 09
Curso de microcontroladores capitulo 09Curso de microcontroladores capitulo 09
Curso de microcontroladores capitulo 09
 
Micro2 tema 1
Micro2 tema 1Micro2 tema 1
Micro2 tema 1
 

Similar a Control 6 Display 7 Seg. Lectura ADC PIC18F2550

Tutorial proton part 4
Tutorial proton part 4Tutorial proton part 4
Tutorial proton part 4dar851112
 
Arduino: Reporte de diseño controlador acuario con Arduino
Arduino: Reporte de diseño controlador acuario con ArduinoArduino: Reporte de diseño controlador acuario con Arduino
Arduino: Reporte de diseño controlador acuario con ArduinoSANTIAGO PABLO ALBERTO
 
Informe N°2-Microcontroladores
Informe N°2-MicrocontroladoresInforme N°2-Microcontroladores
Informe N°2-MicrocontroladoresOmar Ruiz
 
26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial
26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial
26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricialGabriel Bravo Rojas
 
Lógica cableada y Lógica programable - Automatización Industrial
Lógica cableada y Lógica programable - Automatización IndustrialLógica cableada y Lógica programable - Automatización Industrial
Lógica cableada y Lógica programable - Automatización IndustrialUniversidad Politécnica de Chiapas
 
Microcontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltosMicrocontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltosmarco calderon layme
 
Proyecto micro
Proyecto microProyecto micro
Proyecto microjhompix
 
Lab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdfLab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdfsopitamani1
 
Microcontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladoresMicrocontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladoresSANTIAGO PABLO ALBERTO
 
Reloj digital para casa o coche
Reloj digital para casa o cocheReloj digital para casa o coche
Reloj digital para casa o cocheCofer1732
 
Monografia contador digital
Monografia contador digitalMonografia contador digital
Monografia contador digitalJuanito Edgar
 

Similar a Control 6 Display 7 Seg. Lectura ADC PIC18F2550 (20)

Tutorial proton part 4
Tutorial proton part 4Tutorial proton part 4
Tutorial proton part 4
 
Arduino: Reporte de diseño controlador acuario con Arduino
Arduino: Reporte de diseño controlador acuario con ArduinoArduino: Reporte de diseño controlador acuario con Arduino
Arduino: Reporte de diseño controlador acuario con Arduino
 
Informe N°2-Microcontroladores
Informe N°2-MicrocontroladoresInforme N°2-Microcontroladores
Informe N°2-Microcontroladores
 
26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial
26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial
26176947 tutorial-v-escritura-en-lcd-usando-teclado-matricial
 
Lógica cableada y Lógica programable - Automatización Industrial
Lógica cableada y Lógica programable - Automatización IndustrialLógica cableada y Lógica programable - Automatización Industrial
Lógica cableada y Lógica programable - Automatización Industrial
 
Microcontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltosMicrocontroladores - Configuración de puertos, bucles y saltos
Microcontroladores - Configuración de puertos, bucles y saltos
 
Practica7 transferencia registro
Practica7 transferencia registroPractica7 transferencia registro
Practica7 transferencia registro
 
Informe contador mod20
Informe contador mod20Informe contador mod20
Informe contador mod20
 
Tutorial ii proyectos en basic proton
Tutorial ii   proyectos en basic protonTutorial ii   proyectos en basic proton
Tutorial ii proyectos en basic proton
 
Proyecto micro
Proyecto microProyecto micro
Proyecto micro
 
Atmel
AtmelAtmel
Atmel
 
Lab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdfLab# 2 - Temporizador.pdf
Lab# 2 - Temporizador.pdf
 
Los encoders y el plc
Los encoders y el plcLos encoders y el plc
Los encoders y el plc
 
Logica Combinacional
Logica CombinacionalLogica Combinacional
Logica Combinacional
 
Microcontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladoresMicrocontroladores: Fundamentos de microprocesadores y microcontroladores
Microcontroladores: Fundamentos de microprocesadores y microcontroladores
 
Reloj digital para casa o coche
Reloj digital para casa o cocheReloj digital para casa o coche
Reloj digital para casa o coche
 
Monografia contador digital
Monografia contador digitalMonografia contador digital
Monografia contador digital
 
Niple diapopsitiva
Niple   diapopsitivaNiple   diapopsitiva
Niple diapopsitiva
 
Niple diapopsitiva
Niple   diapopsitivaNiple   diapopsitiva
Niple diapopsitiva
 
Niple diapopsitiva
Niple   diapopsitivaNiple   diapopsitiva
Niple diapopsitiva
 

Control 6 Display 7 Seg. Lectura ADC PIC18F2550

  • 1. Este proyecto es muy interesante ya que pone a prueba dos interrupciones por TIMERS al mismo tiempo. El proyecto consta de: Cantidad Componente 6 Display de 7 seg (An) 6 1 PIC18F2550 3 Microinterruptores 4 7 Resis 330R Antes de empezar a programar debemos de tener algunos criterios definidos. ¿Cómo hacer prender 6 Display con circuito integrado? Si usted es un electrónico, recordara que existen algunos circuitos especialmente para realizar dicha acción, como es el 7490 que nos cuenta los pulsos que son ingresado a el y después empieza a contar en forma binaria. ste proyecto es muy interesante ya que pone a prueba dos interrupciones por TIMERS al El proyecto consta de: Componente Display de 7 seg (An) 2N2222A PIC18F2550 Microinterruptores Resis 10K Resis 330R Antes de empezar a programar debemos de tener algunos criterios definidos. hacer prender 6 Display con un solo Si usted es un electrónico, recordara que especialmente para realizar dicha acción, como es el 7490 que nos cuenta los pulsos que son ingresado a el y después empieza a contar en forma binaria. Circuito esquemático de un 7490 El conteo lo hace de 0 a 9, pero esto que está listo para visualizarse a un display de 7 segmentos, ya que tiene que pasar por un decodificador para ahora si usar un display de 7 segmentos. Un ejemplo sencillo para entender este funcionamiento lo podemos ver en seguida: Consta de simplemente de un CI 7490 y un 7447, unas cuantas resistencias de 330 ohms y un display de 7 seg. Construiremos un circuito que maneje 6 display de 7 segmentos, para Visualizar el valor de una lectura de ADC. Circuito esquemático de un 7490 El conteo lo hace de 0 a 9, pero esto no significa visualizarse a un display de 7 segmentos, ya que tiene que pasar por un decodificador para ahora si usar un display de 7 Un ejemplo sencillo para entender este funcionamiento lo podemos ver en seguida: Consta de simplemente de un CI 7490 y un 7447, unas cuantas resistencias de 330 ohms y Construiremos un circuito que maneje 6 display de 7 segmentos, para Visualizar el valor de una lectura de ADC.
  • 2. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 86 Es una forma muy fácil, pero cuando se trata de utilizar más de 1 display se vuelve una tarea muy tediosa, llegando ser no muy complejo pero demasiado grande para poder desarrollarlo en poco tiempo, por eso hay técnicas muy eficientes para ahorrar muchos circuitos y a la vez hacer más fácil de desarrollar. La técnica más usada para usar menos circuitos y realizar la misma tarea es la Multiplexor, esta técnica trata de encender cada display en un periodo de tiempo definido y cada vez que uno es encendido se da el dato a visualizar y después apagada para encender el siguiente. Esta técnica se puede utilizar con lógica TTL pero la desventaja de usar compuertas, decodificadores, multiplexores se vuelve un poco caro, ya que eleva la eficiencia pero a un costo, que al fin al cabo costara más que hacer uno tradicional. Un esquema de ejemplo se puede apreciar enseguida: Esquema de dos Display multiplexados Entonces se llega a una conclusión de que utilizando lógica TTL es eficiente pero conlleva un costo. Entonces para realizar lo misma función y tener la misma eficiencia pero mucho menor costo, es utilizar un microcontrolador para que realice todas las tareas y hasta mas. Nuestra tarea consiste en usar 6 display de 7 segmentos a la vez, y leer la entrada análoga y visualizarla en los display. Se oye una tarea muy tediosa pero los microcontroladores va ser muy sencillo, ya que usaremos un PIC18F2550 que es muy eficiente en todos los aspectos. Esquema de un contador simple
  • 3. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 87 Para hacer el Multiplexor con un microcontrolador es muy sencillo, simplemente usamos un puerto completo para visualizar el número y otros pines que depende de cuantos display se quiera visualizar, en este caso para llevar a cabo el proyecto se tiene 6 Display, se usaran 6 pines del microcontrolador para hacer el switcheo. Cada 3.33mS surgirá una interrupción por TIMER0 y cambiara de pin llegando hasta el máximo que son 6, y así será el ciclo de Multiplexor. Como hablamos de que cada 3.33mS que corresponden a cada display de encendido, entonces si son 6 tendremos una frecuencia total en cada uno de ellos de: ݂ = 1 ‫݋݀݋݅ݎ݁݌‬ ∗ ܰ݀݅‫ݕ݈ܽ݌ݏ‬ ݂ = 1 3.33݉ܵ ∗ 6 ≅ 50 ‫ݖܪ‬ Suficiente para desaparecer el parpadeo, para configurar el TIMER0 se debe de utilizar la formula: ܶ‫0ܴܯ‬ = 65535 − ൤ ‫݁݉݅ݐ‬ ∗ ܱ‫ܿݏ‬ ሺ4 ∗ ‫ݎ݈ܽܿݏ݁ݎ݌‬ሻ ൨ ܶ‫0ܴܯ‬ = 65535 − ൤ 3.33݉ܵ − 8‫ܯ‬ℎ‫ݖ‬ 4 ∗ 1 ൨ ܶ‫0ܴܯ‬ = 58875 El valor obtenido se debe de cargar cada vez que surja la interrupción por timer0. La configuración del timer0 al inicio del nuestro programa es el siguiente: Como el Microcontrolador PIC18F2550 cuenta tan solo de 3 Puerto completo y uno lo vamos a usar para Mostrar los números en cada display correspondiente, y otro para hacer el Multiplexor. Pero como los pines que están dedicados al USB no se puede configurar como salida, entonces perdemos un par de pines, por eso se adopto por usar solo tres pines del PUERTO C y tres del PUERTO A. Para hacer el corrimiento en tales pines se usara la siguiente lógica de programación: Se usa una variable ‘flag’ para hacer el cambio de puerto, cuando el corrimiento del PUERTO C termine cambia rápidamente al PUERTO A, al finalizar empezara otra vez el ciclo. OpenTimer0(TIMER_INT_ON &//Interrupción activada T0_16BIT &//valor de 16 bit T0_SOURCE_INT &//oscilador principal T0_PS_1_1); //Preescalar de 16 if(flag==0){ LATC<<=1;//Recorre un bit a la Izquierda if(LATC==0){//A recorrido los tres bit? flag=1; //Cambia de puerto LATA=0x02;//Empieza en el puerto A } }else{ LATA<<=1;//Recorre un bit a la Izquierda if(LATA>=16){//Ha llegado al limite flag=0; //Cambia de Puerto LATC=0x01;//Inicia otra vez el ciclo } }
  • 4. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 88 Ahora bien tenemos 3.33mS de retardo para poder visualizar el numero en el display correspondiente, entonces cuando la interrupción por timer0 termine, regresa al loop principal, donde colocaremos las comparaciones de cada pin, para cuando se cumpla uno de ellos entre al proceso que es visualizar el numero. Se usa una variable de tipo array donde contiene los datos en la memoria ROM, que corresponde a cada número para mostrar en los display. Ahora bien como se desea tener una lectura del convertidor Análogo-Digital, pero sin interrumpir el Multiplexor, recuerde que el microcontrolador hace las tareas línea tras línea no en forma paralela, si se sabe que estamos trabajando a una frecuencia 50Hz que para nosotros es muy rápido, pero a nivel de procesador es muy lento, ya que podemos hacer lo que necesitamos en menos de 3.33mS. Vallamos por pasos debemos de configurar primero que nada la entrada análoga. Por eso vamos a usar el PINA0 como una entrada análoga, 10bit a una tasa de adquisición de 20 Tad, con valor de referencia de la fuente de alimentación a tierra (+5v, gnd). Al tener configurado el Convertidor AD, debemos de configurar el TIMER1 como temporizador y que surja una interrupción por desbordamiento cada 100mS, haciendo de que cada vez que entre a la interrupción por TIMER1 empiece la conversión a análoga-digital, lo guarde en una variable de tipo int al tener guardado el dato análogo, se pasa por un proceso de conversión de numero a BCD, esto quiere decir que separara cada numero para ser guardado en variables, que solo contenga el numero que debe de visualizarse en cada display. Por ejemplo: Si hemos realizado una lectura de 1023 que es el valor máximo de 10- bit , al pasar por el proceso de conversión de numero a BCD, tendremos en cuatro variables de tipo char M=1 C=0 D=2 U=3 Para hacer este proceso de conversión se usa una técnica muy sencilla, es hacer una pregunta antes de entrar al ciclo de restar con relación al valor tenido. while(1){ if(LATC==0x01) {LATB=mostrar[0];}//Simplemente Muestra 0 else if(LATC==0x02) {LATB=mostrar[0];}//Simplemente Muestra 0 else if(LATC==0x04) {LATB=mostrar[M];}//Simplemente Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[C];}//Simplemente Muestra Centecimas else if(LATA==0X04) {LATB=mostrar[D];}//Simplemente Muestra Decimas else if(LATA==0X08) {LATB=mostrar[U];}//Simplemente Muestra Unidades } const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b00000000,0b00011000};
  • 5. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 89 DATO=ReadADC() ; DATO>=1000? DATO>=100? DATO>=10? DATO>0? DATO-=1000; M++; DATO-=100; C++; DATO-=10; D++; U=DATO; U=DATO; Regresa al programa si si si si no no no no
  • 6. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 90 Ahora bien si se desea una interrupción por overflow del TIMER1 se debe de configurar de la siguiente manera y cargar al timer1 cada vez que surja la interrupción por el valor de: Cada display debe de tener un transistor para que la corriente no caiga en el pin del microcontrolador y así hace que el display ilumine un poco más. Las conexiones de los 7 segmentos se debe de unirse todos y tener un solo en común, y este será conectado al PUERTO B del microcontrolador. Entonces usaremos seis Transistores para poder manejar los seis display. En la base del transistor se debe de conectar una resistencia de 1Kohm aproximadamente para que limite al microcontrolador salga más corriente. Podemos realizar la conexión de todos los Display y transistores en un solo Protoboard, dejando el microcontrolador en otro Protoboard para poner más adelante mas circuitería si queremos: ////////////////////////////////////////////////////////////////////// // Configuración de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer1(TIMER_INT_ON & //Interrupción Desactivada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilador principal T1_PS_1_8 & //Preescalar de 8 T1_OSC1EN_OFF & T1_SYNC_EXT_OFF & T1_SOURCE_CCP); //Sincronismo desactivado /*---------------------Fin de Conf. TIMER1--------------------------*/ WriteTimer1(40535);//Valor para tener una interrupción cada 100ms
  • 7. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 91 Imagen fisica de nuestro Proyecto Como no tenía un potenciómetro a la mano use una fotoresistencia, para hacer el cambio de Voltaje y así para poder apreciar el descenso de la lectura por ADC. Imagen Completa de nuestro Proyecto Fotoresistencia
  • 8. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 92 Diagrama a Manejar: Como podemos notar los microcontroladores nos ahorran pero mucho a desarrollar cosas más complejas a comparación de usar la lógica TTL de los circuito discretos de la seria 74XXXX, aunque para empezar se recomienda empezar por lo difícil jeje. Este circuito utiliza un voltaje total de 5 Volts, para usar mas voltaje y regularlo, siempre es recomendable usar un regulador de voltaje de 7805, ya que puede regular hasta 24 volts a 5 volts continuo.
  • 9. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 93 El programa es el siguiente: //////////////////////////////////////////////////////// // USO DE ADC Y DISPLAY 7 SEG //// //Autor: george.manson.69 //// //Lugar: Mexico //// //Compilador: HI TECH PIC18 (LITE MODE) //// //////////////////////////////////////////////////////// #include<htc.h> ///////////////////////////////////////////////////////////// //Configuracion para trabajar Con oscilador interno de 8Mhz __CONFIG(1,INTIO & FCMDIS & IESODIS & PLLDIV5 & PLLPOSTDIV2 & CPUDIV1 & USBOSC); ///////////////////////////////////////////////////////////// __CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BORV45 & WDTPS32K); __CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN); __CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS); __CONFIG(5,UNPROTECT); __CONFIG(6,UNPROTECT); __CONFIG(7,UNPROTECT); ////////////////////////////// //Frecuencia FOSC 8Mhz ////////////////////////////// #define _XTAL_FREQ 8000000 ///////////////////////////// //VARIABLES ///////////////////////////// const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b00000000,0b00011000}; unsigned int adc; unsigned char M,C,D,U; unsigned char flag=0; ///////////////////////////////////////////////// //Funcion de interrupcion //Si no se usa simplemente no hacemos nada... //Esto sirve para direccionar lo los datos //en un lugar muy cercano al Inicio de la memoria //de datos //////////////////////////////////////////////// static void interrupt isr(void){ ///////////////////////////////////////////////////////////////////////// // INTERRUPCION POT TIMER0 /// //CADA 3.33mS habra una interrupcion que hara que corra un bit hacia /// //la IZQUIERDA para encender el siguiente DISPLAY /// //Cuando surga la interrupcion por TIMER1 no entrara aqui /// ///////////////////////////////////////////////////////////////////////// if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO INT. POR TIMER0? if(flag==0){ LATC<<=1; //Recorre un bit a la Izquierda if(LATC==0){//A recorrido los tres bit? flag=1; //Cambia de puerto LATA=0x02;//Empieza en el puerto A } }else{ LATA<<=1;//Recorre un bit a la Izquierda if(LATA>=16){//Ha llegado al limite flag=0; //Cambia de Puerto LATC=0x01;//Inicia otra vez el ciclo } } TMR0IF=0;//Reset flag
  • 10. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 94 WriteTimer0(58875);//carga nuevamente el valor } /*---------------------Fin de INT. TIMER0---------------------------*/ ////////////////////////////////////////////////////////////////////// // INTERRUPCION POT TIMER1 /// //Al entrar aqui, inicializa las variables a cero desactiva /// //Interrupcion por TIMER0 y empieza el convertidor /// //Cuando tengamos el valor analogo, debemos de sacar las Milesimas /// //Centecimas, Decimas y Unidades. /// //Esta interrupcion surgira cada 100mS /// ////////////////////////////////////////////////////////////////////// if(TMR1IF){ M=C=D=U=0;//Inicializa variables TMR0IE=0; //Desactiva INT por timer0 ConvertADC();//Empieza la conversion Analoga while(BusyADC());//Ha terminado? adc=ReadADC();//Lee el dato while(adc>=1000){//Es mayor de 1000? adc-=1000; //Resta 1000 M++; //Incrementa 1 } while(adc>=100){ //Es mayor de 100? adc-=100; //Resta 100 C++; //Incrementa 1 } while(adc>=10){ //Es mayor de 10? adc-=10; //resta 10 D++; //Incrementa 1 } if(adc>0){ //Es mayor de 0? U=adc; //Toma el valor ultimo }else{ U=0; //Sino,valor a Cero } TMR1IF=0; //Reset timer1 TMR0IE=1; //Activa Timer0 WriteTimer1(40535);//Carga el valor nuevamente. } /*---------------------Fin de INT. TIMER1---------------------------*/ } ////////////////////////////// //FUNCION PRINCIPAL ////////////////////////////// void main(void){ OSCCON=0x70; NOP();NOP();NOP();NOP(); ////////////////////////////////////////////////////////////////////// // Configuracion de Puertos /// ////////////////////////////////////////////////////////////////////// TRISB=0x00;//Puerto B como salida TRISC=0x00;//Puerto C como salida TRISA=0x01;//Pin A0 como entrada analoga CMCON=0x07; /*---------------------Fin de Conf. Puertos-------------------------*/ ////////////////////////////////////////////////////////////////////// // Configuracion de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer0(TIMER_INT_ON & //Interrupcion activada T0_16BIT & //valor de 16 bit T0_SOURCE_INT & //Corriente desde el oscilador principal T0_PS_1_1); //Preescalar de 16 /*---------------------Fin de Conf. TIMER1--------------------------*/
  • 11. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 95 ////////////////////////////////////////////////////////////////////// // Configuracion de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer1(TIMER_INT_ON & //Interrupcion Desactivada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilador principal T1_PS_1_8 & //Preescalar de 8 T1_OSC1EN_OFF & T1_SYNC_EXT_OFF & T1_SOURCE_CCP); //Sincronismo desactivado /*---------------------Fin de Conf. TIMER1--------------------------*/ ////////////////////////////////////////////////////////////////////// // Configuracion de ADC /// ////////////////////////////////////////////////////////////////////// OpenADC(ADC_FOSC_RC &//Internal Oscilador Interno ADC_RIGHT_JUST &//Justificacion a la derecha (10-bit) ADC_20_TAD, //Tiempo de Adquisicion (TAD) ADC_CH0 &//CANAL 3 analogo ADC_INT_OFF &//Interrupcion por ADC APAGDO ADC_REF_VDD_VSS, //V+ref=VCC,V-ref=GND ADC_CH0); //AN4=analogo,resto digitales /*---------------------Fin de Conf. ADC------------------------------*/ INTCON|=0b00100000;//Para activar interrupcion por timer0 WriteTimer0(58875);//Valor para tener una interrupcion cada 3.33 mS WriteTimer1(40535);//Valor para tener una interrupcion cada 100ms GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICOS PORTB=0x00;//Inicializa PUERTO B como apagado LATC=0x01; LATA=0x00; while(1){ if(LATC==0x01) {LATB=mostrar[0];}//Simplemente Muestra 0 else if(LATC==0x02) {LATB=mostrar[0];}//Simplemente Muestra 0 else if(LATC==0x04) {LATB=mostrar[M];}//Simplemente Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[C];}//Simplemente Muestra Centecimas else if(LATA==0X04) {LATB=mostrar[D];}//Simplemente Muestra Decimas else if(LATA==0X08) {LATB=mostrar[U];}//Simplemente Muestra Unidades } }
  • 12. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 96 Para seguir con nuestro circuito ya armado, y no desperdiciar más cables, se propone realizar un contador de eventos, en este caso se tiene en lugar de una entrada análoga, una entrada digital, que cada vez que se detecte un pulso este empiece a incrementar las variables que se mostraran en los display. El programa a manejar es muy parecido del anterior, ya que solo se modifico, dos cosas. Una solo se removió la opción del convertidor análogo digital dejando solo entradas digitales en el PINA0. Dos se quito la lógica de programación del convertidor de número a BCD en la interrupción y se modifico. Ahora como hemos de realizar un contador con un push botón, hay que tener en cuenta algunos aspectos, cada vez que presionamos el botón puede surgir los rebotes, se le dice rebotes de corriente, ya que al presionar el botón, abra picos de voltaje que pueden producir información de pulsaciones erróneas, causando que cuente más de lo previsto. Para la solución de este problema se adopto por realizar lo siguiente: Crear una variable que cuente 3 interrupción por timer1 que corresponden a una temporización de 300mS, al llegar al máximo de pulsos, pregunta si se ha presionado el botón, si es así, incrementara la variable U, cuando dicha variable llega al valor máximo que es 10, se resetea e incrementa la siguiente variable que es D y así sucesivamente hasta llegar a la variable M. El botón puede ser un pulsador, conectado a +5v y el otro extremo a una resistencia de 10k hacia tierra. Siguiendo con nuestro circuito armado de 6 display. Para contar eventos con un botón. ET Sin tiempo Con tiempo antirepote
  • 13. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 97 Podemos apreciar el diagrama a manejar: El Programa que contiene el microcontrolador es el siguiente: //////////////////////////////////////////////////////// // Contador //// //Autor: george.manson.69 //// //Lugar: Mexico //// //Compilador: HI TECH PIC18 (LITE MODE) //// //////////////////////////////////////////////////////// #include<htc.h> ///////////////////////////////////////////////////////////// //Configuracion para trabajar Con oscilador interno de 8Mhz __CONFIG(1,INTIO & FCMDIS & IESODIS & PLLDIV5 & PLLPOSTDIV2 & CPUDIV1 & USBOSC); ///////////////////////////////////////////////////////////// __CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BORV45 & WDTPS32K); __CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN); __CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS); __CONFIG(5,UNPROTECT); __CONFIG(6,UNPROTECT); __CONFIG(7,UNPROTECT); ////////////////////////////// //Frecuencia FOSC 8Mhz
  • 14. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 98 ////////////////////////////// #define _XTAL_FREQ 8000000 ///////////////////////////// //VARIABLES ///////////////////////////// const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b00000000,0b00011000}; unsigned int adc; unsigned char M,C,D,U; unsigned char flag=0; unsigned char var; ///////////////////////////////////////////////// //Funcion de interrupcion //Si no se usa simplemente no hacemos nada... //Esto sirve para direccionar lo los datos //en un lugar muy cercano al Inicio de la memoria //de datos //////////////////////////////////////////////// static void interrupt isr(void){ ///////////////////////////////////////////////////////////////////////// // INTERRUPCION POT TIMER0 /// //CADA 3.33mS habra una interrupcion que hara que corra un bit hacia /// //la IZQUIERDA para encender el siguiente DISPLAY /// //Cuando surga la interrupcion por TIMER1 no entrara aqui /// ///////////////////////////////////////////////////////////////////////// if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO INT. POR TIMER0? if(flag==0){ LATC<<=1; //Recorre un bit a la Izquierda if(LATC==0){//A recorrido los tres bit? flag=1; //Cambia de puerto LATA=0x02;//Empieza en el puerto A } }else{ LATA<<=1;//Recorre un bit a la Izquierda if(LATA>=16){//Ha llegado al limite flag=0; //Cambia de Puerto LATC=0x01;//Inicia otra vez el ciclo } } TMR0IF=0;//Reset flag WriteTimer0(58875);//carga nuevamente el valor } /*---------------------Fin de INT. TIMER0---------------------------*/ ////////////////////////////////////////////////////////////////////// // INTERRUPCION POT TIMER1 /// //Cheka cada 300mS el switch, si esta presionado suma 1 /// //A la variable que corresponda. ////////////////////////////////////////////////////////////////////// if(TMR1IF){ TMR0IE=0; //Desactiva INT por timer0 var++; if(var>3){ var=0; if(RA0){ U++; if(U>=10){ U=0; D++; if(D>=10){ D=0; C++;
  • 15. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 99 if(C>=10){ C=0; M++; if(M>=10){ M=0; } } } } } } TMR1IF=0; //Reset timer1 TMR0IE=1; //Activa Timer0 WriteTimer1(41035);//Valor para tener una interrupcion cada 100ms } } /*---------------------Fin de INT. TIMER1---------------------------*/ ////////////////////////////// //FUNCION PRINCIPAL ////////////////////////////// void main(void){ OSCCON=0x70; NOP();NOP();NOP();NOP(); ////////////////////////////////////////////////////////////////////// // Configuración de Puertos /// ////////////////////////////////////////////////////////////////////// TRISB=0x00;//Puerto B como salida TRISC=0x00;//Puerto C como salida TRISA=0x01;//Pin A0 como entrada digital ADCON1=0x0F; CMCON=0x07; /*---------------------Fin de Conf. Puertos-------------------------*/ ////////////////////////////////////////////////////////////////////// // Configuración de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer0(TIMER_INT_ON & //Interrupción activada T0_16BIT & //valor de 16 bit T0_SOURCE_INT & //Corriente desde el oscilador principal T0_PS_1_1); //Preescalar de 16 /*---------------------Fin de Conf. TIMER1--------------------------*/ ////////////////////////////////////////////////////////////////////// // Configuración de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer1(TIMER_INT_ON & //Interrupción Desactivada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilador principal T1_PS_1_8 & //Preescalar de 8 T1_OSC1EN_OFF & T1_SYNC_EXT_OFF & T1_SOURCE_CCP); //Sincronismo desactivado /*---------------------Fin de Conf. TIMER1--------------------------*/ INTCON|=0b00100000;//Para activar interrupción por timer0 WriteTimer0(58875);//Valor para tener una interrupción cada 3.33 mS WriteTimer1(41035);//Valor para tener una interrupción cada 100ms GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICOS PORTB=0x00; //Inicializa PUERTO B como apagado LATC=0x01; LATA=0x00; while(1){ if(LATC==0x01) {LATB=mostrar[0];}//Simplemente Muestra 0 else if(LATC==0x02) {LATB=mostrar[0];}//Simplemente Muestra 0
  • 16. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 100 else if(LATC==0x04) {LATB=mostrar[M];}//Simplemente Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[C];}//Simplemente Muestra Centecimas else if(LATA==0X04) {LATB=mostrar[D];}//Simplemente Muestra Decimas else if(LATA==0X08) {LATB=mostrar[U];}//Simplemente Muestra Unidades } } Algunas imágenes del Contador: Recuerde siempre alimentar al circuito coin un voltaje de 5 Volts. Boton
  • 17. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 101 Algunas veces en nuestra vida como electrónicos, o simplemente como hobbystas, se nos pasa por la mente realizar un reloj con display, como podemos realizarlos de distintas formas como usando lógica TTL, o pasando ya a usar cosas más avanzadas como los microcontroladores, pues ¿Porque no realizarlo?, ya que tenemos el circuito armado con los 6 display, ahorraremos mucho tiempo para desarrollarlo, simplemente necesitamos colocar 3 pulsadores y realizar otra tipo de lógica de programación en nuestro PIC y hemos realizado nuestro reloj. La idea es tener tres pulsadores de cual un servirá para controlar los demás. Por ejemplo llamemos a uno como SET, a otro botón como HORAS, y el último como MINUTOS, cuando el botón SET no esté presionado, el microcontrolador no hará caso los botones de HORAS y MINUTOS, pero si tenemos lo contrario que el botón SET este presionado mientras este así, podemos cambiar o presionar los botones HORAS y MINUTOS. Teniendo ya establecido las condiciones del los pulsadores ya podemos empezar a programar, lo único que cambiaremos de del programa anterior es algunas variables y solo cambiaremos la función de interrupción del TIMER1, ya que la interrupción por TIMER0 es ya es de ley tenerla. Lo que cambiaremos de la interrupción del TIMER1 es como se debe de comportar al presionar un botón, pero a la vez no interrumpir el proceso de contar los segundos ya que si hacemos que los pulsadores corten la sincronía del tiempo, podemos adelantar o retrasar nuestro reloj. Como sabemos que la configuración de interrupción del TIMER1 surge cada 100mS teniendo que realizar 10 veces dicha interrupción para tener aproximadamente un segundo, crearemos una variable que cuente las interrupciones y al llegar a la decima interrupción sume a otra variable +1. Se han creado 6 variables para que cada una de ellas corresponda a cada display, por ejemplo: H2 H1 M2 M1 S2 S1 La variable que se le sumara uno cuando las 10 interrupciones pasen, es “S1” ya que esta variable es la que corresponde al primer display de Derecha a Izquierda, cuando la variable “S1” llegue al máximo en este caso a 10, “S1=0” y suma uno a la siguiente variable “S2” pero esta Aun siguiendo con nuestro circuito armado para realizar un reloj simple.
  • 18. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 102 variable no debe de llegar hasta 10 sino a 6, ya que debemos de contar solo 60 segundos, cuando la variable “S2” llegue a 6 se volverá a cero, y sumara uno a la variable M1, y así sucesivamente pero si deseamos realizar que las horas solo cuente hasta 24, se realiza la siguiente lógica: Ya tenemos la lógica de cómo realizar la sumatoria de las variables con respecto al tiempo, pero aun no tenemos como poner la lógica de introducir los botones sin afectar el conteo de segundos y aparte de no afectar con rebotes al presionar dicho botón. Bueno para solucionar los rebotes al presionar cualquier botón, se debe de esperar 300mS para que entre o compare si se ha presionado el botón de SET, se usa la comparación: If((var%3)==1); Esta comparación hace que cada 300mS entre y vea que si se ha presionado el botón de SET, ya que: 1%3 No es múltiplo de tres entrega 0 2%3 No es múltiplo de tres entrega 0 3%3 Es múltiplo de tres entrega 1 4%3 No es múltiplo de tres entrega 0 5%3 No es múltiplo de tres entrega 0 6%3 3 Es múltiplo de tres entrega 1 …. Al entrar a esta comparación ahora veremos si se ha presionado el botón SET Ahora si cada vez que pase 300mS se podrá checar el pulsador SET pero sin afectar el tiempo de los segundos. Pero recuerde que los segundos pueden ser afectados a la acumulación de instrucciones de nuestro programa porque recuerde que el lenguaje C esta hecho por macros es decir que contiene líneas de lenguaje ensamblador pero todo el conjunto de una sola instrucción está dirigido simplemente a una línea en C. Por ejemplo: TRISB=0x00 ;No se ejecuta en un ciclo maquina sino lo transformamos a lo que es realmente en ensamblador y tenemos que: Bcf STATUS,5 Movlw 0x00 Movwf TRISB H1++; if(H1==10 && H2<2){ H1=0; H2++; }else if(H1==4 && H2==2){ H2=H1=0; } else if((var%3)==1){ if(SET){ if(HORAS){ H1++; if(H1==10 && H2<2){ H1=0; H2++; }else if(H1==4 && H2==2){ H2=H1=0; } } if(MINUTOS){ M1++; if(M1>=10){ M1=0; M2++; if(M2>=6){ M2=0; } } } } }
  • 19. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 103 En realidad se ejecuta en tres ciclos maquina, esto lo menciono para que tenga una idea de cómo debe de optimizar los códigos para que realice lo mismo pero consuma menos tiempo maquina. Y nuestro proyecto es afectado por los términos anteriores, y podría retrasarse unos segundos cada cuatro u ocho días, se recomienda realizar una buena lógica de programación para solucionar o hacer mucho más pequeño el lapso de tiempo perdido. El circuito a Manejar es el siguiente; Como vemos no se ha cambiado en absoluto la configuración de los transistores, ni los display solo hemos puesto 2 pulsadores extras para cambiar la HORA y MINUTOS.
  • 20. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 104 El programa se muestra a continuación: //////////////////////////////////////////////////////// // Contador //// //Autor: george.manson.69 //// //Lugar: Mexico //// //Compilador: HI TECH PIC18 (LITE MODE) //// //////////////////////////////////////////////////////// #include<htc.h> ///////////////////////////////////////////////////////////// //Configuracion para trabajar Con oscilador interno de 8Mhz __CONFIG(1,INTIO & FCMDIS & IESODIS & PLLDIV5 & PLLPOSTDIV2 & CPUDIV1 & USBOSC); ///////////////////////////////////////////////////////////// __CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BORV45 & WDTPS32K); __CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN); __CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS); __CONFIG(5,UNPROTECT); __CONFIG(6,UNPROTECT); __CONFIG(7,UNPROTECT); ////////////////////////////// //Frecuencia FOSC 8Mhz ////////////////////////////// #define _XTAL_FREQ 8000000 ////////////////////////////// //Definiciones Globales ////////////////////////////// #define SET RA0 #define HORAS RC6 #define MINUTOS RC7 ///////////////////////////// //VARIABLES ///////////////////////////// const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b00000000,0b00011000}; unsigned int adc; unsigned char H2,H1,M2,M1,S2,S1; unsigned char flag=0; unsigned char var; ///////////////////////////////////////////////// //Funcion de interrupcion //Si no se usa simplemente no hacemos nada... //Esto sirve para direccionar lo los datos //en un lugar muy cercano al Inicio de la memoria //de datos //////////////////////////////////////////////// static void interrupt isr(void){ ///////////////////////////////////////////////////////////////////////// // INTERRUPCION POT TIMER0 /// //CADA 3.33mS habra una interrupcion que hara que corra un bit hacia /// //la IZQUIERDA para encender el siguiente DISPLAY /// //Cuando surga la interrupcion por TIMER1 no entrara aqui /// ///////////////////////////////////////////////////////////////////////// if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO INT. POR TIMER0? if(flag==0){ LATC<<=1; //Recorre un bit a la Izquierda if(LATC==0){//A recorrido los tres bit? flag=1; //Cambia de puerto LATA=0x02;//Empieza en el puerto A }
  • 21. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 105 }else{ LATA<<=1;//Recorre un bit a la Izquierda if(LATA>=16){//Ha llegado al limite flag=0; //Cambia de Puerto LATC=0x01;//Inicia otra vez el ciclo } } TMR0IF=0;//Reset flag WriteTimer0(58875);//carga nuevamente el valor } /*---------------------Fin de INT. TIMER0---------------------------*/ ////////////////////////////////////////////////////////////////////// // INTERRUPCION POT TIMER1 /// //Cheka cada 300mS el switch, si esta presionado suma 1 /// //A la variable que corresponda. ////////////////////////////////////////////////////////////////////// if(TMR1IF){ TMR0IE=0; //Desactiva INT por timer0 /*CODIGO PRINCIPAL*/ //Segundos jamas se interrupe// var++; if(var>=10){ var=0; S1++; if(S1==10){ S1=0; S2++; if(S2==6){ S2=0; M1++; if(M1==10){ M1=0; M2++; if(M2==6){ M2=0; H1++; if(H1==10 && H2<2){ H1=0; H2++; }else if(H1==4 && H2==2){ H2=H1=0; } } } } } } else if((var%3)==1){ if(SET){ if(HORAS){ H1++; if(H1==10 && H2<2){ H1=0; H2++; }else if(H1==4 && H2==2){ H2=H1=0; } } if(MINUTOS){ M1++; if(M1>=10){ M1=0;
  • 22. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 106 M2++; if(M2>=6){ M2=0; } } } } } /*******************/ TMR1IF=0; //Reset timer1 TMR0IE=1; //Activa Timer0 WriteTimer1(41900);//Valor para tener una interrupcion cada 100ms } } /*---------------------Fin de INT. TIMER1---------------------------*/ ////////////////////////////// //FUNCION PRINCIPAL ////////////////////////////// void main(void){ OSCCON=0x70; NOP();NOP();NOP();NOP(); ////////////////////////////////////////////////////////////////////// // Configuracion de Puertos /// ////////////////////////////////////////////////////////////////////// TRISB=0x00;//Puerto B como salida TRISC=0xD0;//Puerto C como salida TRISA=0x01;//Pin A0 como entrada digital ADCON1=0x0F; CMCON=0x07; /*---------------------Fin de Conf. Puertos-------------------------*/ ////////////////////////////////////////////////////////////////////// // Configuracion de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer0(TIMER_INT_ON & //Interrupcion activada T0_16BIT & //valor de 16 bit T0_SOURCE_INT & //Corriente desde el oscilador principal T0_PS_1_1); //Preescalar de 16 /*---------------------Fin de Conf. TIMER1--------------------------*/ ////////////////////////////////////////////////////////////////////// // Configuracion de Timer1 /// ////////////////////////////////////////////////////////////////////// OpenTimer1(TIMER_INT_ON & //Interrupcion Desactivada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilador principal T1_PS_1_8 & //Preescalar de 8 T1_OSC1EN_OFF & T1_SYNC_EXT_OFF & T1_SOURCE_CCP); //Sincronismo desactivado /*---------------------Fin de Conf. TIMER1--------------------------*/ INTCON|=0b00100000;//Para activar interrupcion por timer0 WriteTimer0(58875);//Valor para tener una interrupcion cada 3.33 mS WriteTimer1(41900);//Valor para tener una interrupcion cada 100ms GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICOS PORTB=0x00;//Inicializa PUERTO B como apagado LATC=0x01; LATA=0x00; while(1){ if(LATC==0x01) {LATB=mostrar[H2];}//Simplemente Muestra 0 else if(LATC==0x02) {LATB=mostrar[H1];}//Simplemente Muestra 0 else if(LATC==0x04) {LATB=mostrar[M2];}//Simplemente Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[M1];}//Simplemente Muestra Centecimas
  • 23. [PROYECTO #1] 13 de enero de 2011 Usando Display de 7 segmentos Página 107 else if(LATA==0X04) {LATB=mostrar[S2];}//Simplemente Muestra Decimas else if(LATA==0X08) {LATB=mostrar[S1];}//Simplemente Muestra Unidades } } Algunas fotos del Reloj: Foto de reloj SET