Archiv verlassen und diese Seite im Standarddesign anzeigen : Fragen zu Programmtimings; Dauer von Codezeilen berechnen
m@rkus33
17.05.2006, 18:13
Hallo zusammen,
eine Frage:
Wo kann ich Informationen finden über das berechnen der Dauer von Bascom- codezeilen?
Konkret:
Ich möchte wissen wie lange in meinem Code und bei einer bestimmten Quarzfrequenz die einzelnen Abläufe dauern.
Ich habe ein perfekt funktionierendes Programm mit dem Ich Impulse eines Flügelrades zähle. Da ich nur die Anzahl brauche erfolgt keine Auswertung der Zeit zwischen den einzelnen Flanken wie bei einer Geschwindigkeismessung.
Danach werden einige Berechnungen angestellt und das ganze über RS232 ausgegeben.
Jetzt seht eine größere Implementierung an. Ich muss zusätzlich von einem Fremdgerät die RS232 Daten abfragen und in meinen Bytearray einbauen. Nun habe ich Bedenken, das das Zeitfenster zwischen den einzelnen Impulsen nicht mehr ausreicht um das alles abzuarbeiten. Ich darf KEINEN Impuls verlieren.
Gibts irgendwo eine Übersicht wo ich "If - Then Schleifen, Print "irgendwas" eine Inkey()-Abfrage usw. nach der benötigten Dauer berechnen kann?
Danke und Gruß
Markus
wüsste ich nicht, aber du kannst einige der funktionen ja aus den librarys berechnen, die timings für die asm-befehle stehen ja im datenblatt des jeweiligen prozessors...
EDIT: if-then iss keine schleife, sondern nen block, also if-then-block ^^
Martin
Reinhard
17.05.2006, 20:45
Ich habe bei einem ähnlichen Problem zu Beginn der betreffenden Routine einen Ausgang gesetzt und am Ende wieder zurück. Mit dem Scope dann die Laufzeit ausmessen.
Wer aus den Assembler Befehlen die Laufzeit ermitteln kann, kann auch gleich in Assembler programmieren!
Reinhard
Reinhard
17.05.2006, 20:45
Ich habe bei einem ähnlichen Problem zu Beginn der betreffenden Routine einen Ausgang gesetzt und am Ende wieder zurück. Mit dem Scope dann die Laufzeit ausmessen.
Wer aus den Assembler Befehlen die Laufzeit ermitteln kann, kann auch gleich in Assembler programmieren!
Reinhard
1. es braucht auch nochmal zeit nen ausgang zu setzen (1 zyklus jeweils)
2. ehm... du musst dich dafür nicht mit den befehlen auskennen, das iss sturen nachschlagen, und du wirst wohl auch keine lexika auswendig können oder? er muss einfach nur gucken, z.b. wie viele sbi's sind da drin, dann schauter nach wie lang ein sbi braucht (1 zyklus) und dann multiplitziert er das mit der zahl, die er bei der zählung der sbi's rausbekommen hat... das iss alles, und das iss sicher
3. kannst du den doppelpost noch grad löschen bidde? thx ^^
außerdem hört sich die zusatzimplementierung ziemlich leicht an, man kann viiiiiiiiel schlimmeres mit bascom machen, ohne dasses den ganzen prozessortakt benötigt... das iss recht einfach, was du da bisher hast ^^
Martin
m@rkus33
17.05.2006, 20:55
@Reinhard,
auf die Idee bin ich noch gar nicht gekommen. Mal sehen ich werde das versuchen.
Aber ist es nicht möglich die Zeit zu bestimmen die BASCOM für gewisse Routinen braucht?
siehe oben bei mir... das funktioniert sicher ^^
aber bau erstmal dein programm, ich bin mir recht sicher, dass du damit nicht annähernd die kapazitäten des avr's ausschöpfst ^^
Martin
m@rkus33
17.05.2006, 21:02
Hi X-Ryder,
richtig es ist nich schwer, nur habe ich bedenken das ich bei dem Hochzählen des Flügelrades Impulse "verliere". Est so: Der Impuls löst einen Int aus. Im Int wird eine Variable hochgezählt.
Meine Nutzdaten werden im Rythmus (nicht permanent) übertragen. Den Rythmus gibt mir der Timer vor. Alle 0,25 Sek. löst der Timer aus und es wird in Sub "Datensenden" gesprungen.
Dazwischen muss ich die RS232 vom Fremdgerät auslesen. Hier muss erst die Baud Rate umgestellt werden und 40 Ascii Zeichen eingelesen werden. In einen Array verpacken und nur bestimmte Zeichen aus dem Array wiederum in mein Datenarry packen und ab die Post.
Ansich leicht aber das Timing? Wie gesagt ich muss sicher sein das ich keinen Impuls verliere.
Manche Sachen lassen sich schlecht vorhersagen, selbst wenn man den COde kennt. Wenn bei der RS232-Routine zB gwewartet wird, bis der Sender frei ist und das nächste Zeichen gesendet werden kann, ist diese Zeit nicht genau vorhersehbar. Und auch bei den If-Abfragen ist die Ausführungsdauer unterschiedlich, je nach Ergebnis...
In welcher Größenordnung liegt denn die maximale Impulsrate? Wie zählst du? externer Interrupt? Besser wäre, die Impulse direkt an einen Timer/Couter zu hängen, dann ist der Zählvorgang vollkommen unabhängig vom Rest des Programms...
m@rkus33
17.05.2006, 21:11
Hi uwegw,
also max. impulsrate ca. 10.000 I/min, über den Impuls wird der Int0 (externer) ausgelöst - Spung ins Sub"Int0" hier werden genau drei Variablen jeweils hochgezählt.
Frage zur Unabhängikeit: Wer hat eigentlich die Prio der externe Int0 oder der Timerinerrupt?
Was ich meine: Wenn im Int0 zufälligerweise der Timer auslöst, unterbircht der Timer oder nicht? Andersrum genauso unterbricht der Int0 den Timer?
Gruß
Markus
Die Rangfolge der Interrupts ist im Datenblatt angegeben. Die externen kommen ganz als erstes, danach meist die Timer und dann der Rest.
Man kann die Timer auch so einstellen, dass sie vom externen Signal getaktet werden (Pin T1). Dann wird also bei jedem Impuls das Zählerregister weitergezählt. Währenddessen kannst du es jederzeit ohne Störung des Zählvorganges abfragen, und wenn das Register überläuft, kann es das per Interrupt melden...
Die Rangfolge der Interrupts ist im Datenblatt angegeben. Die externen kommen ganz als erstes, danach meist die Timer und dann der Rest.
Diese Aussage ist so nicht richtig.
Die AVR Reihe von Atmel kennt keine priorisierten Interupts.
In welcher Reihenfolge zugleich anfallende Interupts anfallen entzieht sich allerdings meiner Kenntnis.
Frage zur Unabhängikeit: Wer hat eigentlich die Prio der externe Int0 oder der Timerinerrupt?
Was ich meine: Wenn im Int0 zufälligerweise der Timer auslöst, unterbircht der Timer oder nicht? Andersrum genauso unterbricht der Int0 den Timer?
Interupts werden normal nicht unterbrochen, es sei denn man will es so ... (cli / sei)
BTW: der einfachsteWeg ist der:
am Anfang der routine irgendeinen Pin auf H setzen und am Ende den selben auf L .... und das ganze mit nem Oszi ausmessen ....
Im übrigen, ist auch in Assembler das ganze nicht immer klar zu berechnen ... da eben diese "IF" Anweisungen je nach dem ob wahr oder falsch unterschiedlich lange dauern ....
Man kann höchstens eine "Worst Case" Berechnung anstellen ....
Grüße,
da Hanni.
Die AVR Reihe von Atmel kennt keine priorisierten Interupts.
Dem kann ich wiederum nicht zustimmen.....
In welcher Reihenfolge zugleich anfallende Interupts anfallen entzieht sich allerdings meiner Kenntnis.
Genau die Reihenfolge, wie das im Dattenblatt steht, wie der Uwe schon sagte.
Gruß Sebastian
Die Implementierung auf Int0 ist Käse an sich.
Lass doch einfach den Timer hochzählen, dann brauchste
praktisch garkeinen Code und ist auch nicht zeitkritisch.
Die RS-Geschichte läuft dann auch unkritisch
Die harte Sprache ......
10000 Impulse Sek sind Pinatz.
Nebenbei aber viele Byte per Rs232 ausgeben , Taktgenau unberechenbar.
Sogesehen mein Vorschlag : Per CD4024 am dessen Eingang die Impulse zählen lassen , Auslesen per IRQ .... und Reseten dann.
Kostet 11 Cent.
Gento
m@rkus33
17.05.2006, 23:58
hmm...
das Dumme ist nur, das bei jedem gezähltem Impuls die aktuelle Summe mit insgesamt 6 Variablen verglichen werden muss (diese Variablen sind auch noch variabel im Wert) Bei jedem der Vergleiche werden dann verschiedene Aufgaben zu lösen sein.
Also alle x Zeiteinheiten den Wert auslesen ist nicht. Sonst wär es einfach.
Ok eins weis ich jetzt das die 10000 Impulse ne kleinigkeit ist. Dann müsste ja genügend Zeit übrig sein um die ganze RS Geschichte abzuarbeiten. Richtig?
Wie weit können denn die 8bit und 16bit Timer/counter "hochzählen"?
Wie hoch kann ich in mm springen wenn ich 1 m Springen kann ?
So lese ich Deine Frage 8/16 Bit Zähler.
Gento
Wie weit können denn die 8bit und 16bit Timer/counter "hochzählen"?
Also das ist eigentlich das Mindeste was man wissen sollte bevor man zum Programmieren anfängt.
8 Bit = 2^8 = 256 (0-255)
16 Bit = 2^16 = 65536 (0-65535)
m@rkus33
18.05.2006, 12:53
war ne blöde Frage....
Die AVR Reihe von Atmel kennt keine priorisierten Interupts.
Dem kann ich wiederum nicht zustimmen.....
Priorisierte Interupts habe ich meiner Auffassung nach, wenn ich die Prioritäten der einzelnen Interupts selbst definieren kann ....
m@rkus33
18.05.2006, 14:45
ich habe jetzt mal ein wenig rumgespielt und nur den Teil der Abrfage der RS232 Daten vom Fremdgerät gemacht.
Das ist der Code:
$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600
Dim Olcd(40) As Byte 'Asciizeichenarray vom Fremdgerät
Dim A As Byte
Dim I As Byte
Dim Oegt1 As Byte
Dim Oegt2 As Byte
Dim Oegt3 As Byte
Dim Oegt4 As Byte
Dim Ogas1 As Byte
Dim Ogas2 As Byte
Dim Ogas3 As Byte
Dim Ogas4 As Byte
Dim Orpm1 As Byte
Dim Orpm2 As Byte
Dim Orpm3 As Byte
Dim Orpm4 As Byte
Dim Orpm5 As Byte
Dim Onc1 As Byte
Dim Onc2 As Byte
Dim Onc3 As Byte
Dim Odata(16) As Byte At Oegt1 Overlay
Declare Sub Odatensenden
Declare Sub Odatenlesen
Declare Sub Lcdvisual
Config Lcd = 20 * 4
Config Lcdpin = Pin , E = Portd.3 , Rs = Portd.2 , Db7 = Portd.7 , Db6 = Portd.6 , Db5 = Portd.5 , Db4 = Portd.4
Config Serialin = Buffered , Size = 45
Enable Interrupts
Cursor Off
Do
If Ischarwaiting() = 1 Then Odatenlesen
'Gosub Odatensenden
Waitms 10
Gosub Lcdvisual
Loop
'---------------------------
Odatenlesen:
A = Inkey()
If A = 128 Then
For I = 1 To 41
Olcd(i) = Inkey()
Next
End If
Oegt1 = Olcd(4)
Oegt2 = Olcd(5)
Oegt3 = Olcd(6)
Oegt4 = Olcd(7)
Ogas1 = Olcd(13)
Ogas2 = Olcd(14)
Ogas3 = Olcd(15)
Ogas4 = Olcd(16)
Orpm1 = Olcd(20)
Orpm2 = Olcd(21)
Orpm3 = Olcd(22)
Orpm4 = Olcd(23)
Orpm5 = Olcd(24)
Onc1 = Olcd(32)
Onc2 = Olcd(33)
Onc3 = Olcd(34)
Return
'---------------------------
'--------------------------
Lcdvisual:
Locate 1 , 6
Lcd Chr(oegt1) ; Chr(oegt2) ; Chr(oegt3) ; Chr(oegt4) ; "C"
Locate 1 , 16
Lcd Chr(ogas1) ; Chr(ogas2) ; Chr(ogas3) ; Chr(ogas4)
Locate 2 , 6
Lcd Chr(orpm1) ; Chr(orpm2) ; Chr(orpm3) ; Chr(orpm4) ; Chr(orpm5)
Locate 2 , 16
Lcd Chr(onc1) ; Chr(onc2) ; Chr(onc3) ; "V"
Return
'----------------------------
'----------------------------
Odatensenden:
Baud = 4800
Print "Orbitdaten" ; Chr(odata(1) , 16)
Baud = 9600
Return
'--------------------------------
End
Komisch ist aber, wenn ich "Gosub Odatensenden" "aktiviere" kommt mir so einiges durcheinander und das Display zeigt zeitweise andere Datensätze aus dem Array an.
Wenn ich nun in meine (schon recht) vorhandene komplexe Anwendung diesen Teil hier implementiere dann hab ich glaub ich ein Problem. Wenn es jetzt schon mit nicht richtig funktioniert.
Oder wo habe ich den Fehler drin? Ist das nun ein Timingproblem?
Priorisierte Interupts habe ich meiner Auffassung nach, wenn ich die Prioritäten der einzelnen Interupts selbst definieren kann ....
Ja ok, dann hast Du natürlich recht, ich dachte du meinst Prioritäten allgemein :-)
Gruß Sebastian
hmmm ... das möcht mir nicht so recht gefallen:
A = Inkey()
If A = 128 Then
For I = 1 To 41
Olcd(i) = Inkey()
Next
End If
du beschreibst hier die Variable mit dem Inkey der UART, egal ob da
nun Daten drin stehen oder nicht, dann nämlich mit 0.
Ich verwende die buffered Variante der UART nicht gern.
Bedenke: die Uart ist im verhältniss zum Controller schneckenlangsam.
es gibt da 2 Varianten, du kannst den Controller so lange anhalten bis er
empfangen hat z.B. per waitkey Befehl
oder du verwendest den UART Interrupt bei Empfang und lässt den
Knubbel derweil was anderes machen
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.