-
Gemeint ist:
Solange du nicht weisst, was Bascom aus der Anweisung pulsein ... genau macht, also wie es für den Mikrocontroller umgesetzt wird, sehe ich selbst keine Optimierungsmöglichkeiten in dieser Richtung .... (daher Sackhüpfen im Minenfeld).
Ein Flussdiagramm zu dem Thema wäre sicherlich schon mal ein Anfang.
Mal so ne Frage am Rande: für was nen µC willst du das ganze schreiben ?
-
Falls es jemanden interessiert, was Bascom bei "PULSEIN" produziert:
Hat ja drei Loops:
1 Warten auf Pinx != state (count 0-65535)
2 Warten auf Pinx == state (count 0-65535)
3 Warten auf Pinx != state (count 0-65535 mit 10µS Loop)
Um die timeoutwerte zu ändern, müßt man den Code-ändern
Code:
// DIM result as WORD
// Pulsein Result , Pind , 2 , 1
LDI ZL,0x30 // PIND
LDI r24,0x02 // PinNr
LDI r16,0xFF // State
CALL PULSEIN
LDI XL,0x60 // addr "result"
LDI XH,0x00
ST X+,r24 // store result
ST X,r25
...............................................
PULSEIN:
CALL Clear_ErrBit
CLR ZH
CLR XL // clear Timout Lo
CLR XH // clear Timout Hi
CALL MakeMask // R24 Mask, R25 neg Mask
AND r16,r24
LDD r0,Z + 1 // DDRD
AND r0,r25 // Make Pin (2) Input
STD Z + 1,r0 // DDRD
L_0x00D8: // ------------- Loop 1
LDD r0,Z + 0 // PIND
AND r0,r24 // PIND & Mask
EOR r0,r16 // (PIND & Mask) ^ State
BRNE L_0x00E6 // Ok PIN != State
ADIW XL,0x0001 // Timeout counter++
BREQ L_0x0118 // elapsed->ERR-Exit
RJMP L_0x00D8 // cont'd Loop
L_0x00E6:
CLR XL // clear Timout Lo
CLR XH // clear Timout Hi
L_0x00EA: // ------------- Loop 2
LDD r0,Z + 0 // PIND
AND r0,r24 // PIND & Mask
EOR r0,r16 // (PIND & Mask) ^ State
BREQ L_0x00F8 // Ok PIN == State
ADIW XL,0x0001 // Timeout counter++
BREQ L_0x0118 // elapsed->ERR-Exit
RJMP L_0x00EA // cont'd Loop
L_0x00F8:
CLR XL // clear Timout Lo
CLR XH // clear Timout Hi
L_0x00FC: ------------ 10 µS Loop 3
PUSH ZL // Save
PUSH ZH
LDI ZL,0x20 // calc from $XTAL
LDI ZH,0x00
CALL L_0x009C // 10 µS Idle
POP ZH // Restore
POP ZL
LDD r0,Z + 0 // PIND
AND r0,r24 // PIND & Mask
EOR r0,r16 // (PIND & Mask) ^ State
BRNE L_0x011C // OK, Pulsein done *********
ADIW XL,0x0001 // PulseCounter++
BRNE L_0x00FC // cont'd Loop
L_0x0118:
CALL Set_ErrBit
L_0x011C:
MOV r24,XL // result --> R24:r25
MOV r25,XH
RET // that's it
// idle Loop
L_0x009C:
SBIW ZL,0x0001
BRNE L_0x009C
RET
Set_ErrBit:
SET
BLD r6,2
RET
Clear_ErrBit:
CLT
BLD r6,2
RET
MakeMask:
LDI r25,0x01
AND r24,r24
BREQ L_0x00BC
CLC
L_0x00B6:
ROL r25
DEC r24
BRNE L_0x00B6
L_0x00BC:
MOV r24,r25
COM r25
RET
-
Hmm, also wohl die denkbar schlechteste Lösung für zeitkritische Geschichten .... (durch das Polling)
Vorschlag:
Versuch den Timer 1 frei zu bekommen.
So wie ich das anhand deines Codeschnipslels sehe, verwendest du den Timer 1 defakto nur dazu um die Datenübertragung anzustoßen (oder führst du die in der ISR aus ?!)
Ich denke mal, dieses könnte man durchaus in einen andere Timer verlegen.
Ansonsten rük mal bitte ein paar Infos darüb er raus, was für Parameter du nun genau messen willst. Vielleicht hab ich ja dann noch ne zündende Idee.
Grüße,
da Hanni.
-
Hi Hanni,
ahh jetzt verstehe ich die Aussage ;)
Also im Moment führe ich die Datenübertragung im ISR aus. Ich könnte aber auch die Datenübertragung durch den ISR triggern lassen. Das Dumme war, das die Messung des RC-Kanals erst nachdem alles fertig war (Code und HW) mit eingeführt werden musste.
Das Ding macht folgendes (eigentlich nix berauschendes)
Über einen Durchflussmesser kommen Impulse, die der MC über den INT0 zählt. Anhand der gezählten Impulse werden dann Verbauchs- und Bevorratungsberechnungen durchgeführt. Zus. wird die Funktion des Durchflussmessers überwacht, also ob sich das Ding noch dreht oder nicht. Das wird unter anderem auch in der ISR des Timer1 gemacht. Also alle 0,25 Sek. werden die Zählerstände alt und neu verglichen und dann die Daten gesandt.
So nun muss der MC (Mega8) zus. den RC-Kanal überwachen und bei überschreiten eines bestimmten Wertes dies über den Datentransfer melden.
Das alles funktioniert bisher einwandfrei, bis auf das Problem, das bei fehlendem Pulsein alles etwas durcheinanderholpert und durch die lange Wartezeit des Timeouts viele Impulse über den INT0 nicht gezählt werden.
Ich könnte aber vor der Hauptschleife noch eine Pulseinabfrage machen, wenn kein Impuls anliegt dann einfach den Pulsein in der Hauptschleife disablen. Wäre glaub ich die einfachste Variante.
-
Also, zählen von Impulsen über INT0 (Durchflussmesser) und
Messen von Impulsen aus dem RC Kanal (also Impulsbreite o.ä.)?
-
-
Was hast du denn in den Haupt "do...Loop" schleife noch alles zu tun ?
Vielleicht könnt man die beiden Funktionen zusammenführen und gewissermassen gleichzeitig tun.
-
@PicNick
Danke für deinen kommentierten ASM-Code
m@rkus33
Warum wird in diesem Forum immer viel diskutiert und nur so wenig Code veröffentlicht? Hier wird doch kaum jemand kommerzielle Interessen verfolgen?
Jeder erfindet das Fahrrad für sich neu und schreibt zum Schluss
"Danke, jetzt hab ich es."
-
@tomas
ich habe einfach ein schlechtes Gefühl, wenn ich den gesamten Code hier reinstelle. Da habe ich bisher mehrere Monate gebraucht um das Ganze zu entwickeln ( Hard- und Software) und es ist da wo ich es einsetze (kein kommerzielles Intresse!) bisher einmalig. Ich möchte nur nicht das das irgendwo einfach kopiert wird.
@PickNick
ja auch nochmal Danke für den Code. Ich bin nur noch nicht fit genug um den wirklich zu kapieren... kommt noch (hoffe ich ;) )
In meiner Do- Loop passiert nicht besonders viel.
Do
Start ADC
U-Wert einlesen
Stop ADC
vergleich U-Wert mit bisherigen Werten, nach tiefster Wert und
aktueller Wert
Zählergebnisse Impulse mit Vorgaben verglichen
RC- Kanal mit Pulsein gemessen (nur der reine Wert, keine Umrechnung in ms)
RC-Kanal Wert mit Vorgabe vergleichen und Statusmeldung bei Schwellwert Unter- bzw. Überschreitung
Loop
OnInt0:
incr Zähler für Impulsmessung
Return
OnTimer: (alle 0,25 sek.)
Daten (Zählerstand Impulsmessung, Werte U, Statuswerte Durchflussmesser, RC Kanal) werden über RS232 gesendet und über Funk telemetriert.
Gruß
Markus
-
Hmm, mögliche Lösungsansätze:
Man könnte z.B. die Durchfluss Impulse als Takt für den Timer 0 missbrauchen.
Desweiteren erzeugt man sich mit einem beliebigen weiterem Timer eine "Referenzzeit" welche dann dafür genutzt werden könnte um:
a) Die Anzahl der Impulse innerhalb einer bestimmten Zeit zu speichern.
b) um die Impulsbreite des RC Impulses zu messen.
Den RC Impuls würde ich über einen Flankengesteuerten externen Interupt messen. (man muss halt nach jedem Impuls die Flanke wechseln).
Die Datenübertragung würde ich übrigens in den Main Loop packen.
So, nun stellt sich allerdings die Frage, ob dieses theoretisch mit deiner bisherigen Hardware realisierbar wäre.
Grüße,
da Hanni.