mikrocontroller.net

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


Autor: Markus (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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--);
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define BUS_CLOCK 4000

void delay (unsigned int time)
{
unsigned int temp;
for(;time;time--) for(temp=(BUS_CLOCK/23);temp;temp--);
}
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
void delay (unsigned int time)
{
}

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
void delay (unsigned int time)
{
  volatile unsigned int temp;

  for(;time;time--)
    for(temp=(BUS_CLOCK/23);temp;temp--)
      ;
}

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.

Autor: Markus (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
    for(temp=(BUS_CLOCK/23);temp;temp--)
      ;

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.

Autor: Markus (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver R. (superberti)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke erstmal, werde es heute abend versuchen.
mfg Markus

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.