¿Hay alguna manera de calcular milisegundos desde DS1307

2

Tengo un DS1307 y he hecho su programa y le he quitado tiempo. En mi programa tengo sec1,sec2 que contiene los dígitos de segundos e igual para min1,min2 & %código%. Estoy guardando todo en una variable hr1,hr2

TIME

Ahora sprintf(TIME,"%s%s:%s%s:%s%s",hr2,hr1,min2,min1,sec2,sec1); contiene el valor de TIME . Pero también necesito el valor de Hour, Minutes, Seconds .

¿Hay alguna lógica que pueda usar en el código o cualquier otra forma de calcular los valores para milliseconds

CÓDIGO PARA MilliSecond

 //MSECOND is variable to hold millisecond
   int count = 0;
    do
    {
        count++;
        sprintf(MSECOND,"%d",count);
        sprintf(TIME,"%s%s:%s%s:%s%s:%s",hr2,hr1,min2,min1,sec2,sec1,MSECOND);
        putsUART1("Time: ");
        putsUART1(TIME);
        putsUART1(" \n ");
    }while(count<=999);

EDIT

Esta pregunta hace referencia a mi pregunta anterior: ¿Dónde guardar el programa DS1307 para obtener un valor en tiempo real? . Estoy usando milliseconds MCU. No he publicado el código completo. Está en el enlace.

    
pregunta user007

2 respuestas

3

De acuerdo con la hoja de datos DS1307 el pin SQW / OUT puede producir una onda cuadrada a 1Hz, 4.096 kHz, 8.192 kHz, 32.768 kHz.

Las hojas de datos dicen:

  

REGISTRO DE CONTROL ...
  Bit 4: Habilitar onda cuadrada (SQWE). Este bit, cuando   configurado en lógica 1, habilita la salida del oscilador. La frecuencia de la   La salida de onda cuadrada depende del valor de los bits RS0 y RS1.   Con la salida de onda cuadrada ajustada a 1Hz, los registros del reloj se actualizan en   El borde descendente de la onda cuadrada. En la aplicación inicial de poder   para el dispositivo, este bit generalmente se establece en un 0.

Entonces, si tiene un pin MCU de repuesto, su sistema podría ingresar esa señal. AFAICT, esa señal / información no está disponible a través de I2C, es solo de hardware.

Aún depende de la precisión con la que necesite los milisegundos, y de la cantidad de procesador de repuesto que tenga, podría usar una de las señales de onda cuadrada de mayor frecuencia y dividirse a milisegundos en el software.

Un simple cambio binario (potencia de dos divisiones) sería barato, pero tendría un error del%. Una división más precisa necesitaría un poco más de procesamiento.

Editar:
¿Es este nivel de precisión suficiente para su propósito?

Hacer algo que lleva tiempo, y contar es una forma potencialmente frágil de controlar el tiempo. Su código no muestra nada que tenga algún tipo de restricción controlada por el tiempo que no sea la velocidad del UART. Como el código puede imprimir diferentes números de caracteres (por ejemplo, en putsUART1(TIME); ), entonces no va a ser muy preciso. Peor aún, si hay algún otro procesamiento que hacer, el bucle de tiempo se desviará, de manera imprevisible.

Cuando un sistema no tiene un reloj en tiempo real, normalmente usamos un temporizador de hardware, para mantener la hora razonablemente precisa. Sin embargo, tiene un reloj razonablemente preciso en el DS1307, y el único hardware necesario para rastrearlo es un pin de entrada con una interrupción.

Escribiste "Está funcionando, pero no sabes por qué falta 1 segundo, después de 34 segundos, salta directamente a 36 segundos".

Parece que falta el segundo 35 por completo. Eso no está funcionando realmente. Está imprimiendo algunos números, que parecen la secuencia correcta, pero eso no significa mucho. Es bastante fácil escribir un precio de código que cuente hasta 999 e imprima. Eso no significa que cada número haya tardado un milisegundo en aparecer.

Si desea obtener ayuda más específica, debe decirnos qué tan preciso debe ser el temporizador de milisegundos y qué otros procesadores y periféricos está utilizando su sistema.

Sólo he usado PIC32 de maneras muy triviales, hace años (cuando aparecieron por primera vez).

Sin embargo, el PIC32MX795F512L tiene un montón de temporizadores de hardware. Por lo tanto, estos podrían programarse para crear un temporizador de milisegundos estable y razonablemente preciso. Además de ser temporizadores, también pueden contar eventos externos. Por lo tanto, se podría usar un temporizador para sincronizar con el DS1307.

Sin embargo, solo programaría un temporizador para ser, digamos, un temporizador de 0,5 milisegundos, y ocasionalmente lo sincronizaría con el DS1307. Si el PIC32MX795F512L se está ejecutando desde un cristal, será razonablemente preciso. Lo dejé correr durante unas horas y lo comparé con el DS1307 para comprender la cantidad de desviación entre las dos fuentes de tiempo.

El uso del temporizador de hardware evitará el problema básico de usar un 'ciclo de ocupado' para obtener el tiempo.

    
respondido por el gbulmer
1

Hace un tiempo tuve la misma pregunta y mi solución actual (la más simple) es la siguiente:

  1. Asigne el pin SQW a un pin de interrupción (pin 2 y 3 de arduino);
  2. Establezca el DS1307 para generar la onda cuadrada a 1Hz;
  3. Escriba en la configuración attachInterrupt(digitalPinToInterrupt("pin number"),"ISR name",FALLING) (en mi caso, los segundos aumentan cuando cae la señal de sqw);
  4. En el ISR solo escriba timeref = millis() (timeref es un largo global sin firma);
  5. Finalmente, en tu código puedes hacer algo como esto:

Setup(){ tref = timeref; //needed in case timeref is updated meanwhile elapseref = millis(); (do some work); elapse = millis(); //in my case I want to index time to the previous work ReadRTC(); } void ReadRTC(){ byte tens; byte units; byte income; Wire.beginTransmission(rtc_addr); Wire.write(0); Wire.endTransmission(false); Wire.requestFrom(rtc_addr,7,true); elaspertc = millis(); for(byte i = 0; i<7; i++){ income = Wire.read(); tens = income >> 4; units = income & 15; rtdata[i+2] = tens * 10 + units; // milliseconds will be store on the 1st 2 } ms = (elapse - elapseref) / 2 + elapseref - tref; //the formula can be optimize but it can also lead to overflow. As mention, in my case, I want to index time to (do some work) s = elapsertc - tref; //It is needed to correct time case s is equal or greater then 1000 ms (1s) if(s>=1000){ if(ms>=1000){ ms -= 1000; } else{ rtcdata[2] -= 1 } } rtcdata[0] = ms >> 8; rtcdata[1] = ms & 255; }

Estoy trabajando con una tabla roja (arduino) pero en cualquier caso es para dar una idea. Espero que funcione para ti.

    
respondido por el Nuno Silveira

Lea otras preguntas en las etiquetas