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 Nosave 'Register werden manuell in der ISR gesichert
'-------------------------------------------------------------------------------------------------------------
'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 = 256 - Berechnung_1 'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
Servoausgabe_2 = 256 - Berechnung_2 'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
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
$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
lds r17 , {kanal} 'hole Kanalnummer
cpi r17 , 1 'check Kanal und ...
brne LABEL_KANAL_2 '... "wenn nicht gleich" verzweige zum nächsten Kanal
sbic porta , 0 'Skip next instr. wenn PORTA.0 = 0 ist
rjmp label_1 'Springe zum LOW-setzen des Servosignals
lds r18 , {Servoausgabe_1} 'Hole aufbereiteten Pulslängenwert für Timer0
Out Tcnt0 , R18 'Setze Timer0 mit Pulslängenwert
sbi porta , 0 'Setze Servosignal HIGH
rjmp Ende_isr 'Springe zum Ende der ISR
Label_1:
cbi porta , 0 'Setze Servosignal nach LOW
inc r17 'Erhöhe Kanalnummer
sts {kanal} , r17 'Sichere Kanalnummer
'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
Label_kanal_2: 'Bearbeitung von Kanal 2
cpi r17 , 2 'check Kanal und ...
brne LABEL_KANAL_3 '... "wenn nicht gleich" verzweige zum nächsten Kanal
sbic porta , 1 'Skip next instr. wenn PORTA.1 = 0 ist
rjmp label_2 'Springe zum LOW-setzen des Servosignals
lds r18 , {Servoausgabe_2} 'Hole aufbereiteten Pulslängenwert für Timer0
Out Tcnt0 , R18 'Setze Timer0 mit Pulslängenwert
sbi porta , 1 'Setze Servosignal HIGH
rjmp Ende_isr 'Springe zum Ende der ISR
Label_2:
cbi porta , 1 'Setze Servosignal nach LOW
inc r17 'Erhöhe Kanalnummer
sts {kanal} , r17 'Sichere Kanalnummer
'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
Label_kanal_3: 'Bearbeitung von Kanal 3
cpi r17 , 3 'check Kanal und ...
brne LABEL_KANAL_4 '... "wenn nicht gleich" verzweige zum nächsten Kanal
sbic porta , 2 'Skip next instr. wenn PORTA.2 = 0 ist
rjmp label_3 'Springe zum LOW-setzen des Servosignals
lds r18 , {Servoausgabe_3} 'Hole aufbereiteten Pulslängenwert für Timer0
Out Tcnt0 , R18 'Setze Timer0 mit Pulslängenwert
sbi porta , 2 'Setze Servosignal HIGH
rjmp Ende_isr 'Springe zum Ende der ISR
Label_3:
cbi porta , 2 'Setze Servosignal nach LOW
inc r17 'Erhöhe Kanalnummer
sts {kanal} , r17 'Sichere Kanalnummer
'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
Label_kanal_4: 'Bearbeitung von Kanal 4
cpi r17 , 4 'check Kanal und ...
brne LABEL_KANAL_5 '... "wenn nicht gleich" verzweige zum nächsten Kanal
sbic porta , 3 'Skip next instr. wenn PORTA.3 = 0 ist
rjmp label_4 'Springe zum LOW-setzen des Servosignals
lds r18 , {Servoausgabe_4} 'Hole aufbereiteten Pulslängenwert für Timer0
Out Tcnt0 , R18 'Setze Timer0 mit Pulslängenwert
sbi porta , 3 'Setze Servosignal HIGH
rjmp Ende_isr 'Springe zum Ende der ISR
Label_4:
cbi porta , 3 'Setze Servosignal nach LOW
inc r17 'Erhöhe Kanalnummer
sts {kanal} , r17 'Sichere Kanalnummer
'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
Label_kanal_5: 'Bearbeitung von Kanal 5
cpi r17 , 5 'check Kanal und ...
brne Ende_isr '... "wenn nicht gleich" verzweige zum Ende der ISR
clr r18 'Setze r18 auf 0
Out Tcnt0 , R18 'Setze Timer0 auf 0
lds r18 , {pausen_variable} 'Hole Pausenvariable
cpi r18 , 7 'Vergleiche mit 7
brlo label_incr_pause 'Ist Pausenvariable (r18) kleiner 7 verzweige
clr r18 'Setze r18 auf 0
sts {pausen_variable} , r18 'Setze Pausenvariable auf 0
ldi r17 , 1 'Setze r17 auf 1
sts {kanal} , r17 'Setze Kanal auf 1 (Speichere r17 nach Kanal)
rjmp ende_isr 'Springe
Label_incr_pause:
inc r18 'Erhöhe r18 um 1
sts {pausen_variable} , r18 'Speichere r18 nach Pausenvariable
Ende_isr:
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
Lesezeichen