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 Rc_signal_1_stop As Word
Dim Rc_signal_2_stop As Word
Dim Rc_signal_3_stop As Word
Dim Rc_signal_1_stop_flag As Byte
Dim Rc_signal_2_stop_flag As Byte
Dim Rc_signal_3_stop_flag As Byte
Dim Impulslaenge_1 As Byte
Dim Impulslaenge_2 As Byte
Dim Impulslaenge_3 As Byte
'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
  If Rc_signal_1_stop_flag = 1 Then     'Bearbeitung nur, wenn ISR Pulsende gefunden hat
      Disable Pcint1                    'Mögliche Korruption durch ISR vorbeugen
      Impulslaenge_1 = Rc_signal_1_stop - Rc_signal_1_start
      Enable Pcint1
      Rc_signal_1_stop_flag = 0
      Berechnung_1 = Impulslaenge_1
      Shift Berechnung_1 , Right , 3    'Division von Berechnung_1 durch 8
      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
      Servoausgabe_1 = 256 - Berechnung_1       'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
  End If
  If Rc_signal_2_stop_flag = 1 Then     'Bearbeitung nur, wenn ISR Pulsende gefunden hat
      Disable Pcint0                    'Mögliche Korruption durch ISR vorbeugen
      Impulslaenge_2 = Rc_signal_2_stop - Rc_signal_2_start
      Enable Pcint0
      Rc_signal_2_stop_flag = 0
      Berechnung_2 = Impulslaenge_2
      Shift Berechnung_2 , Right , 3    'Division von Berechnung_1 durch 8
      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_2 = 256 - Berechnung_2       'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
  End If
  Servoausgabe_3 = 190
  Servoausgabe_4 = 190
Loop
'======================================================
'ISR
'======================================================
Rc_eingang_1:
 $asm
   push r17                             'Register auf Stack sichern
   sbis pinb , 1                        'Skip next Instr if PINBx = 1
   rjmp Puls_ende1                      'Springe Puls_ende
   in r17 , tcnt1l                      'Timer1 low Byte holen
   sts {Rc_signal_1_start} , r17        'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
   in r17 , tcnt1h                      'Timer1 high Byte holen
   sts {Rc_signal_1_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
   rjmp ende1                           'Springe zum Ende
  Puls_ende1:
   in r17 , tcnt1l                      'Timer1 low Byte holen
   sts {Rc_signal_1_stop} , r17         'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
   in r17 , tcnt1h                      'Timer1 high Byte holen
   sts {Rc_signal_1_stop} + 1 , r17     'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
   ldi r17 , 1
   sts {Rc_signal_1_stop_flag} , r17    'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
  Ende1:
   pop r17                              'Register vom Stack zurückholen
 $end Asm
Return
Rc_eingang_2:
 $asm
   push r17                             'Register auf Stack sichern
   sbis pinA , 7                        'Skip next Instr if PINBx = 1
   rjmp Puls_ende2                      'Springe Puls_ende
   in r17 , tcnt1l                      'Timer1 low Byte holen
   sts {Rc_signal_2_start} , r17        'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
   in r17 , tcnt1h                      'Timer1 high Byte holen
   sts {Rc_signal_2_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
   rjmp ende2                           'Springe zum Ende
  Puls_ende2:
   in r17 , tcnt1l                      'Timer1 low Byte holen
   sts {Rc_signal_2_stop} , r17         'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
   in r17 , tcnt1h                      'Timer1 high Byte holen
   sts {Rc_signal_2_stop} + 1 , r17     'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
   ldi r17 , 1
   sts {Rc_signal_2_stop_flag} , r17    'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
  Ende2:
   pop r17                              'Register vom Stack zurückholen
 $end Asm
Return
Rc_eingang_3:
 $asm
   push r17                             'Register auf Stack sichern
   sbis pinB , 2                        'Skip next Instr if PINBx = 1
   rjmp Puls_ende3                      'Springe Puls_ende
   in r17 , tcnt1l                      'Timer1 low Byte holen
   sts {Rc_signal_3_start} , r17        'Speichere Timer1 low Byte nach Rc_signal_x_start low Byte
   in r17 , tcnt1h                      'Timer1 high Byte holen
   sts {Rc_signal_3_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal_x_start high Byte
   rjmp ende3                           'Springe zum Ende
  Puls_ende3:
   in r17 , tcnt1l                      'Timer1 low Byte holen
   sts {Rc_signal_3_stop} , r17         'Speichere Timer1 low Byte nach Rc_signal_x_stop low Byte
   in r17 , tcnt1h                      'Timer1 high Byte holen
   sts {Rc_signal_3_stop} + 1 , r17     'Speichere Timer1 high Byte nach Rc_signal_x_stop high Byte
   ldi r17 , 1
   sts {Rc_signal_3_stop_flag} , r17    'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
  Ende3:
   pop r17                              'Register vom Stack zurückholen
 $end Asm
Return
Servoausgabe:
 $asm
   push r16                             'Register auf Stack sichern
   in r16,sreg                          'Statusregister holen und halten
   push r17                             '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
   sts {kanal} , r17                    'Sichere Kanalnummer
   lds r17 , {Servoausgabe_1}           'Hole aufbereiteten Pulslängenwert für Timer0
   Out Tcnt0 , R17                      '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
  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
   sts {kanal} , r17                    'Sichere Kanalnummer
   lds r17 , {Servoausgabe_2}           'Hole aufbereiteten Pulslängenwert für Timer0
   Out Tcnt0 , R17                      '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
  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
   sts {kanal} , r17                    'Sichere Kanalnummer
   lds r17 , {Servoausgabe_3}           'Hole aufbereiteten Pulslängenwert für Timer0
   Out Tcnt0 , R17                      '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
  Label_kanal_4:                        'Bearbeitung von Kanal 4 mit anschließendem Pausenanfang
   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
   sts {kanal} , r17                    'Sichere Kanalnummer
   lds r17 , {Servoausgabe_4}           'Hole aufbereiteten Pulslängenwert für Timer0
   Out Tcnt0 , R17                      '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
'Pausenauffüllung
   'Pausenanfang
   inc r17
   sts {kanal} , r17                    'Sichere Kanalnummer
   ldi r17 , &B00000101                 'CS00 und CS02 für prescaler 1024 in Timer0 vorbereiten
   Out Tccr0b , R17                     'Timer0 läuft mit 128µs Auflösung
   ldi r17 , 162                        'Wert für ca 12ms bis zum nächsten OVF (162=256-94) bei prescaler 1024
   Out Tcnt0 , R17
   rjmp Ende_isr                        'Springe zum Ende der ISR
  'Pausenende
  Label_kanal_5:                        'Bearbeitung von Kanal 5 (Pausenende)
   ldi r17 , &B00000011                 'CS00 und CS01 für prescaler 64 in Timer0 vorbereiten
   Out Tccr0b , R17                     'Timer0 läuft wieder mit 8µs Auflösung
   ldi r17 , 1                          'Kanalnummer auf 1 setzen
   sts {kanal} , r17                    'Sichere Kanalnummer
  Ende_isr:
   pop r17                              'Register vom Stack zurückholen
   Out Sreg , R16                       'Statusregister zurückspeichern
   pop r16                              'Register vom Stack zurückholen
 $end Asm
Return
 
						
Lesezeichen