Proyecto1

23
Este proyecto es muy interesan a prueba dos interrupciones por mismo tiempo. El proyecto cons Cantidad Co 6 Displ 6 1 P 3 Micro 4 7 R Antes de empezar a programar d tener algunos criterios definidos ¿Cómo hacer prender 6 Display circuito integrado? Si usted es un electrónico, record existen algunos circuitos especia realizar dicha acción, como es el cuenta los pulsos que son ingres después empieza a contar en for nte ya que pone r TIMERS al sta de: omponente lay de 7 seg (An) 2N2222A PIC18F2550 ointerruptores Resis 10K Resis 330R debemos de s. con un solo dara que almente para l 7490 que nos sado a el y rma binaria. Circuito esquemático de El conteo lo hace de 0 a que está listo para visua segmentos, ya que tiene decodificador para ahor segmentos. Un ejemplo sencillo para funcionamiento lo pode Consta de simplemente 7447, unas cuantas resis un display de 7 seg. Construiremos un circ display de 7 segmento el valor de una lectu e un 7490 9, pero esto no significa alizarse a un display de 7 e que pasar por un ra si usar un display de 7 a entender este emos ver en seguida: de un CI 7490 y un stencias de 330 ohms y cuito que maneje 6 os, para Visualizar ura de ADC.

Transcript of Proyecto1

Page 1: Proyecto1

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.

Page 2: Proyecto1

[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

Page 3: Proyecto1

[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������ ∗ ���� ��

� = 13.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 } }

Page 4: Proyecto1

[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];}//Simplemen te Muestra 0 else if(LATC==0x02) {LATB=mostrar[0];}//Simplemen te Muestra 0 else if(LATC==0x04) {LATB=mostrar[M];}//Simplemen te Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[C];}//Simplemen te Muestra Centecimas else if(LATA==0X04) {LATB=mostrar[D];}//Simplemen te Muestra Decimas else if(LATA==0X08) {LATB=mostrar[U];}//Simplemen te Muestra Unidades }

const unsigned char mostrar[10]={0b11000000,0b11111001,0b10100100,0b101 10000,0b10011001, 0b10010010,0b10000011,0b11111000,0b00000000, 0b00011000};

Page 5: Proyecto1

[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

Page 6: Proyecto1

[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 Desactiv ada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilado r 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 interrupc ión cada 100ms

Page 7: Proyecto1

[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

Page 8: Proyecto1

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

Page 9: Proyecto1

[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 & PLL POSTDIV2 & CPUDIV1 & USBOSC); /////////////////////////////////////////////////// ////////// __CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BOR V45 & 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,0b11111 001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b000000 00,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 c orra un bit hacia /// //la IZQUIERDA para encender el siguiente DISPLAY /// //Cuando surga la interrupcion por TIMER1 no entrar a aqui /// /////////////////////////////////////////////////// ////////////////////// if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO IN T. 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

Page 10: Proyecto1

[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 d esactiva /// //Interrupcion por TIMER0 y empieza el convertidor /// //Cuando tengamos el valor analogo, debemos de saca r 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 oscilado r principal T0_PS_1_1); //Preescalar de 16 /*---------------------Fin de Conf. TIMER1--------- -----------------*/

Page 11: Proyecto1

[PROYECTO #1] 13 de enero de 2011

Usando Display de 7 segmentos Página 95

/////////////////////////////////////////////////// /////////////////// // Configuracion de Timer1 /// /////////////////////////////////////////////////// /////////////////// OpenTimer1(TIMER_INT_ON & //Interrupcion Desactiv ada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilado r 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 interrup cion cada 3.33 mS WriteTimer1(40535);//Valor para tener una interrup cion cada 100ms GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICO S 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];}//Simplemen te Muestra 0 else if(LATC==0x04) {LATB=mostrar[M];}//Simplemen te Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[C];}//Simplemen te Muestra Centecimas else if(LATA==0X04) {LATB=mostrar[D];}//Simplemen te Muestra Decimas else if(LATA==0X08) {LATB=mostrar[U];}//Simplemen te Muestra Unidades } }

Page 12: Proyecto1

[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

Page 13: Proyecto1

[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 & PLL POSTDIV2 & CPUDIV1 & USBOSC); /////////////////////////////////////////////////// ////////// __CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BOR V45 & WDTPS32K); __CONFIG(3,PBDIGITAL & LPT1DIS & MCLREN); __CONFIG(4,STVRDIS & LVPDIS & ICPORTDIS & DEBUGDIS) ; __CONFIG(5,UNPROTECT); __CONFIG(6,UNPROTECT); __CONFIG(7,UNPROTECT); ////////////////////////////// //Frecuencia FOSC 8Mhz

Page 14: Proyecto1

[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,0b11111 001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b000000 00,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 c orra un bit hacia /// //la IZQUIERDA para encender el siguiente DISPLAY /// //Cuando surga la interrupcion por TIMER1 no entrar a aqui /// /////////////////////////////////////////////////// ////////////////////// if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO IN T. 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 su ma 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++;

Page 15: Proyecto1

[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 interru pcion 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 oscilado r principal T0_PS_1_1); //Preescalar de 16 /*---------------------Fin de Conf. TIMER1--------- -----------------*/ /////////////////////////////////////////////////// /////////////////// // Configuración de Timer1 /// /////////////////////////////////////////////////// /////////////////// OpenTimer1(TIMER_INT_ON & //Interrupción Desactiv ada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilado r 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 interrup ción cada 3.33 mS WriteTimer1(41035);//Valor para tener una interrup ció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];}//Simplemen te Muestra 0

Page 16: Proyecto1

[PROYECTO #1] 13 de enero de 2011

Usando Display de 7 segmentos Página 100

else if(LATC==0x04) {LATB=mostrar[M];}//Simplemen te Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[C];}//Simplemen te Muestra Centecimas else if(LATA==0X04) {LATB=mostrar[D];}//Simplemen te Muestra Decimas else if(LATA==0X08) {LATB=mostrar[U];}//Simplemen te Muestra Unidades } }

Algunas imágenes del Contador:

Recuerde siempre alimentar al circuito coin un voltaje de 5 Volts.

Boton

Page 17: Proyecto1

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

Page 18: Proyecto1

[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; } } } } }

Page 19: Proyecto1

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

Page 20: Proyecto1

[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 & PLL POSTDIV2 & CPUDIV1 & USBOSC); /////////////////////////////////////////////////// ////////// __CONFIG(2,VREGDIS & PWRTEN & BORDIS & WDTDIS & BOR V45 & 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,0b11111 001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000011,0b11111000,0b00000000,0b00011 000}; 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 c orra un bit hacia /// //la IZQUIERDA para encender el siguiente DISPLAY /// //Cuando surga la interrupcion por TIMER1 no entrar a aqui /// /////////////////////////////////////////////////// ////////////////////// if(TMR0IF && !TMR1IF && TMR0IE){//NO HA SURGIDO IN T. 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 }

Page 21: Proyecto1

[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 su ma 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;

Page 22: Proyecto1

[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 interru pcion 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 oscilado r principal T0_PS_1_1); //Preescalar de 16 /*---------------------Fin de Conf. TIMER1--------- -----------------*/ /////////////////////////////////////////////////// /////////////////// // Configuracion de Timer1 /// /////////////////////////////////////////////////// /////////////////// OpenTimer1(TIMER_INT_ON & //Interrupcion Desactiv ada T1_16BIT_RW & //valor de 16 bit T1_SOURCE_INT & //Corriente desde el oscilado r 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 interrup cion cada 3.33 mS WriteTimer1(41900);//Valor para tener una interrup cion cada 100ms GIE=1; //INTERRUPCIONES GLOBALES ACTIVADAS PEIE=1; //ACTIVA INTERURPCIONES POR PERIFERICO S 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];}//Simpleme nte Muestra 0 else if(LATC==0x04) {LATB=mostrar[M2];}//Simpleme nte Muestra Milesimas else if(LATA==0X02) {LATB=mostrar[M1];}//Simpleme nte Muestra Centecimas

Page 23: Proyecto1

[PROYECTO #1] 13 de enero de 2011

Usando Display de 7 segmentos Página 107

else if(LATA==0X04) {LATB=mostrar[S2];}//Simpleme nte Muestra Decimas else if(LATA==0X08) {LATB=mostrar[S1];}//Simpleme nte Muestra Unidades } }

Algunas fotos del Reloj:

Foto de reloj

SET