MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!
Hallo zusammen,
mit "hintereinander Einlesen" meinte ich in meinem letzten Posting das Einlesen von 3 RC Signalen, und zwar unabhängig davon, WANN sie der Empfänger sendet (wir reden nicht von einem Summensignal, sondern von 3 getrennten Anschlüssen am Empfänger).
Es gibt Empänger, die ein Signal zu Ende senden, dann mit dem nächsten beginnen (am nächsten Ausgang des Empfängers) usw bis alle 4, 6 oder 8 Kanäle durch sind. Andere Empänger setzen die Kanäle nahezu zeitgleich auf 1 und wieder andere beginnen den nächsten Kanal nach einer vordefinierten Zeit. Manche käufliche V-Mischer hatten dann das Problem, dass sie nicht mehr funktionierten, wenn man die Reihenfolge der RC Kanäle veränderte.
Ich möchte meinen Code so gestalten, dass es egal ist, welchen Empfänger ich dran hänge. Wenn ich also vom Fall ausgehe, dass die einzelnen RC Signale nahezu gleichzeitig beginnen auf 1 (high) zu gehen, und ich sie dann HINTEREINANDER einlese, so dauert das Einlesen 3 x 20ms. Das kann ich nicht während der Pause der Servoausgabe einbauen, da diese ja spätestens nach 20ms wieder bedient werden möchten (müssen).
@ PICture
Das Problem liegt daran, das ich mehr als 1 Servosignal einlesen muss. Genauergesagt mindestens 2. Eines ist der Betriebsmode (also Baggerbetrieb oder Fahrbetrieb) und das zweite die eigentliche Steuereingabe. Deshalb versuche ich alles auf einen Chip zu bekommen.
Alternativ ginge es mit 3 Chips: Einer wertet nur den Betriebsmode aus und setzt einen Ausgang auf high oder low, die anderen steuern die Servos und werten nur den Ausgang des "Betriebsmode-Chips" aus.
Mal sehen, wie es weitergeht
mfg
Robert
mfg
Robert
Hallo Robert,
wenn es in Bascom zeitkritisch wird, kann man es mit Inlineassembler versuchen.
Ich habe nix weiter gemacht als in Deinem letzten geposteten Programm versucht, die Impulsmeß-ISRs mit ASM zu ersetzten mit manuellem Registersichern (On interrupt label Nosave) und hoffe keinen Bug eingebaut zu haben.
Die max. Ausführungszeit einer ISR sollte von ca. 17µs auf ca. knapp 5µs gesunken sein. Vielleicht bessert es das Verhalten.
Ungetestet und ohne Gewähr
Gruß
Searcher
Code:'=============================================================================== 'RC Eingang 1 an Pin 3 (PB1, PCINT9) 'RC Eingang 2 an Pin 7 (PA7, PCINT7) 'RC Eingang 3 an Pin 5 (PB2, INT0) 'Servo 1 an Pin 13 (PA0) 'Servo 2 an Pin 12 (PA1) 'Servo 3 an Pin 11 (PA2) 'Servo 4 an Pin 10 (PA3) '=============================================================================== $regfile = "attiny24.dat" $crystal = 8000000 'FuseBit CKDIV8 deaktivieren $hwstack = 32 $swstack = 20 $framesize = 40 '------------------------------------------------------------------------------------------------- 'Timer und konfigurieren '------------------------------------------------------------------------------------------------- Config Timer1 = Timer , Prescale = 8 'Timer für Einlesen RC Signale Start Timer1 Config Timer0 = Timer , Prescale = 64 'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms Enable Timer0 On Timer0 Servoausgabe '------------------------------------------------------------------------------------------------------------- 'Variablen definieren '------------------------------------------------------------------------------------------------------------- 'Variablen fürs RC Einlesen Dim Rc_signal_1_start As Word Dim Rc_signal_2_start As Word Dim Rc_signal_3_start As Word Dim Impulslaenge_1 As Word Dim Impulslaenge_2 As Word Dim Impulslaenge_3 As Word 'Variablen für Berechnungen Dim Berechnung_1 As Word Dim Berechnung_2 As Word 'Variablen für Servoausgabe Dim Kanal As Byte Dim Servoausgabe_1 As Byte Dim Servoausgabe_2 As Byte Dim Servoausgabe_3 As Byte Dim Servoausgabe_4 As Byte Dim Pausen_variable As Byte '------------------------------------------------------------------------------------------------- 'Einigen Variablen Werte zuweisen '------------------------------------------------------------------------------------------------- Kanal = 1 Pausen_variable = 0 '------------------------------------------------------------------------------------------------------------- 'Ein- und Ausgang festlegen '------------------------------------------------------------------------------------------------------------- Ddra = &B00001111 'PA0 - PA3 werden Ausgänge Ddrb = &B00000000 'PortB bleibt Eingang '------------------------------------------------------------------------------------------------- 'Interrupt-Service-Routinen konfigurieren und freigeben '------------------------------------------------------------------------------------------------- 'Info: 'Alle Porta Pinchangeinterrupts sind in Bascom "PCINT0" zugeordnet. 'Alle Portb Pinchangeinterrupts sind in Bascom "PCINT1" zugeordnet. Pcmsk1.pcint9 = 1 'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen Enable Pcint1 'Pinchangeinterrupt1 (1 weil auf PortB) zulassen On Pcint1 Rc_eingang_1 Nosave 'Register werden manuel in der ISR gesichert Pcmsk0.pcint7 = 1 'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen Enable Pcint0 'Pinchangeinterrupt0 (0 weil auf PortA) zulassen On Pcint0 Rc_eingang_2 Nosave 'Register werden manuel in der ISR gesichert Config Int0 = Change 'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen Enable Int0 On Int0 Rc_eingang_3 Nosave 'Register werden manuel in der ISR gesichert Enable Interrupts '====================================================== 'Hauptprogramm '====================================================== Do 'Umrechnung erstes RC Signal auf 8-Bit Berechnung_1 = Impulslaenge_1 / 8 'ergibt Werte zwischen 125 und 250 If Berechnung_1 > 255 Then 'zu hohe Werte abfangen Berechnung_1 = 255 End If If Berechnung_1 < 120 Then 'zu kleine Werte abfangen Berechnung_1 = 120 End If 'Umrechnung zweites RC Signal auf 8-Bit Berechnung_2 = Impulslaenge_2 / 8 'ergibt Werte zwischen 125 und 250 If Berechnung_2 > 255 Then 'zu hohe Werte abfangen Berechnung_2 = 255 End If If Berechnung_2 < 120 Then 'zu kleine Werte abfangen Berechnung_2 = 120 End If Servoausgabe_1 = Berechnung_1 Servoausgabe_2 = Berechnung_2 Servoausgabe_3 = 190 Servoausgabe_4 = 190 Loop '====================================================== 'ISR '====================================================== 'Rc_eingang_1: ' If Pinb.1 = 1 Then ' Rc_signal_1_start = Timer1 ' Else ' Impulslaenge_1 = Timer1 - Rc_signal_1_start ' End If 'Return Rc_eingang_1: $asm push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern sbis pinb , 1 'Skip next Instr if PINBx = 1 rjmp pulslaenge1 'Spring zur Berechnung von Impulslaenge in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_1_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_1_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte rjmp ende1 'Springe zum Ende Pulslaenge1: in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_1_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_1} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_1_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_1} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte Ende1: pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen $end Asm Return 'Rc_eingang_2: ' If Pina.7 = 1 Then ' Rc_signal_2_start = Timer1 ' Else ' Impulslaenge_2 = Timer1 - Rc_signal_2_start ' End If 'Return Rc_eingang_2: $asm push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern sbis pina , 7 'Skip next Instr if PINBx = 1 rjmp pulslaenge2 'Spring zur Berechnung von Impulslaenge in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_2_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_2_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte rjmp ende2 'Springe zum Ende Pulslaenge2: in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_2_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_2} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_2_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_2} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte Ende2: pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen $end Asm Return 'Rc_eingang_3: ' If Pinb.2 = 1 Then ' Rc_signal_3_start = Timer1 ' Else ' Impulslaenge_3 = Timer1 - Rc_signal_3_start ' End If 'Return Rc_eingang_3: $asm push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern sbis pinb , 2 'Skip next Instr if PINBx = 1 rjmp pulslaenge3 'Spring zur Berechnung von Impulslaenge in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_3_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_3_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte rjmp ende3 'Springe zum Ende Pulslaenge3: in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_3_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_3} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_3_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_3} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte Ende3: pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen $end Asm Return Servoausgabe: If Kanal = 1 Then If Porta.0 = 0 Then 'wenn der Ausgangspin aus ist Load Timer0 , Servoausgabe_1 'wird der Timer0 mit dem Wert der Variable "Servoausgabe_1" vorgeladen Porta.0 = 1 'und der Ausgangspin eingeschaltet Else 'erst beim nächsten Timer0 Überlauf landen wir hier Porta.0 = 0 'Ausgangspin wird wieder ausgeschaltet Incr Kanal 'und der nächsten Kanal bearbeitet End If End If If Kanal = 2 Then If Porta.1 = 0 Then Load Timer0 , Servoausgabe_2 Porta.1 = 1 Else Porta.1 = 0 Incr Kanal End If End If If Kanal = 3 Then If Porta.2 = 0 Then Load Timer0 , Servoausgabe_3 Porta.2 = 1 Else Porta.2 = 0 Incr Kanal End If End If If Kanal = 4 Then If Porta.3 = 0 Then Load Timer0 , Servoausgabe_4 Porta.3 = 1 Else Porta.3 = 0 Incr Kanal End If End If 'Pausenauffüllung If Kanal = 5 Then Timer0 = 0 '8-Bit Timer auf 0, Überlauf alle 2,048ms If Pausen_variable < 7 Then '2,048ms * 6 = 12,288ms Pausenfüllzeit Incr Pausen_variable Else Pausen_variable = 0 Kanal = 1 End If End If Return
Hoffentlich liegt das Ziel auch am Weg
..................................................................Der Weg zu einigen meiner Konstruktionen
Hallo
Die Verwendung des (NoSave-) Pinchange-Interrupts zum Einlesen halte ich auch für richtig, ich war nur zu faul es umzusetzen.Mit "ähnlich gut" meine ich, dass ein geringes, aber deutlich sichtbares Servozucken an den Servos vorhanden ist, welche mit den eingelesenen RC-Signalen versorgt werden. Servos, denen ich im Programm einen Festwert zuweise, zucken nicht.
Was ihr weder in der Bascom- noch in der ASM-Version beachtet ist der Überlauf des Timers während der Impulsmessung. Hier schlummert möglicherweise auch mein Denkfehler:
GrußCode:'------------------------------------------------------------------------------------------------------------- 'Hauptprogramm starten '------------------------------------------------------------------------------------------------------------- Do If Pina.7 = 1 And Empfangskanal_temp_ein(1) = 0 Then Empfangskanal_temp_ein(1) = Timer1 End If If Pina.7 = 0 And Empfangskanal_temp_ein(1) <> 0 Then Empfangskanal_temp_aus(1) = Timer1 If Empfangskanal_temp_aus(1) > Empfangskanal_temp_ein(1) Then ' Wert nur gültig wenn kein Timerüberlauf Empfangskanal(1) = Empfangskanal_temp_aus(1) - Empfangskanal_temp_ein(1) End If Empfangskanal_temp_ein(1) = 0 End If If Empfangskanal(1) <> 0 Then Servo(1) = Empfangskanal(1) End If Loop End
mic
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Inder Bascom Version funktioniert dies auch bei Timer Überlauf, solange Impulslaenge_1 nicht überläuft. Da hier nur Werte bis max 2000 kommen dürften, geht das auch so:
Rc_eingang_1:
If Pinb.1 = 1 Then
Rc_signal_1_start = Timer1
Else
Impulslaenge_1 = Timer1 - Rc_signal_1_start
End If
Return
Du brauchst also keine Vorkehrungen zu treffen, ob der aktuelle Wert größer als der vorherige ist
If Empfangskanal_temp_aus(1) > Empfangskanal_temp_ein(1) Then ' Wert nur gültig wenn kein Timerüberlauf
Ob searcher das in ASM auch so umgesetzt hat, kann ich leider nicht beurteilen.
Hallo zusammen,
ich habe mir gerade die Zeiten angesehen, die Ihr für die Ausführung der ISR vermutet. Als Anfänger und Laie weiß ich natürlich nicht, wie lange so ein Sprung in die ISR und wieder zurück dauert. Aber selbst wenn ich von rund 20 µs ausgehen, sind das "nur" 2% der Gesamtmessdauer bei einem 1ms Signal (bei 2ms wäre es nur noch 1 % Abweichung). Da die Ausgabewerte durch die Verwendung des 8-Bit-Timers dann auch noch durch 8 geteilt werden, "scheinen" mir die Sprungzeiten kaum noch relevant, oder rechne ich da falsch . Ist wie gesagt nur eine Vermutung.
mfg
Robert
Hallo Robert,
rechne mal so:
Du hast auf der Ausgabeseite eine Auflösung von 125 Schritten für die Spanne zwischen 1ms und 2ms, also für 1ms. D.h. ein Schritt hat die Dauer von 8µs. Da machen 20µs natürlich schon einen Unterschied.
Hallo, die ASM Teile sollen eine 1:1 Umsetzung der entsprechenden Bascom ISRs sein; also keine Gültigkeitsüberprüfung. Falls der Timer überläuft würde das Ergebnis der Subtraktion negativ sein. Die Impulslaenge Variable ist vom Typ Word mit 16Bit wie auch TCNT1 16Bit, kann keine negativen Zahlen enthalten, "läuft mit über" und enthält dann den gewollten Abstand von Rc_signal_start und aktuellem Timerstand. Soll auch so in der ASM funktionieren.
@radbruch: Hab noch keine Zeit gefunden, mich in Deine Version reinzudenken.
Die ASM Teile könnten noch etwas optimiert werden, wenn die Push und Pop nur da stehen, wo sie wirklich gebraucht werden. Falls PIN high ist, spart man an der Stelle fast nochmal ca 1µs.
Mit der "Servoausgabe ISR" hab ich mich auch noch nicht beschäftigt
Gerade überlege ich, ob man nicht ein Polling in einer einzigen ISR zum Pulsmessen durchführen könnte.
Also irgendeiner der drei Interrupts tritt auf und in der einzigen ISR, die allen drei Interrupts zugeordnet ist werden dann alle drei Eingänge auf ihren Zustand gepollt und über Flagsteuerung Falschberechnungen verhindert werden. Keine Ahnung, ob das schneller werden könnte ...
Gruß
Searcher
Code:Rc_eingang_1: $asm sbis pinb , 1 'Skip next Instr if PINBx = 1 rjmp pulslaenge1 'Spring zur Berechnung von Impulslaenge push r17 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_1_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_1_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte pop r17 'Register vom Stack zurückholen rjmp ende1 'Springe zum Ende Pulslaenge1: push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_1_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_1} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_1_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_1} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen Ende1: $end Asm Return
Geändert von Searcher (22.12.2013 um 13:09 Uhr)
Hoffentlich liegt das Ziel auch am Weg
..................................................................Der Weg zu einigen meiner Konstruktionen
@Searcher
Nach dem ganzen "Weihnachts- und Familienfeierstreß" habe ich mich wieder dem Programmieren zugewand. Ich habe Deinen ASM-Code mal drauf gespielt. Ist schwer zu sagen, ob es gewirkt hat: Die Servos haben vorher leicht gezuckt, und zucken hinterher auch leicht (subjektiv etwas weniger). Ich denke es liegt daran, dass wir bisher "nur" bei den 3 ISRs vom RC-Signal Einlesen Zeit gespart haben. Bei der Ausgabe wird allerding viel öfter in die ISR gesprungen (alleine 6-7 mal nur für die Pausenzeit).
Ich habe die letzten Stunden damit verbacht, Deinen ASM Code zu verstehen. Meine Güte, wer hat sich den sowas ausgedacht Obwohl ich versucht habe, mich auch hier http://www.avr-asm-tutorial.net/avr_de/index.html einzulesen, gebe ich nun offen und ehrlich zu: ASM werd ich wohl nie kapieren
Ich habe den neuen Code nochmal angehängt. Deinen Code, der die Register nur im Bedarfsfall sichert/holt, konnte ich anpassen und einfügen (war nach Deiner tollen Vorarbeit auch nicht so schwer).
Nur die Ausgabe ISR habe ich nicht realisieren können
mfg
Robert
Code:'=============================================================================== 'RC Eingang 1 an Pin 3 (PB1, PCINT9) 'RC Eingang 2 an Pin 6 (PA7, PCINT7) 'RC Eingang 3 an Pin 5 (PB2, INT0) 'Servo 1 an Pin 13 (PA0) 'Servo 2 an Pin 12 (PA1) 'Servo 3 an Pin 11 (PA2) 'Servo 4 an Pin 10 (PA3) '=============================================================================== $regfile = "attiny84.dat" $crystal = 8000000 'FuseBit CKDIV8 deaktivieren $hwstack = 50 $swstack = 50 $framesize = 50 '------------------------------------------------------------------------------------------------- 'Timer und konfigurieren '------------------------------------------------------------------------------------------------- Config Timer1 = Timer , Prescale = 8 'Timer für Einlesen RC Signale Start Timer1 Config Timer0 = Timer , Prescale = 64 'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms Enable Timer0 On Timer0 Servoausgabe '------------------------------------------------------------------------------------------------------------- 'Variablen definieren '------------------------------------------------------------------------------------------------------------- 'Variablen fürs RC Einlesen Dim Rc_signal_1_start As Word Dim Rc_signal_2_start As Word Dim Rc_signal_3_start As Word Dim Impulslaenge_1 As Word Dim Impulslaenge_2 As Word Dim Impulslaenge_3 As Word 'Variablen für Berechnungen Dim Berechnung_1 As Word Dim Berechnung_2 As Word 'Variablen für Servoausgabe Dim Kanal As Byte Dim Servoausgabe_1 As Byte Dim Servoausgabe_2 As Byte Dim Servoausgabe_3 As Byte Dim Servoausgabe_4 As Byte Dim Pausen_variable As Byte '------------------------------------------------------------------------------------------------- 'Einigen Variablen Werte zuweisen '------------------------------------------------------------------------------------------------- Kanal = 1 Pausen_variable = 0 '------------------------------------------------------------------------------------------------------------- 'Ein- und Ausgang festlegen '------------------------------------------------------------------------------------------------------------- Ddra = &B00001111 'PA0 - PA3 werden Ausgänge Ddrb = &B00000000 'PortB bleibt Eingang '------------------------------------------------------------------------------------------------- 'Interrupt-Service-Routinen konfigurieren und freigeben '------------------------------------------------------------------------------------------------- 'Info: 'Alle Porta Pinchangeinterrupts sind in Bascom "PCINT0" zugeordnet. 'Alle Portb Pinchangeinterrupts sind in Bascom "PCINT1" zugeordnet. Pcmsk1.pcint9 = 1 'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen Enable Pcint1 'Pinchangeinterrupt1 (1 weil auf PortB) zulassen On Pcint1 Rc_eingang_1 Nosave 'Register werden manuel in der ISR gesichert Pcmsk0.pcint7 = 1 'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen Enable Pcint0 'Pinchangeinterrupt0 (0 weil auf PortA) zulassen On Pcint0 Rc_eingang_2 Nosave 'Register werden manuel in der ISR gesichert Config Int0 = Change 'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen Enable Int0 On Int0 Rc_eingang_3 Nosave 'Register werden manuel in der ISR gesichert Enable Interrupts '====================================================== 'Hauptprogramm '====================================================== Do 'Umrechnung erstes RC Signal auf 8-Bit Berechnung_1 = Impulslaenge_1 / 8 'ergibt Werte zwischen 125 und 250 If Berechnung_1 > 255 Then 'zu hohe Werte abfangen Berechnung_1 = 255 End If If Berechnung_1 < 120 Then 'zu kleine Werte abfangen Berechnung_1 = 120 End If 'Umrechnung zweites RC Signal auf 8-Bit Berechnung_2 = Impulslaenge_2 / 8 'ergibt Werte zwischen 125 und 250 If Berechnung_2 > 255 Then 'zu hohe Werte abfangen Berechnung_2 = 255 End If If Berechnung_2 < 120 Then 'zu kleine Werte abfangen Berechnung_2 = 120 End If Servoausgabe_1 = Berechnung_1 Servoausgabe_2 = Berechnung_2 Servoausgabe_3 = 190 Servoausgabe_4 = 190 Loop '====================================================== 'ISR '====================================================== 'Rc_eingang_1: ' If Pinb.1 = 1 Then ' Rc_signal_1_start = Timer1 ' Else ' Impulslaenge_1 = Timer1 - Rc_signal_1_start ' End If 'Return Rc_eingang_1: $asm sbis pinb , 1 'Skip next Instr if PINBx = 1 rjmp pulslaenge1 'Spring zur Berechnung von Impulslaenge push r17 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_1_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_1_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte pop r17 'Register vom Stack zurückholen rjmp ende1 'Springe zum Ende Pulslaenge1: push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_1_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_1} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_1_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_1} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen Ende1: $end Asm Return 'Rc_eingang_2: ' If Pina.7 = 1 Then ' Rc_signal_2_start = Timer1 ' Else ' Impulslaenge_2 = Timer1 - Rc_signal_2_start ' End If 'Return Rc_eingang_2: $asm sbis pinA , 7 'Skip next Instr if PINBx = 1 rjmp pulslaenge2 'Spring zur Berechnung von Impulslaenge push r17 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_2_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_2_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte pop r17 'Register vom Stack zurückholen rjmp ende2 'Springe zum Ende Pulslaenge2: push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_2_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_2} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_2_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_2} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen Ende2: $end Asm Return 'Rc_eingang_3: ' If Pinb.2 = 1 Then ' Rc_signal_3_start = Timer1 ' Else ' Impulslaenge_3 = Timer1 - Rc_signal_3_start ' End If 'Return Rc_eingang_3: $asm sbis pinb , 2 'Skip next Instr if PINBx = 1 rjmp pulslaenge3 'Spring zur Berechnung von Impulslaenge push r17 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen sts {Rc_signal_3_start} , r17 'Speichere Timer1 low Byte nach Rc_signal low Byte in r17 , tcnt1h 'Timer1 high Byte holen sts {Rc_signal_3_start} + 1 , r17 'Speichere Timer1 high Byte nach Rc_signal high Byte pop r17 'Register vom Stack zurückholen rjmp ende3 'Springe zum Ende Pulslaenge3: push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 'Register auf Stack sichern push r18 'Register auf Stack sichern in r17 , tcnt1l 'Timer1 low Byte holen lds r18 , {Rc_signal_3_start} 'Hole Rc_signal low Byte Sub R17 , R18 'Subtrahiere Rc_signal low Byte von Timer1 low Byte sts {Impulslaenge_3} , r17 'Speichere Resultat low Byte nach Impulslaenge low Byte in r17 , tcnt1h 'Timer1 high Byte holen lds r18 , {Rc_signal_3_start} + 1 'Hole Rc_signal high Byte sbc r17 , r18 'Subtrahiere Rc_signal high Byte von Timer1 high Byte sts {Impulslaenge_3} + 1 , r17 'Speichere Resultat high Byte nach Impulslaenge high Byte pop r18 'Register vom Stack zurückholen pop r17 'Register vom Stack zurückholen Out Sreg , R16 'Statusregister zurückspeichern pop r16 'Register vom Stack zurückholen Ende3: $end Asm Return Servoausgabe: If Kanal = 1 Then If Porta.0 = 0 Then 'wenn der Ausgangspin aus ist Load Timer0 , Servoausgabe_1 'wird der Timer0 mit dem Wert der Variable "Servoausgabe_1" vorgeladen Porta.0 = 1 'und der Ausgangspin eingeschaltet Else 'erst beim nächsten Timer0 Überlauf landen wir hier Porta.0 = 0 'Ausgangspin wird wieder ausgeschaltet Incr Kanal 'und der nächsten Kanal bearbeitet End If End If If Kanal = 2 Then If Porta.1 = 0 Then Load Timer0 , Servoausgabe_2 Porta.1 = 1 Else Porta.1 = 0 Incr Kanal End If End If If Kanal = 3 Then If Porta.2 = 0 Then Load Timer0 , Servoausgabe_3 Porta.2 = 1 Else Porta.2 = 0 Incr Kanal End If End If If Kanal = 4 Then If Porta.3 = 0 Then Load Timer0 , Servoausgabe_4 Porta.3 = 1 Else Porta.3 = 0 Incr Kanal End If End If 'Pausenauffüllung If Kanal = 5 Then Timer0 = 0 '8-Bit Timer auf 0, Überlauf alle 2,048ms If Pausen_variable < 7 Then '2,048ms * 6 = 12,288ms Pausenfüllzeit Incr Pausen_variable Else Pausen_variable = 0 Kanal = 1 End If End If Return
Lesezeichen