Hai Leute!
Ich wollte mal kurz fragen, wie ich in C dem Programm beibringe, dass es kurz warten soll.
So in der Art wie bei Bascom das mit "waitms n" gemacht wird.
Oder gibt's sowas garnicht und ich muss direkt die Timer ansprechen?
MfG, Sascha
Hai Leute!
Ich wollte mal kurz fragen, wie ich in C dem Programm beibringe, dass es kurz warten soll.
So in der Art wie bei Bascom das mit "waitms n" gemacht wird.
Oder gibt's sowas garnicht und ich muss direkt die Timer ansprechen?
MfG, Sascha
Die Funktion gibt es in C nicht.
Solche Warte Funktionen sind eigentlich sehr schlecht, da in dieser Zeit der µC keine anderen Aufgaben erledigen kann.
Wenn du doch eine solche Funktion haben willst, dann kannst du das auch mittels einer Schleife erledigen.
Dabei bleibt er solang in der schleife bis die Zeit abgelaufen ist.Code:for(i=0 ; i<laenge ; i++){}
Natürlich kannst du jetzt die Zeit nicht in ms angeben.
aber:
T = 1/f
Bei einem 16Mhz Quartz würde er bei laenge=1 genau 0,0000625 ms in der Schleife bleiben. (0,0000625 = (1/((16*10^6)/1024)*1000))
Für 1 ms müsstest du also länge=16000 setzen.
Ich hoffe ich habe es verständlich ausgedrückt
Und hoffentlich hab ich da nichts falsch gerechnet
die Sprung- und Prüfbefehle innerhalb der Schleife "verbrauchen" aber auch noch einige Taktzyklen, so dass diese Rechnung nicht funktionieren wird. In Assembler geht das Ganze recht einfach mit "nop"-Befehlen, und weil man da die Befehle genau kennt kann man die Anzahl der zusätzlichen Takte für Sprünge etc. leicht berechnen. Ich habe also mal eine C-Routine mit Inline-Assemblercode geschrieben. Du musst als Parameter nur angeben, wie oft 50µs gewartet werden soll (für 10MHz ausgelegt, für 16 MHz ersetze ldi r16,125 durch ldi r16,200).
Beispiel: 1ms Wartezeit=20*50µs => wait(20);
Das Schöne an dem Wert 50µs ist, dass man Zeiten bis 3,2 Sekunden (65535*50µs) in hoher Auflösung bekommen kann.Code:void wait(unsigned int multiplier50us) { unsigned int i; for(i=0;i<multiplier50us;i++) { asm volatile( "ldi r16, 125" "\n\t" "L_%=:dec r16" "\n\t" //1 "tst r16" "\n\t" //1 "brne L_%=" "\n\t" //2 :::"r16"); } }
mfG
cht
wie viele Taktzyklen braucht ein Durchlauf der Schleife?Zitat von cht
keine Ahnung, da musst du dir den Assemblercode angucken den der GCC ausspuckt. So in der Größenordnung um 10 für die C-Schleife schätze ich. Die Zyklen für den asm-code werd ich mal ausrechnen, moment (editdie Zahl oben (125) +1)*4). Durch die Schleife entsteht natürlich immer noch ein Fehler, aber weil die Schleife selbst bei mir schon 50µs dauert wird der Fehleranteil kleiner. 10 Zyklen wären z.B. 1µs@10MHz, also 2% Abweichung. Beim Warten darf es ja manchmal gerne etwas mehr, nur nicht weniger sein (zB beim Warten auf das Initialisieren eines LCD, dafür war das gedacht), also stört das nicht weiter finde ich.
mfG
cht
Ok,... vielen Dank Jungs!
Das es nicht so ganz ratsam ist, ist mir auch mehr als klar... aber für ein paar Tests ist es doch ganz angenehm, wenn ne Diode mal für ne bestimmbare Anzahl von Sekunden leuchtet oder ausgeht ...
MfG, Sascha
@cht
Für welchen µC ist eigentlich dein Code?
PICs brauchen für das Abarbeiten von Befehlen ja länger als AVR soweit ich weiß.
das ist möglich. Ich ging hier von AVRs aus. Allerdings sollte es auch für PICs ein Datenblatt und einen Befehlssatz zB als pdf geben, da kann man dann nachsehen was wie lange dauert. Eventuell muss man auch das AVR-Register r16 durch was anderes ersetzen.
mfG
cht
am besten du nimmst einen timer! der is am genauesten, da rein hardwaretechnisch.außerdem kannst die cpu auch daweil in den _idle_mode schicken(Spart strom).
mit den zählschleifen hast du das problem dass wenn inzwischen viele interruptrequests kommen/der controler sonst wie ausgelastet is, das einfach viel länger dauert als gedacht.
die datendafür stehn alle in den datenblättern(laufzeit, periodenzeit,....)
mfg
Damit solche schleifen nicht durch interrupts gestört werden, kann man für diese Zeit die Interrupts per assemblerbefehle deaktivieren.
Lesezeichen