Guten Tag, ich benötige für den Temperatursensor DS1820 verschiedene Verzögerungen. Ich hab mir überlegt dies mit einem Timer zu machen. Den Timer habe ich bereits zum laufen gebracht. unsigned char ds1820_reset(void) { char a,presence; P4_0=0; P4_DIR=0xFF; delay(480); P4_DIR=0x00; delay(66); presence = P4_0; delay(480-66); a=presence; return a; } // 0=presence, 1 = no part Ich hab da ein Problem mit der Umsetzung. Eine delay Funktion habe ich ja nicht. Kann mir jemand sagen wie ich dies mit einem Timer realisieren könnte?
naja, als erstes solltest du mal sagen, um welchen MC es sich handelt, wie schnell der getaktet ist, ob du einen freien Timer nur für diese Aufgabe hast (eigentlich Verschwendung, aber wenn er sonst gar nichts zu tun hätte, kann man auch einen nehmen) und wie genau die die Zeiten eingehalten werden sollen. Wenn du es wirklich nur als Totzeit brauchst (also die Wartezeit nicht anderweitig nutzen willst/kannst/brauchst, erfüllen Warteschleifen denselben Zweck. Das sollte man dann aber mit dem inline-Assembler tun.
Ich verwende einen 8bit Mikrocontroller von Infineon. Der Typ lautet XC888.
Der Mikrocontroller läuft intern mit 24 Mhz. Das mit der For Schleife funktioniert nicht. Ich weiss auch nicht waran es liegen könnte. Ich brauche ja Verzögerungen zum Beispiel von 66us, 480us.
1 | void delay1(int useconds) |
2 | {
|
3 | int s; |
4 | for (s=0; s<useconds;s++); |
5 | }
|
6 | |
7 | void delay2(int useconds) |
8 | {
|
9 | int s; |
10 | for (s=0; s<useconds;s++) |
11 | {
|
12 | _nop_(); |
13 | }
|
14 | }
|
15 | |
16 | void main(void) |
17 | {
|
18 | |
19 | while(1) |
20 | {
|
21 | P4_0=1; |
22 | delay1(5); |
23 | P4_0=0; |
24 | |
25 | }
|
26 | }
|
Mit dem Oszi sehe ich einen kurzen Puls, der 7,5ms lang ist. Ich komme da nicht auf Mikrosekunden.
Ich kann machen was ich will, ich komme nicht unter den Millisekundenbereich.
Deine delayschleifen werden normalerweise vom Compiler wegoptimiert. Verwendest Du GCC?
Wie lange dauert das denn ? void main(void) { while(1) { P4_0=1; _nop_(); P4_0=0; } }
Alle 650us kommt ist ein Puls zu sehen. Der Puls ist ungefähr 110us breit. Als Compiler verwende ich Keil uVision Version 3. Ich hab mal die Resetfunktion so implementiert:
1 | unsigned char ds1820_reset(void) |
2 | {
|
3 | unsigned char err; |
4 | err = 0xFF; |
5 | |
6 | P4_DIR=0x02; |
7 | P4_1 = 1; |
8 | |
9 | P3_7 = 1; |
10 | _nop_(); |
11 | _nop_(); |
12 | _nop_(); |
13 | _nop_(); |
14 | _nop_(); |
15 | _nop_(); |
16 | _nop_(); |
17 | _nop_(); |
18 | _nop_(); |
19 | _nop_(); |
20 | _nop_(); |
21 | P3_7 = 0; |
22 | |
23 | P4_DIR=0x00; |
24 | |
25 | P3_6 = 1; |
26 | P3_6 = 0; |
27 | |
28 | err = P4_1; // get presence signal |
29 | |
30 | P3_5 = 1; |
31 | _nop_(); |
32 | _nop_(); |
33 | _nop_(); |
34 | _nop_(); |
35 | _nop_(); |
36 | _nop_(); |
37 | _nop_(); |
38 | _nop_(); |
39 | _nop_(); |
40 | _nop_(); |
41 | P3_5 = 0; |
42 | |
43 | if( (P4_1) == 0 ) |
44 | err = 1; |
45 | |
46 | |
47 | return err; // presence signal returned |
48 | } // 0=presence, 1 = no part |
Mit dem Port3 überprüfe ich, ob die Zeitverzögerungen so einigermaßen stimmen. Port4 Pin1 ist die Datenleitung des DS1820 angeschlossen. Ich bekomme bei der Ausführung dieser Funktion immer eine 1 raus.
holger: Alle 650us ist ein Puls zu sehen. Der Puls ist ungefähr 110us breit. Der Dude: Als Compiler verwende ich Keil uVision Version 3.
Wenn dein uC wirklich mit 24MHz läuft und für drei simple Befehle jeweils 36us braucht, dann hast du irgendwo etwas falsch eingestellt. Schau mal ins Datenblatt !
Ich weiss nicht wo ich da genau schauen muss. Zuvor habe ich schonmal überüft wie die Systemfrequenz steht. Laut EEinstellung liegt diese bei 24Mhz. Extern habe ich einen Resonator von 8Mhz angeschlossen.
Das Ding läuft doch in Zeitlupe mit ungefähr 27kHz. Schau mal in Kapitel: Clock Generation Unit Mehr kann ich dir dazu nicht sagen. Ich kenn den XC888 nicht.
Oder hast du einfach Schrott gemessen ? Wenn es 110ns sind dann sind wir ungefähr bei 24MHz.
Ich sach mal auch, das Ding läuft definitiv nicht mit 24MHz. Hier gibts auch viele mit 8051 Erfahrung, aber die benutzen in der Regel die wesentlich bekannteren Atmels, z.B. AT89C51CC03, AT89LP4052 (ich auch). Zu speziellen XC888 Eigenheiten kann ich Dir daher nicht helfen. Für die standard 8051 hab ich hier funktionierenden Code: http://home.tiscali.de/peterd/appl/soft/c51/thclock/index.htm Wenn Du den XC888 entsprechend runtertaktest, sollte er auch da laufen. Peter
>Wenn es 110ns sind dann sind wir ungefähr bei >24MHz. Da hab ich mich gerade gewaltig verrechnet. Und wenn ich ins Datenblatt sehe dann läuft der intern sogar mit 96MHz.
Upps 96MHz stimmt doch nicht: 3.8.2 Clock Management The CGU generates all clock signals required within the microcontroller from a single clock, fsys. During normal system operation, the typical frequencies of the different modules are as follow: • CPU clock: CCLK, SCLK = 24 MHz • Fast clock (used by MultiCAN): FCLK = 24 or 48 MHz • Peripheral clock: PCLK = 24 MHz • Flash Interface clock: CCLK2 = 48 MHz and CCLK = 24 MHz
Das nächste interessante ist das hier: While the standard 8051 processor is designed around a 12-clock machine cycle, the XC886/888 CPU uses a 2-clock machine cycle. This allows fast access to ROM or RAM memories without wait state. Access to the Flash memory, however, requires an additional wait state (one machine cycle). The instruction set consists of 45% one-byte, 41% two-byte and 14% three-byte instructions. Auf 110us für drei Befehle komme ich damit aber auch nicht :(
Also ich weiss nicht was ich jetzt tun sollte. Ich bin total verwirrt. Das mit der Warteschleife funktioniert nicht sowie mit dem Timer und der Datenpin vom DS1820 liefert ständig +5V.
Der Mikrocontroller basiert doch auf dem 8051. Dies bedeutet 12 Taktzyklen entspricht einem Befehl oder?
Also der Mikrocontroller macht mich noch ganz verrückt. Mit den AVR Mikrocontrollern kann ich besser umgehen.
...vielleicht mache ich auch beim Messen mit dem Oszi was falsch. Ich verwende hier ein Tektronix TDS220.
>Der Mikrocontroller basiert doch auf dem 8051. Dies bedeutet 12 >Taktzyklen entspricht einem Befehl oder? Nein, siehe oben. Dein uC läuft mit 24MHz. Ein Machinenzyklus ist 24MHz/2. Also 12MHz. Sagen wir einfach mal 10MHz um einfacher zu rechnen. P4_0=1; _nop_(); P4_0=0; Das sind für mich drei Befehle. Sagen wir mal die brauchen alle zwei Zyklen plus ein Waitstate fürs holen aus dem Flash. 3 3 100ns sind 900ns. 900ns * 1.2 sind 108ns. Schon ziemlich dicht an 110ns :) >...vielleicht mache ich auch beim Messen mit dem Oszi was falsch. Undersampling ? Dreh den Zeitbasisknopf doch mal weiter nach rechts.
>900ns * 1.2 sind 108ns.
So ein Quatsch ! Sind 1.08us.
Ich geh schlafen.
Aber ich komme messtechnisch nicht auf die obige Zeit von ungefähr 110us. Die Register für die Einstellung der System Clock: OSC_CON = 0x05; // external oscillator CMCON = 0x00; // clock divider: fsys/4
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.