¿Hay algún problema con el uso de las funciones de retardo al usar el oscilador interno en el PIC?

4

Estoy realizando un proyecto que requiere que el microcontrolador use las funciones delay_ms () (compilador CCS C) para esperar un período de tiempo determinado.

Estoy usando PIC 16f628A y mientras el programa se ejecutó como estaba previsto en Proteus, pero fue 85 veces más rápido que cuando lo probé en la pizarra.

Elegí configurar el oscilador interno a la frecuencia mínima posible (48 khz) para disminuir el consumo de energía y especifiqué que en el asistente y el archivo .h tienen la línea #uso retardo (interno = 48 kHz).

¿Qué estoy haciendo mal?

    
pregunta Ahmad Hani

3 respuestas

4

Summary:

Debe configurar OSCF (bit 3) en 0 en el registro PCON en su código (es decir, durante el tiempo de ejecución) cuando desee que el PIC INTOSC (Oscilador interno) se ejecute a una velocidad nominal de 48 kHz ( en realidad en cualquier lugar entre 31.4 kHz y 78.62 kHz) en lugar de la frecuencia predeterminada de encendido de INTOSC de 4 MHz.

Detalles :

  

Elegí configurar el oscilador interno a la frecuencia mínima posible (48 khz) para disminuir el consumo de energía y especifiqué que en el asistente y el archivo .h tienen la línea #uso retardo (interno = 48 kHz).

El problema es que ninguna de las cosas que usted enumera realmente configura el hardware de INTOSC a 48 kHz. Según lo que dijiste, parece que tu software asume que la CPU funcionará a 48 kHz, pero tu hardware seguirá funcionando a la frecuencia INTOSC de 4 MHz predeterminada.

  

el programa funcionó como estaba previsto en Proteus, pero fue aproximadamente 85 veces más rápido que cuando lo probé en el tablero.

Sí, eso es lo que espero.

85 más rápido x 48 kHz = 4 MHz (aprox.)

Este resultado sugiere que su MCU en realidad aún se está ejecutando a la frecuencia INTOSC predeterminada de 4 MHz.

El punto importante es que no puede configurar ese PIC para que se ejecute a 48 kHz desde el encendido . Si configura CONFIG BITS (a.k.a. Fuses) en una de las dos variantes de configuración de INTOSC, la MCU utilizará la frecuencia interna de 4 MHz en el encendido.

Luego, cuando desee cambiarlo a 48 kHz (tal vez al comienzo de su main() pero quizás en otra parte de su código (usted puede elegir) luego configure OSCF (bit 3) a 0 en el registro PCON - ese bit es lo que cambia la frecuencia INTOSC de 4 MHz a 48 kHz (después de una corta transición de conmutación).

Consultelasección14.2.8"FUNCIÓN ESPECIAL: MODOS DE OSCILADOR DE VELOCIDAD DUAL" en la página 101 de PIC16F628A hoja de datos para más detalles.

Tambiéntengaencuentaquelahojadedatosnoespecificalaprecisióndelrelojde48kHz(soloseespecificalaprecisióndelrelojde4MHz).Sinembargo,la PIC16F628A errata muestra que el reloj de 48 kHz puede variar entre 31.4 kHz y 78.62 kHz.

respondido por el SamGibson
0

Es posible que no ajuste correctamente el reloj. Puedes hacer la siguiente prueba:

  1. hacer una prueba de bucle while: while (1) {RB0 = 1; RB0 = 0;} Usa el osciloscopio para medir la velocidad. Cada instrucción tomaría 4 ciclos de reloj para ejecutarse si recuerdo correctamente. Si la velocidad es correcta, lo que significa que el reloj no tiene ningún problema. de lo contrario arregla la configuración del reloj.

  2. si el reloj es correcto, compruebe el código para la función de retardo. Adjunté un código que usé anteriormente para este chip:

Creo que obtuve el código fuente de: enlace

delay.c

/*
 *  Delay functions
 *  See delay.h for details
 *
 *  Make sure this code is compiled with full optimization!!!
 */

#include    "delay.h"

void
DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
    do {
        DelayUs(996);
    } while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ 
    unsigned char   i;
    do {
        i = 4;
        do {
            DelayUs(250);
        } while(--i);
    } while(--cnt);
#endif
}

retraso.h. Tenga en cuenta que debe definir el valor de XTAL_FREQ. en este ejemplo es 4MHz

/*
 *  Delay functions for HI-TECH C on the PIC
 *
 *  Functions available:
 *      DelayUs(x)  Delay specified number of microseconds
 *      DelayMs(x)  Delay specified number of milliseconds
 *
 *  Note that there are range limits: x must not exceed 255 - for xtal
 *  frequencies > 12MHz the range for DelayUs is even smaller.
 *  To use DelayUs it is only necessary to include this file; to use
 *  DelayMs you must include delay.c in your project.
 *
 */

/*  Set the crystal frequency in the CPP predefined symbols list in
    HPDPIC, or on the PICC commmand line, e.g.
    picc -DXTAL_FREQ=4MHZ

    or
    picc -DXTAL_FREQ=100KHZ

    Note that this is the crystal frequency, the CPU clock is
    divided by 4.

 *  MAKE SURE this code is compiled with full optimization!!!

 */

#ifndef XTAL_FREQ
#define XTAL_FREQ   4MHZ        /* Crystal frequency in MHz */
#endif

#define MHZ *1000L          /* number of kHz in a MHz */
#define KHZ *1          /* number of kHz in a kHz */

#if XTAL_FREQ >= 12MHZ

#define DelayUs(x)  { unsigned char _dcnt; \
              _dcnt = (x)*((XTAL_FREQ)/(12MHZ)); \
              while(--_dcnt != 0) \
                  continue; }
#else

#define DelayUs(x)  { unsigned char _dcnt; \
              _dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
              while(--_dcnt != 0) \
                  continue; }
#endif

extern void DelayMs(unsigned char);
    
respondido por el william
0

Usar delay_ms () siempre es crítico si quieres tener una sincronización precisa. Es difícil sin ver su código, pero probablemente su procesamiento demore demasiado. Un ejemplo simple:

while(1) {
  delay_ms(100);
  do_some_calculation();
  toggle_an_led();
}

Podría pensar que el LED cambiará cada 100 ms, pero si el cálculo toma por ejemplo 10 ms, el intervalo es de 110 ms. Incluso la activación de un LED influye en la sincronización.

Por lo tanto, si desea tener una sincronización precisa, use un temporizador de hardware y no delay_ms ().

    
respondido por el koalo

Lea otras preguntas en las etiquetas