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--); }
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.
hallo! danke für die antwort, kannst du mir das jetzt noch vorrechnen wie man auf die zeit kommt? danke markus
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.
okay dann frage ich anders: wie wird eine Delay funktion geschrieben, auf was muss alles geachtet werden? Danke Markus
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.
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); }
> 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.