Forum: Mikrocontroller und Digitale Elektronik Delay Funktion für Freescale


von Markus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo! Verwende einen Freescale MC.
Will einen Delay funktion schreiben, habe ein bischen gegoogelt und eine 
Delay Funktion gefunden. Kann mir die jemand erklären, wenn möglich auch 
vorrechnen. Habe das probiert, es häbgt ein 4Mhz Quarz dort, wenn ich 
delay (1000) teste komme ich auf ca. 1,4s- möchte aber eine sekunde...

Die Einstellungen sind im Datenblatt ab seite 135 beschrieben

// Clear COP Watchdog timeout
  SOPT1 = 0x00;
// Select FBE MCG mode (IREFS=0, CLKS=10)
  MCGC1 = 0xB8;
// LP=0 and selects external high frequency crystal clock 
MCGC2 = 0x36;
// PLLS=0
  MCGC3 = 0x00;
// Wait until the initialization cycle of the external crystal clock is 
completed
  while(!(MCGSC&0x02))


#define BUS_CLOCK 4000

void delay (unsigned int time)
{
unsigned int temp;
for(;time;time--) for(temp=(BUS_CLOCK/23);temp;temp--);
}

von Karl H. (kbuchegg)


Lesenswert?

1
#define BUS_CLOCK 4000
2
3
void delay (unsigned int time)
4
{
5
unsigned int temp;
6
for(;time;time--) for(temp=(BUS_CLOCK/23);temp;temp--);
7
}
Dieser Code ist hochgradig davon abhängig, was dein Compiler daraus 
macht. Das hängt wiederrum von der Compilerversion und ganz speziell von 
den Optimierungen abhängig, die der Compiler macht.
Ein guter optimizing Compiler, übersetzt das zb so, als ob da
1
void delay (unsigned int time)
2
{
3
}

stehen würde.

-> Das ist eine ziemlich schlechte Methode um delay-Zeiten zu 
generieren. Wenn du sie aber benutzen willst, dann mach es wenigstens so
1
void delay (unsigned int time)
2
{
3
  volatile unsigned int temp;
4
5
  for(;time;time--)
6
    for(temp=(BUS_CLOCK/23);temp;temp--)
7
      ;
8
}

und dann musst du die 23 anpassen, bis die Zeiten stimmten (oder im 
Assembleroutput nachsehen, wieviele Taktzyklen für einen Durchlauf der 
innersten Schleife benötigt werden. Aber auch dann wird die Zeit nicht 
exakt stimmen.

von Markus (Gast)


Lesenswert?

hallo! danke für die antwort, kannst du mir das jetzt noch vorrechnen 
wie man auf die zeit kommt? danke
markus

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> hallo! danke für die antwort, kannst du mir das jetzt noch vorrechnen
> wie man auf die zeit kommt?

Nein, kann ich nicht.
Das hängt wie gesagt davon ab, wie der Compiler
1
    for(temp=(BUS_CLOCK/23);temp;temp--)
2
      ;

umsetzt. Die 23 da drinnen werden wohl so zustande gekommen sein, dass 
sich jemand den vom Compiler generierten Assembler-output angesehen hat 
und abgezählt hat, wieviele Prozessortakte bei einem Durchlauf 
verbraucht werden.

Dieser Code wurde empirisch zusammengestellt und nicht indem irgendetwas 
berechnet wurde.

von Markus (Gast)


Lesenswert?

okay dann frage ich anders:
wie wird eine Delay funktion geschrieben, auf was muss alles geachtet 
werden? Danke
Markus

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> okay dann frage ich anders:
> wie wird eine Delay funktion geschrieben,

Die einfache Antwort ist:
gar nicht

delay benutzt man (auser in seltenen Ausnahmefällen) höchstens für kurze 
Zeiten und auch dann nur, wenn die Zeit nicht sehr kritisch ist und es 
nichts ausmacht, wenn es mal wieder etwas länger dauert.

Für genaues Timing bzw. längere Wartezeiten benutzt man Timer im 
Zusammenspiel mit Interrupts. Denn dann kann der µC auch mal 
zwischendurch sich um andere Dinge kümmern anstatt nur stupide die Zeit 
runterzuzählen.

von Oliver R. (superberti)


Lesenswert?

Hi,

ich benutze bei meinem MC9S08QG8 immer folgenden Code. Das sollte 
eigentlich auch auf Deinem MC laufen und ist durch den asm-Teil nicht so 
compilerabhängig:

// For the wait and delay functions
#define FREQ_BUS              8000000  // 8 MHz
#define NUM_BUS_CYCLES        (FREQ_BUS * 100)/1000000
#define DELAY_X_VALUE         (((((NUM_BUS_CYCLES - 6)*10)/4)+5)/10)-1


void Delay_100us (unsigned char hundreds_us)
{
  asm
  {
    lda hundreds_us
    beq exit
    delay_us:
      ldx #DELAY_X_VALUE          ; [2]
    loop:
      dbnzx loop                  ; [4]
    dbnza delay_us                ; [4]
    exit:
  }
}

void Wait_ms(unsigned int aWait_ms)
{
  unsigned int i;
  for (i=0;i<aWait_ms;i++)
    Delay_100us(10);
}

von Olaf (Gast)


Lesenswert?

> okay dann frage ich anders:
> wie wird eine Delay funktion geschrieben, auf was muss alles geachtet
> werden?

Am besten ist es du benutzt einen Timer und laesst damit einen
IRQ erzeugen. Also z.b alle 10ms wird ein Interrupt aufgerufen.

In der Interruptfunktion wird dann eine Variable immer dekrementiert
wenn sie nicht null ist.


In deinem Hauptprogramm setzt du diese Variable auf einem Wert groesser
Null. Und wartest dann danach bis sie null erreicht.

Das hat den Vorteil das die Zeit genau stimmt und eben nicht von seinem
Compiler und seinen Optimierungen abhaengt. Und sich auch nicht aendert
wenn dein Hauptprogramm von einem Interrupts unterbrochen wird.

Ausserdem wenn du eine bestimmte Zeit, sagen wir mal 50ms warten willst,
dann kannst du zwischen dem Timerstart und dessen Ablauf vielleicht
noch etwas anderes machen das dir wichtig ist.

Es ist auch moeglich mehere Wartezeiten in mehreren Variablen zu haben.


Nachteil von soetwas ist das es immer eine gewisse IRQ-Grundlast im 
System
gibt. Wenn du also z.B alle 10us einen IRQ brauchst weil dein Timer eine
entsprechende Aufloesung braucht, ist das unguenstig. Eventuell macht
es dann Sinn direkt mit einem Timer zu warten.

Beachte bitte das du nur Variablen innerhalb und ausserhalb eines IRQs
benutzen solltest die dein System unteilbar verwendet. Bei einem
68k Derivat natuerlich kein Problem. Bei einem AVR aber waere eine
16Bit Variable schon schlecht.

Olaf

von Markus (Gast)


Lesenswert?

danke erstmal, werde es heute abend versuchen.
mfg Markus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.