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 ?.
Zusammenfassung:
Sie müssen OSCF
(Bit 3) 0
im PCON
Register 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) 0
im PCON
Register auf - dieses Bit schaltet um INTOSC-Frequenz von 4 MHz bis 48 kHz (nach kurzem Umschaltübergang).
Siehe Abschnitt 14.2.8 „SONDERFUNKTION: DUAL-SPEED-OSZILLATORMODI“ auf Seite 101 des PIC16F628A-Datenblatts für weitere Details.
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.
Möglicherweise stellen Sie die Uhr nicht richtig ein. Sie können den folgenden Test machen:
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.
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);
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().
Ahmed Hani