Gibt es ein Problem bei der Verwendung von Verzögerungsfunktionen bei Verwendung des internen Oszillators in PIC?

Ich mache ein Projekt, bei dem der Mikrocontroller die Funktionen delay_ms () (Compiler CCS C) verwenden muss, um eine bestimmte Zeit zu warten.

Ich verwende PIC 16f628A und das Programm lief zwar wie vorgesehen in Proteus, aber es lief etwa 85-mal schneller als damals, als ich es auf dem Board ausprobierte.

Ich habe mich entschieden, den internen Oszillator auf die minimal mögliche Frequenz (48 kHz) einzustellen, um den Stromverbrauch zu senken, und ich habe dies im Assistenten angegeben, und so hat die .h-Datei die Zeile #use delay(internal=48kHz).

Was mache ich falsch ?.

Antworten (3)

Zusammenfassung:

Sie müssen OSCF(Bit 3) 0im PCONRegister in Ihrem Code (dh während der Laufzeit) auf setzen, wenn Sie möchten, dass der PIC INTOSC (Internal Oscillator) mit nominal 48 kHz (eigentlich irgendwo zwischen 31,4 kHz und 78,62 kHz) läuft Power-on INTOSC Standardfrequenz von 4 MHz.

Einzelheiten:

Ich habe mich entschieden, den internen Oszillator auf die minimal mögliche Frequenz (48 kHz) einzustellen, um den Stromverbrauch zu senken, und ich habe dies im Assistenten angegeben, und so hat die .h-Datei die Zeile #use delay(internal=48kHz).

Das Problem ist, dass keines der Dinge, die Sie auflisten, die INTOSC- Hardware tatsächlich auf 48 kHz einstellt. Basierend auf dem, was Sie gesagt haben, scheint Ihre Software davon auszugehen, dass die CPU mit 48 kHz läuft, aber Ihre Hardware wird immer noch mit der standardmäßigen INTOSC-Frequenz von 4 MHz laufen.

Das Programm lief wie vorgesehen in Proteus, aber es lief etwa 85-mal schneller als damals, als ich es auf dem Board ausprobierte.

Ja, das erwarte ich.

85 schneller x 48 kHz = 4 MHz (ca.)

Dieses Ergebnis deutet darauf hin, dass Ihre MCU tatsächlich noch mit der Standard-INTOSC-Frequenz von 4 MHz lief.

Der wichtige Punkt ist, dass Sie diesen PIC nicht so konfigurieren können, dass er ab dem Einschalten mit 48 kHz läuft . Wenn Sie die CONFIG BITS (auch bekannt als Fuses) auf eine der beiden Varianten der INTOSC-Einstellung einstellen, verwendet die MCU beim Einschalten die interne 4-MHz-Frequenz.

Wenn Sie es dann auf 48 kHz umschalten möchten (vielleicht am Anfang Ihres Codes, main()aber vielleicht an anderer Stelle in Ihrem Code - es liegt an Ihnen zu wählen), setzen Sie dann OSCF(Bit 3) 0im PCONRegister auf - dieses Bit schaltet um INTOSC-Frequenz von 4 MHz bis 48 kHz (nach kurzem Umschaltübergang).


Auszug aus dem PIC16F628A-Datenblatt mit OSCF-Bit im PCON-Register


Siehe Abschnitt 14.2.8 „SONDERFUNKTION: DUAL-SPEED-OSZILLATORMODI“ auf Seite 101 des PIC16F628A-Datenblatts für weitere Details.


Auszug aus dem PIC16F628A-Datenblatt zum Umschalten der INTOSC-Geschwindigkeit


Beachten Sie auch, dass das Datenblatt die Genauigkeit des 48-kHz-Takts nicht angibt (dort wird nur die 4-MHz-Taktgenauigkeit angegeben). Die PIC16F628A-Errata zeigt jedoch , dass der 48-kHz-Takt tatsächlich zwischen 31,4 kHz und 78,62 kHz variieren kann.


PIC16F628A Errata für INTOSC bei 48 kHz


Das war das Problem, vielen Dank, ich sollte hinzufügen, dass es im CCS-Compiler eine Funktion gibt, die verwendet werden kann, ohne die Register zu schreiben ( setup_oscillator (OSC_48KHZ);)

Möglicherweise stellen Sie die Uhr nicht richtig ein. Sie können den folgenden Test machen:

  1. Führen Sie einen Schleifentest durch: while(1){RB0=1;RB0=0;} Verwenden Sie ein Oszilloskop, um die Geschwindigkeit zu messen. Jede Anweisung würde 4 Taktzyklen dauern, um ausgeführt zu werden, wenn ich mich richtig erinnere. Wenn die Geschwindigkeit stimmt, hat die Uhr kein Problem. Andernfalls korrigieren Sie die Uhreinstellung.

  2. Wenn die Uhr richtig ist, überprüfen Sie bitte den Code für die Verzögerungsfunktion. Ich habe einen Code angehängt, den ich zuvor für diesen Chip verwendet habe:

Ich glaube, ich habe den Quellcode von: http://www.alternatezone.com/electronics/dds.htm

Verzögerung.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
}

Verzögerung.h . Bitte beachten Sie, dass Sie den Wert von XTAL_FREQ definieren müssen. in diesem Beispiel sind es 4 MHz

/*
 *  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);
Leider habe ich kein Oszi.

Die Verwendung von delay_ms() ist immer kritisch, wenn Sie ein genaues Timing haben möchten. Es ist schwierig, ohne Ihren Code zu sehen, aber wahrscheinlich dauert Ihre Verarbeitung zu lange. Ein einfaches Beispiel:

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

Man könnte meinen, dass die LED alle 100 ms umschaltet, aber wenn die Berechnung beispielsweise 10 ms dauert, beträgt das Intervall eher 110 ms. Auch das Umschalten einer LED selbst hat Einfluss auf das Timing.

Wenn Sie also ein genaues Timing haben möchten, verwenden Sie lieber einen Hardware-Timer und nicht delay_ms().

Die Berechnung ist in meinem Code sehr minimal, setze buchstäblich nur einen Pin hoch und dann eine Funktion, die Verzögerungsms für Minites verwendet. Ich brauche das Timing nicht kritisch, aber zumindest ähnlich dem beabsichtigten Timing, könnte der Mikrocontroller fehlerhaft sein.