Zitat Zitat von R2D2 Bastler Beitrag anzeigen
Sowas habe ich bereits versucht umzusetzen, ....
Gut, doch keine neue Idee Egal, dann hab ich was zum Testen für Dich. Eine Übersetzung der Ausgabe ISR nach ASM. Ohne Gewähr (wie immer) da ich außer Kompilieren nicht getestet habe.
Ist wieder nichts weiter als eine fast 1:1 Übersetzung von der Funktion her. In der Bascom ISR wird mit "Load Timer" gearbeitet. Das hab ich zur "Servoausgabe_x" Berechnung in der Hauptschleife vorweggenommen und nicht weiter überprüft, ob das so hinhauen kann. Sollte eigentlich nach der Bascom Hilfe zu LOAD. - nosave - bei der ON Timer0 label Anweisung. Viel Muße bei der Durchsicht

Könnte mir jemand Schritt für Schritt erklären, wie ich einen passenden ASM Code basteln kann, ohne dafür 3 Jahre an die Uni zu müssen?
Das wär zu viel für mich Hab versucht gut zu kommentieren.

Gruß
Searcher

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