TODOPIC
Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: 123456 en 02 de Julio de 2016, 17:49:37
-
Hola,
Quería saber si me podían guiar con un proyecto que necesito hacer:
¿Que habría que hacer para programar un reloj? No importa el tipo, con el mas básico posible alcanza
No hace falta hacer el hardware, con el codigo en MPLAB alcanza y sobra. :)
¿Tendria que usar multiplexado para los supuestos displays? ¿Hacen falta interrupciones? ¿Como harían para que el micro se de cuenta que un segundo es un segundo? ¿Con un contador? ¿Donde se guarda ese dato? ¿Como sabe que 60 segundos se convierten en un minuto?
Muchas gracias, saludos :P
-
Me suena a tarea de la facultad
-
No de la facultad, de la secundaria...
Ah, si lo decís por las preguntas, las hice yo para explicarles bien cuales son mis dudas.
Lo que tengo que hacer es un reloj, por eso todas mis preguntas, si me pudieran ayudar a despejar esas dudas les agradecería un montón.
saludos.
-
Te respondo las preguntas, pero codigo no vas a obtener, Solo si presentas tu codigo y veo que estas tratando de aprender vas a recibir ayuda de mi parte y tal ves un poco de codigo tambien.
Primero es necesario definir un lenguaje en el cual vas a programar:
¿ASM o C?
Respecto a las preguntas:
¿Que habría que hacer para programar un reloj?
Lo mas basico basico pero basico y que no posee ninguna precision, es decir podriamos estar errandole en 1 o 2 segundos por minuto ( que a la hora es mucho), seria con delays, es decir solo tocarias los modulos del puerto ( entrada, salida, ponerlo en 1 o en 0 )
Si queres un poquito mas de precision Usas un timers. Yo no usaria el PIC16F84A es caro y no posee nada. Aunque sea usaria el PIC16F88 que es una version mas actual y mas barata.
¿Tendria que usar multiplexado para los supuestos displays?
Depende de como sea tu reloj o como lo quieras hacer, Supongamos 6 display 7 segmentos, lo mas simple seria una multiplexacion, por que necesitarias 7 pines para cada segmento + 6 pines para los comunes, lo cual vas a necesitar bastantes pines y que el PIC16F84A no posee, tal ves si son 4 displays sea mas simple.
¿Hacen falta interrupciones?
Depende como quieras programarlo, si usas el timer para llevar los segundos estaria bueno usarlas, y dejar el programa principal para solo el multilpexado.
¿Como harían para que el micro se de cuenta que un segundo es un segundo?
Cada instruccion ejecutada ocupa un tiempo especifico, ej lenguajes como C es muy dificil saber la cantidad de instrucciones, pero si en ASM. Lo que se hace es usar un timer, ese timer es un contador de pulsos, esos pulsos provienen del reloj que tiene el timer o del reloj que se alimenta el PIC. Si conoces la frecuencia del oscilador, podes saber cuanto tarda en sumar 1 ese timer, Si por ejemplo cargas 200 en el timer, tenes que cuando llegue a 256 se produce el overflow y activa la interrupcion, entonces conoces que pasaron 56 pulsos.
¿Con un contador?¿Donde se guarda ese dato?
Si usas el timer con el reloj principal que normalmente va a ser de 4Mhz lo mas seguro, el timer va a producir un overflow de muy poco tiempo, entonces la idea es generar una interrupcion de un valor concreto, supongamos esto, configuras el timer para que se produzca una interrupcion cada 0.01s ( 10ms ) , entonces para saber cuanto es 1 segundo, creas una variable (en C) o usas un registro ( en ASM ) para contar la cantidad de veces que entra, al llegar a 100 ( 100 * 10ms = 1s) sabes que paso 1 segundo.
¿Como sabe que 60 segundos se convierten en un minuto?
El micro no sabe nada, el que sabe eso sos vos, entonces suponente que creas una variable que se llame segundos, y ahora cada ves que pasa un segundo lo incrementas en 1, vos sos el encargado de revisar que si incrementas no exceda los 60 segundos. Ejemplo ( esto es pseudocodigo para que entiendas )
Segundos + 1
Si Segundos es igual a 60
Entonces Hago:
Segundos igual a 0
Minutos + 1
Hasta ahi simple, pero si observas tambien sume 1 a minutos, y tambien tengo que asegurarme que si minutos es 60 entonces ponerlo a 0 y sumarle uno a hora, y lo mismo con horas, la cosa termina asi:
Segundos + 1
Si Segundos es igual a 60 Entonces:
Segundos igual a 0
Minutos + 1
Si Minutos es igual a 60 Entonces:
Minutos igual a 0
Horas + 1
Si Horas es igual a 24 Entonces:
Horas igual a 0
-
que se luzca en el trabajo que le pidieron en la escuela y haga un chalieplexing, controlando ocho led display con solo nueve pines del microcontrolador! :-/
-
Muchas gracias KILLERJC por responderme las preguntas, aunque hay algo que no me termina de quedar claro,
Si usas el timer con el reloj principal que normalmente va a ser de 4Mhz lo mas seguro, el timer va a producir un overflow de muy poco tiempo, entonces la idea es generar una interrupcion de un valor concreto, supongamos esto, configuras el timer para que se produzca una interrupcion cada 0.01s ( 10ms ) , entonces para saber cuanto es 1 segundo, creas una variable (en C) o usas un registro ( en ASM ) para contar la cantidad de veces que entra, al llegar a 100 ( 100 * 10ms = 1s) sabes que paso 1 segundo.
¿Como hago para configurar el arranque del timer? ¿Con el preescaler?
Y suponiendo que lo modifico, ¿No tendría que tener en cuenta que cada instrucción además consume tiempo por lo tanto se me puede llegar a desfasar el reloj?
Encontre estas dos formulas pero no estoy seguro si funcionan para mi codigo ya que yo quiero usar el TMR0 como temporizador y no como contador.
(http://www.aquihayapuntes.com/images/stories/practicasPIC/recursos/tmr0Temp/formulatmr0.png)
(http://www.aquihayapuntes.com/images/stories/practicasPIC/recursos/tmr0Temp/formulatmr0_1.png)
Este es el código que programe hasta ahora(tambien lo voy a adjuntar):
;Reloj con interrupciones y 4 displays con multiplexado
;-------------------------------------Zona de datos--------------------------------------
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ;Config
LIST P=16F84A ;Procesador
INCLUDE <P16F84A.INC> ;Fichero con las etiquetas
CBLOCK 0x0C ;Bloque de variables asignadas a partir de 0x0C
Segundos ;Variable de segundos
Minutos ;de minutos
Horas ;y de horas
ENDC ;aca termina el bloque de variables
;--------------------------------------Zona de codigos----------------------------------------
ORG 0
Inicio
movlw 0x00 ;Carga 0 en W
bsf STATUS,RP0 ;Acceso al banco 1
bcf OPTION_REG,T0CS ;Pone a 0, timer0 como temporizador
bcf STATUS,RP0 ;Vuelve al banco 0
Reloj call Timer0_Un_Segundo ;Llama a la rutina "Timer0_Un_Segundo"
call Cambio_Segundos
goto Reloj
;-------------------------Contador de segundos----------------------------
Timer0_Un_Segundo
movlw 0x00 ;Carga 0 en W
movwf TMR0 ;Carga el TMR0 con 0x00
bcf INTCON,T0IF ;Resetea el flag de desbordamiento del TMR0
Timer0_Desborde
btfss INTCON,T0IF ;Salta si se desborda el TMR0
goto Timer0_Desborde ;Repite la subrutina porque no hubo overflow
return ;Return para volver
;------------------------Actualizador de segundos--------------------------
Cambio_Segundos
incf Segundos ;Incrementa en 1 el contador de segundos
movlw d'60' ;Pone d60 en W
subwf Segundos,W ;Resta Segundos - W y lo guarda en W
btfsc STATUS,Z ;Salta si Z=0, porque el segundero no llego a 60
call Cambio_Minutos ;Llamaa a la subrutina Cambio_minutos
return ;Vuelve
;------------------------Actualizador de minutos---------------------------
Cambio_Minutos
movlw 0x00 ;Pone 0 en W
movwf Segundos ;Pone W en Segundos
incf Minutos ;Incrementa en 1 minutos
movlw d'60' ;Pone 60 en W
subwf Minutos,W ;Resta Minutos - W, y lo guarda en W
btfsc STATUS,Z ;Salta si Z=0, o sea que Minutos es menor a 60
call Cambio_Horas ;Llama a la subrutina de cambio de horas
return ;Termina la subrutina y vuelve
;------------------------Actualizador de horas-------------------------------
Cambio_Horas
movlw 0x00 ;Pone 0 en W
movwf Minutos ;Pone W en Minutos
incf Horas ;Incrementa 1 hora
movlw d'25' ;Pone 60 en W
subwf Horas,W ;Resta Horas - W y lo guarda en W
btfss STATUS,Z ;Salta si Z=1, o sea que Horas es 25
return ;Termina la subrutina siendo Z=0
movlw 0x00 ;Pone 0 en W
movwf Horas ;Pone W en Horas
return ;Termina la subrutina
END ;Fin del programa
Quizas les parezca poco optimizado pero es que es uno de mis primeros programas :P
Muchisimas gracias, saludos
-
El timer en su cuenta es independiente de las instrucciones, es decir va a contar pulsos del oscilador ( dividido 4 ) pensalo como un contador por hardware,
Si uses o no interrupciones tenes un pequeño desfase.
Primero al producirse el overflow tenes un tiempo hasta que el micro ejecute la instruccion ubicada en 0x04. Luego tenes el salto, luego tenes que guardar W y STATUS ( en el datasheet esta el codigo de como hacerlo), luego preguntas por si fue la interrupcion del timer en caso que tengas otra, y recien alli podes "recargar" el timer.
Es decir todas esas instrucciones y tiempos tenes que tenerlo en cuenta al momento de tener la cuenta.
-----------
Si tuvieras un micro mas actual, los PICs traen un modulo que se llama CCP o Timers autorecargables, que automaticamente cuando se obtiene el tiempo programado el contador se resetea a 0 y comienza a contar de nuevo, Sin que vos lo recargues y sin sufrir lo que comente antes.
-------------
Pero creo que lo primero es tratar de hacerlo simple, es decir un timer a 10ms, contar la cantidad de interrupciones, etc, verificar que todo funcione, y recien alli empezar a ver que se cumpla correctamente lo del tiempo
PD:
http://eng-serve.com/pic/pic_timer.html
Calculadora de timer
Aunque te lo da en C, podes elegir las opciones y te dice el tiempo que tardaria. Sabiendo el preescaler + tiempo a cargar podes configurar tu timer como vos quieras.