TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Trev en 11 de Octubre de 2009, 23:48:40
-
A ver si me pueden dar una mano con este problema uso el timer1 con crystal externo de 32768 Hz la simulación en proteus creo que esta perfecta porque hago dos breakpoint cuando ingreso a la interrupción del timer y cuando se actualiza la hora y me da un segundo exacto en ambos casos,no se que pasa cambie los cristales el de 4 MHz puse otro y lo mismo,lo puse mas cerca y lo mismo,puse uno de 20 MHz y lo mismo :(,cambie los de 32768 HZ y lo mismo ya no se que hacer es la primera vez que uso el timer1 con oscilador externo y hace 4 dias que estoy lidiando con este problema
#include <16f877a.h>
#use delay(clock=20000000)
#fuses HS,PUT,NOPROTECT,NOWDT,NOLVP
#byte portb=6
#byte portc=7
#byte portd=8
#include <flex_lcd.c>
#use standard_io(b,c)
//#use fast_io(b)
#define SEGUNDOS_EN_UNA_HORA 3600
#define SEGUNDOS_EN_UN_MINUTO 60
int32 Conta_Segundos=0,MomentoActual=0;
int32 Horas=0,Minutos=0,Segundos=0;
int set,flag_timer1;
byte last_b;
void Mi_Hora(void);
void Cambiar_Hora(int32 *Horas,int32 *Minutos);
void reset(void)
{
Conta_Segundos=0;
Momentoactual=0;
}
#INT_TIMER1
timer1_rsi()
{
set_timer1(32768);
++Conta_Segundos;
Mi_Hora();
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld ",Horas,Minutos,Segundos);
}
// Interrupcion RB4 - RB7 /////////////////////////////////////////////////////
#INT_RB
rb_isr()
{
byte changes;
changes=last_b^portb; //XOR.
last_b=portb;
if (bit_test(changes,5) && !bit_test(last_b,5))
{
lcd_gotoxy(6,2);
lcd_putc(".. "); //Indica que se va a incrementar las horas.
delay_ms(200);
lcd_gotoxy(6,2);
lcd_putc(" ");
delay_ms(200);
lcd_gotoxy(6,2);
lcd_putc(".. ");
if(set==1)
{
lcd_gotoxy(1,2);
lcd_putc(" .. "); // Indica que se van a incrementar los minutos
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" ");
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" .. ");
}
set+=1;
if (set==2)
set=0;
}
if (bit_test(changes,6) && !bit_test (last_b,6)) //INCREMENTAR.
{
Cambiar_hora(&Horas,&Minutos);
}
if (bit_test(changes,7) && !bit_test (last_b,7)) //DECREMENTAR.
{
Cambiar_hora(&Horas,&Minutos);
}
Conta_Segundos=(Minutos*60)+(Horas*3600)+Segundos;
bit_clear(portb,0); //Solo modifico el nibble bajo sin tocar el alto
bit_clear(portb,1); //y consigo escribir el port
bit_clear(portb,2);
bit_clear(portb,3);
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld ",Horas,Minutos,Segundos);
delay_ms(10);
set_timer1(32768);
}
// Programa Principal /////////////////////////////////////////////////////////
void Mi_Hora()
{
MomentoActual=Conta_Segundos;
Horas=MomentoActual/SEGUNDOS_EN_UNA_HORA;
MomentoActual%=SEGUNDOS_EN_UNA_HORA; //Guarda el resto de la división entera.
Minutos=MomentoActual/SEGUNDOS_EN_UN_MINUTO;
MomentoActual%=SEGUNDOS_EN_UN_MINUTO;
Segundos=MomentoActual;
if(Horas==24 && Minutos==0 && Segundos==0)
{
Horas=0;
Minutos=0;
Segundos=0;
reset();
}
}
void Cambiar_hora(int32 *Horas,int32 *Minutos)
{
if(set==0)
{
if(portb==0b10110000)
{
++*Minutos;
if(*Minutos==60){*Minutos=0;}
}
}
if(set==1)
{
if(portb==0b10110000)
{
++*Horas;
if(*Horas==24){*Horas=0;}
}
}
if(set==0)
{
if(portb==0b01110000)
{
if(*Minutos==0){*Minutos=60;}
--*Minutos;
}
}
if(set==1)
{
if(portb==0b01110000)
{
if(*Horas==0){*Horas=24;}
--*Horas;
}
}
}
void main(void)
{
lcd_init();
set_tris_b(0xf0);
port_b_pullups(TRUE);
portb=0xf0;
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);//el preescaler q va es 2.
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
set_tris_c(0b00000011);
set_tris_d(0x00);
lcd_gotoxy(1,1);
lcd_putc("Reloj Digital");
delay_ms(1500);
lcd_putc("\fHora 00:00:00 ");
lcd_gotoxy(1,2);
lcd_putc(" .. ");
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" ");
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" .. ");
delay_ms(250);
set_timer1(32768);
while(1)
{
}
}
-
A ver si me pueden dar una mano con este problema uso el timer1 con crystal externo de 32768 Hz la simulación en proteus creo que esta perfecta porque hago dos breakpoint cuando ingreso a la interrupción del timer y cuando se actualiza la hora y me da un segundo exacto en ambos casos,no se que pasa cambie los cristales el de 4 MHz puse otro y lo mismo,lo puse mas cerca y lo mismo,puse uno de 20 MHz y lo mismo :(,cambie los de 32768 HZ y lo mismo ya no se que hacer es la primera vez que uso el timer1 con oscilador externo y hace 4 dias que estoy lidiando con este problema
estas seguro que cuando cargar el timer con ese valor te da 1 segundo exacto? tengo otra pregunta si te parece tan importante la hora porque no dejas que de ello se encargue otro modulo especializado en eso?
-
Estoy segurisimo según creo o estoy loco? :oops: y sino fijate en la imagen del debug que hice en proteus entre impresiones consecutivas en display pasa un segundo exacto exacto ;fijate en el breakpoint que hice otros me recomendaron q sacara el printf de ahi y lo hiciera con flag pero haciendo eso no era exacto y con respecto a tu otra pregunta
1. Según creo esta el DS1307 pero viendo la hoja de datos su precición depende de la del cristal asique estoy en la misma
2.Aun siendo mejor no lo voy a conseguir estoy en la 2da ciudad de mi pais y tuve suerte de conseguir el cristal digo DS1307 y no saben que es me quieren dar un transistor me paso lo mismo que cuando traté de conseguir un motor DC.
Asique es lo que hay y tendrá que salir con esto a menos que alguien me quiera enviar uno y se agradeceria
Si quieres te paso el archivo del proteus asi lo debugeas tu mismo,Saludos y gracias.
-
Podrías subir un esquemático? La precarga del Timer esta bien, podrías usar lo que te aconsejo Suky también en la configuración del Timer1.
Saludos
-
Bien MLO voy a subir el archivo de proteus y el código para que lo debugees esta bueno lo que decia Suky de las banderas para casos en general pero probando ese código ya ni siquiera en el simulador era exacto asique sigo con el mio original,que a mi entender el simulador me indica que no hay errores.Gracias y nos vemos
-
Hola.
Me refería al diagrama esquemático de conexión.
-
Lo que pasa que mi método podrá adelantarse o atrasarse en 1 ciclo un par de 1us (Que el ojo humano nunca detectaría), pero los errores entre ciclos se cancelan, y en 10 min, 1h, 30hs no debería de visualizarse ningún error perceptible, esto porque no recargamos el timer. Es lo que intenté explicar en el otro hilo, pero... :?
Saludos!
-
Hola.
No quiero una foto de tu montaje Trev.
En la simulación marca la interrupción de 1 segundo correctamente, así que podría ser una falla en el hardware, por lo que seria recomendable que subas el diagrama esquemático del hardware, para revisar las conexiones y esas cosas, si puedes subir la foto también, pssss bien, eso ayudaría mucho para detectar mas fallos.
Saludos
-
Hola amigos,Suky creo que te refieres a T1_DIV_BY_2 pero poniendo esto interrupe cada 4 s en la ayuda dice:
Parameters:
mode values may be:
T1_DISABLED, T1_INTERNAL, T1_EXTERNAL, T1_EXTERNAL_SYNC
T1_CLK_OUT
T1_DIV_BY_1, T1_DIV_BY_2, T1_DIV_BY_4, T1_DIV_BY_8
constants from different groups may be or'ed together with |.
asique no es T1_DIV_BY_1/2. No es la fórmula asi? 1segundo=(65536/32768)*PREESCALER si P=1/2 da 1 y lo pongo como T1_DIV_BY_2
Bien no cargo el timer pero interrumpe cada 4s.
MLO adjunto la foto es un buen cablerio je
-
:shock: :shock: :shock:
jeje no pude ver el cristal!!
La idea es que el cristal de 32k768Hz este lo mas cerca posible a los pines correspondientes a T1OSO y T1OSI y que de ellos salgan los condensadores de 33pF a GND. Otra recomendación es el anillo de GND al rededor de los pines del oscilador. Hay veces que las proto nos juegan malas pasadas con los cristales -a mi también me ha pasado-
Saludos
-
Bueno mañana lo voy a emprolijar un poco porque ya es tarde al montaje porque puede haber capacidades parasitas pero ya hice eso y nada (lo acerque no lo emprolije) y ya les dije q los cap son de 27pF saludos
Mañana subo otra vez la foto la saco con mi celu
-
:oops: :oops: Estaba haciendo la cuenta mentalmente al revés :oops: Pido disculpas por ser tan necio y no haber estudiado bien el tema. :mrgreen:
Edit: Se podría combinar el timer con el módulo CCP en modo captura y evento especial (Todo en conjunto funcionaria de la manera que trabaja el timer2 con PR2) para generar la interrupción automática sin recarga del timer logrando mayor precisión.-
Saludos!
-
Voy a hacer una cosa; mañana emprolijo y cuando tenga plata me compro otro cristal en otro lugar si lo consigo y sino de última probamos con tu otra forma Suky que ni idea porque nunca use el timer2,es el cristal ¿y que? cuando quiera usar el DS1307 lo voy a tener que conectar = asique es frustrantre :(
-
Yo no creo que sea el cristal, jamás me he encontrado con un cristal que falle.
Yo apuesto a que el error está en el código. Y lo digo por lo siguiente: desde que el micro salta a la interrupción hasta que ejecuta la precarga para la siguiente interrupción hay varios ciclos de reloj, especialmente lo referido al guardado de contexto y alguna operación más. Si quieres examina el código ASM que genera tu programa para comprobar el montón de instrucciones que hay antes del set_timer().
Una vez llegado a la precarga, tú le estableces un salto de 32768 ciclos y por lo tanto la duración será de 32768+el tiempo perdido anteriormente.
Si no estoy equivocado, con ese programa, el reloj atrasará en lugar de adelantar.
Y respecto a que en Proteus no se vea ese efecto puede ser por dos razones:
- sólo tienes precisión de 4 decimales. Si hubiera un error de 99 microsegundos no lo verías
- no es la primera vez que Proteus falla
-
El hecho es que adelanta por lo tanto no es cierto lo que dices y fijate en los breakpoint que trazo en proteus.
-
Ademas la diferencia no esta en el orden de los µs sino en los milisegundos adelanta 6 min en 12 hs = se agradece la respuesta
-
Yo sigo pensando que ese programa debe retrasar. A ver si hay algún problema con las divisiones y los decimales que tienes en la función que reparte los segundos entre horas y minutos.
¿Puedes hacer una prueba?: no hagas ninguna operación con la variable "momento_actual". Déjala incrementarse indefinidamente y cuando pase una hora justa comprueba si su valor es 3600 justos. Apuesto a que la cifra va a ser menor a 3600.
-
Analizando un poco como trabaja el sistema todo indica que debería de atrasar tal como comenta Nocturno!
Paso a paso seria, el timer1 cuenta la entrada de una señal externa de 32768Hz, osea un periodo de 30.5us. Entonces cuando se produce la interrupción por overflow se tiene 30us para actualizar el timer y así no perder un ciclo en la cuenta, y esto con un cristal de 4MHz vamos a estar un poco ajustados (Por experiencia el guardado de contexto ronda alrededor de los 50 ciclos) así que lo recomendable sería un cristal de 20 MHz. Luego para el timer0 cuando se realiza una escritura este se inhibe durante 2 ciclos, pero en el datasheet no encontré nada de esto referido al Timer1, pero igual me queda la duda :?
Sería bueno que realices la prueba que comenta Nocturno, porque por mas vueltas que se le de no se ve porque adelante, y es raro que el cristal este fuera de frecuencia :undecided:
Saludos!
-
Hola.
Pues los cristales de 32k768Hz si que son sensibles al calor, hay que soldarlos rápido no mas para evitar estar cambiándolos jejeje. Coincido con Suky, sería mejor aumentar el valor del cristal del oscilador general, para no aumentar el error en tiempo en la gestión de la interrupción.
Saludos
-
Bien muchachos estoy enfermo hoy aguantenme un dia y si puse cristal de 20 MHz y lo que dice nocturno son 3 intrucciones de carga del timer que son
MOVLW 80
MOVWF 0F
CLRF 0E
a 20 megas son 600 ns ahh y otra cosa y hablando a la ligera mire el asm y parece que solo al final de las interrupciones limpia las banderas y recupera los registros imp según creo pero no parece salvarlos,lo vi a la ligera no loestudie pero me parecio eso,mos vemos mañana.
-
:shock: No solo eso, esta el guardado de contexto. Buscar información sobre interrupciones, manejo de interrupciones, etc. ;-)
-
Efectivamente, lo que más consume es el guardado del contexto.
Que te recuperes
-
Gracias viejo era una migraña nomas y Suky ya se a lo que te refieres al salvado de los registros importantes como STATUS Y W solo que no le dimos ese nombre en mi escuela y son estas:
0000: MOVLW 00
0001: MOVWF 0A
0002: GOTO 5A2
0003: NOP
0004: MOVWF 7F
0005: SWAPF 03,W
0006: CLRF 03
0007: MOVWF 21
0008: MOVF 0A,W
0009: MOVWF 20
000A: CLRF 0A
000B: MOVF 04,W
000C: MOVWF 22
000D: MOVF 77,W
000E: MOVWF 23
000F: MOVF 78,W
0010: MOVWF 24
0011: MOVF 79,W
0012: MOVWF 25
0013: MOVF 7A,W
0014: MOVWF 26
0015: MOVF 7B,W
0016: MOVWF 27
0017: BCF 03.7
0018: BCF 03.5
0019: BTFSS 0B.3
001A: GOTO 01D
001B: BTFSC 0B.0
001C: GOTO 036
001D: MOVLW 8C
001E: MOVWF 04
001F: BTFSS 00.0
0020: GOTO 023
0021: BTFSC 0C.0
0022: GOTO 039
0023: MOVF 22,W
0024: MOVWF 04
0025: MOVF 23,W
0026: MOVWF 77
0027: MOVF 24,W
0028: MOVWF 78
0029: MOVF 25,W
002A: MOVWF 79
002B: MOVF 26,W
002C: MOVWF 7A
002D: MOVF 27,W
002E: MOVWF 7B
002F: MOVF 20,W
0030: MOVWF 0A
0031: SWAPF 21,W
0032: MOVWF 03
0033: SWAPF 7F,F
0034: SWAPF 7F,W
0035: RETFIE
asique son 53 + las 3 de carga del timer son 56/5 µs de retraso 11.2 µs de retraso por segundo y no se veria en el proteus porque tiene presición de 4 decimales pero con eso deben pasar casi 100.000 segundos para q retrase un segundo o sea un segundo de retraso cada un poquito mas de un dia y es aceptable tampoco podemos pretender perfeccion absoluta
ademas que si o si se tienen que ejecutar.
-
mmm... mira el análisis que hice unos mensajes anteriores y te darás cuenta que si usas 20MHz, alcanzas a actualizar el timer antes de que llegue el siguiente pulso :|
-
Hola :) Nocturno:
Yo no creo que sea el cristal, jamás me he encontrado con un cristal que falle.
El hecho es que falla y esta adelantando como 300 Hz y es este,el de 20 MHz no tiene nada q ver o poco.
No hay otra forma de explicar que adelante!!.
Pero creo que estamos de acuerdo en algunos puntos:
desde que el micro salta a la interrupción hasta que ejecuta la precarga para la siguiente interrupción hay varios ciclos de reloj, especialmente lo referido al guardado de contexto y alguna operación más.
Una vez llegado a la precarga, tú le estableces un salto de 32768 ciclos y por lo tanto la duración será de 32768+el tiempo perdido anteriormente.
Asique como esto es inevitable (a menos que se pueda cambiar el orden de ejecución,o sea que primero se salve W y se cargue el timer y solo serian 1000 ns,pero el compilador realiza automaticamente esto asique es inmutable) con este método y si o si hay q cargar el timer porque no hay preescaler 1:2 en el mejor de los casos se logra que retrase 6 minutos por año y con este valor porque tampoco se puede compensar porque
el timer1 cuenta la entrada de una señal externa de 32768Hz, osea un periodo de 30.5us.
porque son 11 µs a 20 mHz y no podria poner por ejemplo set_timer1(32769) porque me paso y ya adelantaria salvo q use un cristal de 8 MHz entonces la perdida de tiempo ya estaria cerca de los 30,5 se perderia una cuenta y la compensaria sumandole a la carga del timer.
Ya emprolije todo y sigue = voy a hacer lo que planteas Nocturno y despues cuento
no hagas ninguna operación con la variable "momento_actual". Déjala incrementarse indefinidamente y cuando pase una hora justa comprueba si su valor es 3600 justos. Apuesto a que la cifra va a ser menor a 3600.
y sino de lutima pasare a lo que planteas Suky:
Se podría combinar el timer con el módulo CCP en modo captura y evento especial (Todo en conjunto funcionaria de la manera que trabaja el timer2 con PR2) para generar la interrupción automática sin recarga del timer logrando mayor precisión.-
Paro lo cual vendria bien que esboces un ejemplo
Todo esto biene despues que logre que atrase y no q adelante,Nos vemos ;-)
-
Todavía no logras entender como trabaja o no logre explicarme aquí:
Analizando un poco como trabaja el sistema todo indica que debería de atrasar tal como comenta Nocturno!
Paso a paso seria, el timer1 cuenta la entrada de una señal externa de 32768Hz, osea un periodo de 30.5us. Entonces cuando se produce la interrupción por overflow se tiene 30us para actualizar el timer y así no perder un ciclo en la cuenta, y esto con un cristal de 4MHz vamos a estar un poco ajustados (Por experiencia el guardado de contexto ronda alrededor de los 50 ciclos) así que lo recomendable sería un cristal de 20 MHz. Luego para el timer0 cuando se realiza una escritura este se inhibe durante 2 ciclos, pero en el datasheet no encontré nada de esto referido al Timer1, pero igual me queda la duda :?
Sería bueno que realices la prueba que comenta Nocturno, porque por mas vueltas que se le de no se ve porque adelante, y es raro que el cristal este fuera de frecuencia :undecided:
Saludos!
Los 30.5 us es el periodo de la señal que ingresa al timer1 y que cuenta, por eso con lo que detalle saco la conclusión de que es mejor un cristal de 20MHz.
Llegaste a hacer la prueba que indico Nocturno?
Después la opción del combinar CCP con el timer si el problema es la frecuencia del oscilador estamos en las mismas :?
Saludos!
-
Y ahora que lo pienso, ¿porqué no usas el Timer2?
Si le pones un prescaler de 1:16 y un postcaler de 1:8 tendrás 32768 / 16 / 8 = 256 ticks por segundo.
El Timer2 es de 8 bits y desbordaría cada segundo sin tener que precargar nada.
-
Yo estoy convencido que con el TIMER1 se puede hacer perfectamente.
Configurando correctamente el preescaler se pueden obtener tiempos de interrupción, para ese cristal de 32768 de:
Preescaler Tint
1:1 500ms
1:2 1000ms
1:4 2000ms
1:8 4000ms
No hay que estar escribiendo en el registro del TIMER, cosa nada recomendable, ya que se presentan los siguientes problemas
Al escribir el registro, no se puede escribir en TMR1L porque esta acción implica la pérdida de dos ciclos de máquina completos en resincronizar el reloj del temporizador.
Se elimina el tiempo contado por el temporizador desde que se desbordó hasta que se escribió, porque el contador cuenta aún después de desbordarse y pedir INT, la latencia de la interrupción puede ser variable, así que este tiempo no podemos conocerlo a ciencia cierta.
Sería conveniente sólo escribir en TMR1H, tiempo antes que TMR1L se desborde, de modo que no haya problemas con la temporización. Recordemos que TMR1H se incrementa con cada desbordamiento de TMR1L.
Así que lo mejor es no tocar el timer, sino configurarlo correctamente.
Aquí un enlace a un trabajo que no he terminado, pero que puede aclarar algunas cosas:
TIMER1 en los microcontroladores PIC. Ajuste por software del periodo de desbordamiento (http://www.wikitronica.net/index.php/TIMER1_en_los_microcontroladores_PIC._Ajuste_por_software_del_per%C3%AD%C2%ADodo_de_desbordamiento)
saludos
Reinier
-
Configurando correctamente el preescaler se pueden obtener tiempos de interrupción, para ese cristal de 32768 de:
Preescaler Tint
1:1 500ms
1:2 1000ms
1:4 2000ms
1:8 4000ms
Estas cometiendo el mismo error mio, sin cargar el timer sería:
Preescaler Tint
1:1 2000ms
1:2 4000ms
1:4 8000ms
1:8 16000ms
Ahora con respecto a escribir el timer se pierden 2 ciclos maquinas, si ese fuese el caso no habría problemas, pero se pierden en este caso que usa una fuente externa? (2 ciclos de la fuente externa) Igual si fuera el caso creo que no responde al adelanto que presenta el reloj :?
Saludos!
-
Si el TIMER1 es de 16 bits y el período de reloj para el cristal externo del que se habla es de 32768Hz, en un segundo se producen desbordamientos según la siguiente expresión (2^16)/32768 que da exactamente 2, lo que significa que el timer se desbordará dos veces en 1 segundo, por lo que su período es de 0.5s que es lo mismo que 500ms y así sucesivamente.
Saludos
Reinier
PD: He arreglado este post para que se entienda mejor
-
:shock: El cristal es de 32768 Hz, osea que el timer contará 32768 pulsos por segundo, y como es de 16bits, el desbordamiento ocurre a 216=65536, osea que deben pasar 2 segundos :mrgreen:
Saludos!
-
Si Suki, tienes razón, es evidente que hoy ando confundi'o
-
Ya esta amigos no se peleen mas por el timer1 que no da para mas el asunto no pude eliminar el adelantamiento es mejor pasar al timer2 y asi no depender de un cristal que evidentemente no son de confianza,hoy si puedo subo el ejemplo terminado,nos vemos :)
-
Nunca nos peleamos! Todo es para ir aprendiendo un poquito cada día. Es lo bueno del foro que todos aportan sin ningún interés tratando de resolver el problema ;-)
Saludos!
-
Me confundí parece que Nocturno habla como si el timer 2 fuera un contador con cristal externo ¿pero como se configura? la ayuda no dice nada o estamos los dos confundidos? :?
-
Yo hice un reloj con TIMER1 que funcionó durante dos meses sin interrupción y no se adelantó ni atrasó (al menos sisiblemente). Claro, utilicé TIMER1+CCP. Si quieres me das un correo y mañana cuando pase por la casa te mando el proyecto completo. Está en hecho C de CCS y hay simulación para Proteus.
saludos
Reinier
-
Yo hice un reloj con TIMER1 que funcionó durante dos meses sin interrupción y no se adelantó ni atrasó (al menos sisiblemente). Claro, utilicé TIMER1+CCP. Si quieres me das un correo y mañana cuando pase por la casa te mando el proyecto completo. Está en hecho C de CCS y hay simulación para Proteus.
saludos
Reinier
Hola amigo mejor subelo al foro, para que cuando alguien presente este mismo problema sepa como solucionarlo! y asi no te tenga que mandar un MP para que tambien le reenvies el documento....
Respecto al tema siempre me he dado cuenta que proteus es una cosa muy distinta simulando en C, a veces coincide pero cuando el tiempo es muy importante casi nunca es exacta, y lo he comprobado! los erros son en msegundos, con osciloscopio de laboratorios especializados de la U y computador core 2 duo 2 gigas de ram y un pwm.
Conclusion si tienes un osciloscopio a la mano trata de ver ese pulso y sales de duda.
Otra es volver a ASM :? (ya hasta se me olvido pasar de banco :mrgreen:) y controlar esas instrucciones al maximo.
pero estoy casi completamente seguro que el error esta en codigo..
-
Hola,despues de un tiempo se pudo solucionar el problema no habia ningún error en el programa ni en el proteus,era el maldito cristal y la protoboard,cambié todo de lugar y pasado 1 dia de prueba no adelanta ni atrasa ni un minuto,tambien modifique el programa para eliminar la precarga del timer1 con el módulo CCP en modo captura,en fin solucionado :-/
-
jeje no pude ver el cristal!!
La idea es que el cristal de 32k768Hz este lo mas cerca posible a los pines correspondientes a T1OSO y T1OSI y que de ellos salgan los condensadores de 33pF a GND. Otra recomendación es el anillo de GND al rededor de los pines del oscilador. Hay veces que las proto nos juegan malas pasadas con los cristales -a mi también me ha pasado-
Me lo imaginaba ... es que las protoboard a veces dan malas pasadas.
Que bueno que ya este bien.
Saludos
-
Y respecto a que en Proteus no se vea ese efecto puede ser por dos razones:
- sólo tienes precisión de 4 decimales. Si hubiera un error de 99 microsegundos no lo verías
- no es la primera vez que Proteus falla
Si MLO yo confiaba en el proteus y no me falló eso es lo mejor de esto es bueno poder confiar en el sino todo se vuelve muy entropico,hay q dudar primero del harware antes del proteus,nos vemos y ahora me gustaría agregarle una función de alarma cuando tenga tiempo,nos vemos :-/ aca dejo el código definitivo
#use delay(clock=20000000)
#fuses HS,PUT,NOPROTECT,NOWDT,NOLVP
#byte portb= 6
#byte portc= 7
#byte portd= 8
#include <flex_lcd.c>
#use standard_io(b,c)
//#use fast_io(b)
#define SEGUNDOS_EN_UNA_HORA 3600
#define SEGUNDOS_EN_UN_MINUTO 60
int32 Conta_Segundos=0,MomentoActual=0;
int32 Horas=0,Minutos=0,Segundos=0;
int set,flag_timer1;
byte last_b;
void Mi_Hora(void);
void Cambiar_Hora(int32 *Horas,int32 *Minutos);
void reset(void)
{
Conta_Segundos=0;
Momentoactual=0;
}
#INT_CCP1
CCP1_rsi()
{
Conta_Segundos+=1;
Mi_Hora();
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld ",Horas,Minutos,Segundos);
}
#INT_RB
rb_isr()
{
byte changes;
changes=last_b^portb; //XOR.
last_b=portb;
if (bit_test(changes,5) && !bit_test(last_b,5))
{
lcd_gotoxy(6,2);
lcd_putc(".. "); //Indica que se va a incrementar las horas.
delay_ms(200);
lcd_gotoxy(6,2);
lcd_putc(" ");
delay_ms(200);
lcd_gotoxy(6,2);
lcd_putc(".. ");
if(set==1)
{
lcd_gotoxy(1,2);
lcd_putc(" .. "); // Indica que se van a incrementar los minutos
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" ");
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" .. ");
}
set+=1;
if (set==2)
set=0;
}
if (bit_test(changes,6) && !bit_test (last_b,6)) //INCREMENTAR.
{
Cambiar_hora(&Horas,&Minutos);
}
if (bit_test(changes,7) && !bit_test (last_b,7)) //DECREMENTAR.
{
Cambiar_hora(&Horas,&Minutos);
}
Conta_Segundos=(Minutos*60)+(Horas*3600)+Segundos;
portb=0x00;
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld ",Horas,Minutos,Segundos);
delay_ms(10);
set_timer1(0);
}
// Programa Principal /////////////////////////////////////////////////////////
void Mi_Hora()
{
MomentoActual=Conta_Segundos;
Horas=MomentoActual/SEGUNDOS_EN_UNA_HORA;
MomentoActual%=SEGUNDOS_EN_UNA_HORA; //Guarda el resto de la división entera.
Minutos=MomentoActual/SEGUNDOS_EN_UN_MINUTO;
MomentoActual%=SEGUNDOS_EN_UN_MINUTO;
Segundos=MomentoActual;
if(Horas==24 && Minutos==0 && Segundos==0)
{
Horas=0;
Minutos=0;
Segundos=0;
reset();
}
}
void Cambiar_hora(int32 *Horas,int32 *Minutos)
{
if(set==0)
{
if(portb==0b10110000)
{
++*Minutos;
if(*Minutos==60){*Minutos=0;}
}
}
if(set==1)
{
if(portb==0b10110000)
{
++*Horas;
if(*Horas==24){*Horas=0;}
}
}
if(set==0)
{
if(portb==0b01110000)
{
if(*Minutos==0){*Minutos=60;}
--*Minutos;
}
}
if(set==1)
{
if(portb==0b01110000)
{
if(*Horas==0){*Horas=24;}
--*Horas;
}
}
}
void main(void)
{
lcd_init();
set_tris_b(0xf0);
port_b_pullups(TRUE);
portb=0xf0;
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
set_tris_c(0b00000011);
set_tris_d(0x00);
lcd_gotoxy(1,1);
lcd_putc("Reloj Digital");
delay_ms(1500);
lcd_putc("\fHora 00:00:00 ");
lcd_gotoxy(1,2);
lcd_putc(" .. ");
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" ");
delay_ms(250);
lcd_gotoxy(1,2);
lcd_putc(" .. ");
delay_ms(250);
setup_timer_1(T1_EXTERNAL |T1_DIV_BY_1 |T1_CLK_OUT);
enable_interrupts(INT_CCP1);
setup_ccp1(CCP_COMPARE_RESET_TIMER);
CCP_1=32768;
while(1)
{
}
}
-
Me alegro que lo hayas resuelto.
Pero no confíes en Proteus 100% aunque en esta ocasión te haya dado la razón, falla mucho.
-
Ok Nocturno seria bueno q abras un hilo sobre eso asi nos prevenimos,gracias por tu aporte ahh y los otros dias q nos quedamos sin este foro andube chusmeando por tu pagina esta buena, Salu2 ;-)
-
Juraría que había un hilo abierto en el que se publicaron los principales errores detectados, pero lo he estado buscando y no lo encuentro.
Gracias por lo de la página.
-
Y que tal es el HT1380?me lo acabo de comprar tenia intenciones de usar un DS3232 pero fue imposible conseguirlo :5] alguien ha usado este chip estaria piola q me contaran sus experiencias mientras estoy aprendiendo i2c q no se nada pero si alguno lo ha usado me gustaria saber q onda,bye