Estoy haciendo un proyecto que requiere tener el microcontrolador para usar las funciones delay_ms() (compilador CCS C) para esperar un tiempo determinado.
Estoy usando PIC 16f628A y, aunque el programa se ejecutó según lo previsto en Proteus, se ejecutó unas 85 veces más rápido que cuando lo probé en la placa.
Elegí configurar el oscilador interno a la frecuencia mínima posible (48 khz) para disminuir el consumo de energía y lo especifiqué en el asistente, por lo que el archivo .h tiene la línea #use delay(internal=48kHz).
Qué estoy haciendo mal ?.
Resumen:
Debe configurar OSCF
(bit 3) 0
en el PCON
registro de su código (es decir, durante el tiempo de ejecución) cuando desee que el PIC INTOSC (oscilador interno) se ejecute a 48 kHz nominales (en realidad, entre 31,4 kHz y 78,62 kHz) en lugar del frecuencia predeterminada de encendido 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 lo especifiqué en el asistente, por lo que el archivo .h tiene la línea #use delay(internal=48kHz).
El problema es que ninguna de las cosas que enumera realmente configuran el hardware INTOSC a 48 kHz. Según lo que dijo, parece que su software asume que la CPU se ejecutará a 48 kHz, pero su hardware seguirá funcionando a la frecuencia INTOSC predeterminada de 4 MHz.
el programa funcionó según lo previsto en Proteus pero funcionó unas 85 veces más rápido que cuando lo probé en la placa.
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 todavía se estaba ejecutando en 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 los BITS DE CONFIGURACIÓN (también conocidos como Fusibles) en una de las dos variantes de la configuración INTOSC, entonces la MCU utilizará la frecuencia interna de 4 MHz al encenderse.
Luego, cuando desee cambiarlo a 48 kHz (quizás al comienzo de su main()
pero quizás en otra parte de su código; depende de usted elegir), luego configure OSCF
(bit 3) en 0
el PCON
registro: ese bit es lo que cambia el Frecuencia INTOSC de 4 MHz a 48 kHz (después de una breve transición de conmutación).
Consulte la sección 14.2.8 "FUNCIÓN ESPECIAL: MODOS DE OSCILADOR DE VELOCIDAD DOBLE" en la página 101 de la hoja de datos PIC16F628A para obtener más detalles.
También tenga en cuenta que la hoja de datos no especifica la precisión del reloj de 48 kHz (solo se especifica allí la precisión del reloj de 4 MHz). Sin embargo, la errata de PIC16F628A muestra que el reloj de 48 kHz en realidad puede variar entre 31,4 kHz y 78,62 kHz.
Es posible que no ajuste correctamente el reloj. Puedes hacer la siguiente prueba:
haz una prueba de bucle while: while(1){RB0=1;RB0=0;} Usa un osciloscopio para medir la velocidad. Cada instrucción tomaría 4 ciclos de reloj para ejecutarse si no recuerdo mal. Si la velocidad es correcta, significa que el reloj no tiene problema. de lo contrario, corrija la configuración del reloj.
si el reloj es correcto, verifique el código para la función de retraso. Adjunté un código que usé anteriormente para este chip:
Creo que obtuve el código fuente de: http://www.alternatezone.com/electronics/dds.htm
retraso.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
}
demora.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);
El uso de delay_ms() siempre es fundamental si desea tener una sincronización precisa. Es difícil sin ver su código, pero probablemente su procesamiento lleve demasiado tiempo. Un ejemplo sencillo:
while(1) {
delay_ms(100);
do_some_calculation();
toggle_an_led();
}
Puede pensar que el LED cambiará cada 100 ms, pero si el cálculo toma, por ejemplo, 10 ms, el intervalo es más bien 110 ms. Incluso alternar un LED en sí mismo tiene una influencia en el tiempo.
Entonces, si desea tener una sincronización precisa, use un temporizador de hardware y no delay_ms().
Ahmad Hani