Code:
'*******************************************************************************
'***   Programm zur manuellen Ansteuerung eines Steppers mit clk, Dir, Enable***
'***   mit Pollin Drehencoder                                                ***
'*******************************************************************************
'***   Author: MrMiffy08                                                        ***
'***   Datum:  2.4.2012                                                      ***
'*******************************************************************************
'*** mit Attiny 2313

'Pind.1 Encoder Signal A   Pin 2
'Pind.0 Encoder Signal B   Pin 3
'Pind.3 Drehencoder Taster      Pin 7

'Pind.2 Output für Motor_Takt   Pin 6
'Pind.4 Motor Enable Output     Pin 8
'Pind.5 Motor Richtung DIR Output  Pin9

$regfile = "attiny2313.dat"
$crystal = 8000000
$swstack = 10

'System-Timer für periodische Encoder-Abfrage

Config Timer0 = Timer , Prescale = 64
On Timer0 Isr_timer0
Enable Timer0
Const Timer0_reload = 131                                   'Wert für 1ms Abfragetakt Dreh-Encoder


'Inputs: Drehencoder-Anschlüsse
Config Portd.0 = Input : Set Portd.0 : Ph_b Alias Pind.0    'Encoder Signal B  an Pin 2
Config Portd.1 = Input : Set Portd.1 : Ph_a Alias Pind.1    'Encoder Signal A  an Pin 3
Config Portd.3 = Input : Set Portd.3 : Encoder_switch Alias Pind.3       'Drehencoder Taster   Pin 7
'Outputs
Config Portd.2 = Output : Set Portd.2 : Mot_takt Alias Pind.2       'Output für Motor_Takt Pin 6 hier muss der Takt rauskommen
Config Portd.4 = Output : Set Portd.4 : Motor_enable_output Alias Pind.4       'Motor Enable Output Pin 8 - braucht High für Motor On
Config Portd.5 = Output : Set Portd.5 : Mot_dir Alias Pind.5       'Motor DIR Output Pin 9 Richtungswechsel mit H/L
'Config Portd.5 = Output : Set Portd.5 : Mot_takt_2 Alias Pind.5       ' dies ist der 2. Phaseneingang beim A3966 für die Richtungssteuerung



Config Encoder_switch = 1                                   'Taster Pullup, muss initial auf High sein!
Config Motor_enable_output = 0                              'Pulldown an Motor Enable Ausgang  - muss initial auf GND

Config Timer1 = Timer , Prescale = 8 Timer1                 'Einstellungen Für Den Motor -takt = 24s/sec
Const Timer1_reload = 23869


Const Langzaehler = 100                                     'nach 100ms gilt die Taste als lange gedrueckt
Const Doppelzaehler = 20                                    'Innerhalb dessen muss zweiter Klick erfolgen
Dim Zaehler As Byte
Dim Gedrueckt As Byte                                       'Art des Drueckens (Kurz/Lang/Doppel)

Const Kurz = 1
Const Lang = 2
Const Doppel = 3





'*******************************************************************************
'***   Variablen                                                             ***
'*******************************************************************************

Dim Rotary As Byte                                          'Zahlenwert des Encoders
Dim Rotary0 As Byte                                         'Aktueller Rasterwert (A,B)
Dim Rotary1 As Byte                                         'Übergangswert (A,B) zwischen Rastungen
Dim Rotary2 As Byte                                         'Letzter Rasterwert (A,B)
Dim Rotary_last As Byte                                     'Letzter Encoder-Wert (nur für Demo)

Dim Motakt As Word
Dim Motakt_timer As Word
'Dim Motakt_2 As Word



'*******************************************************************************
'***   ISR_TIMER0                                                            ***
'***   Periodische Auswertung des Dreh-Encoders                              ***
'*******************************************************************************

Enable Interrupts

Isr_timer0:
Timer0 = Timer0_reload


Shift Rotary0 , Left , 1                                    'Schieberegister für Entprellung (A,B)

Rotary0.4 = Ph_a                                            'Phase A lesen -> Bit 4
Rotary0.0 = Ph_b                                            'Phase B lesen -> Bit 0

If Rotary0 <> Rotary2 Then                                  'Neues Signalpaar (A,B) ?
   Select Case Rotary0
      Case &B0000_0000                                      'Aktuell (A,B)= (0,0)
         Select Case Rotary1
            Case &B1111_0000                                'Übergang war (A,B)= (1,0), also
               Incr Rotary                                  'Encoder-Wert erhöhen
            Case &B0000_1111                                'Übergang (A,B)= (0,1), also
               Decr Rotary                                  'Encoder-Wert verringern
   End Select
           Rotary2 = &B0000_0000                            'Aktuelles (A,B) in vorheriges (A,B)
      Case &B0000_1111                                      'Übergang (A,B)= (0,1) zwischen Rastungen
         Rotary1 = &B0000_1111                              'erkennen und in abspeichern
      Case &B1111_0000                                      'Übergang (A,B)= (1,0) zwischen Rastungen
         Rotary1 = &B1111_0000                              'erkennen und abspeichern
      Case &B1111_1111                                      'Aktuell (A,B)= (1,1)
   Select Case Rotary1
      Case &B0000_1111                                      'Übergang war (A,B)= (0,1), also
         Incr Rotary                                        'Encoder-Wert erhöhen
      Case &B1111_0000                                      'Übergang war (A,B)= (1,0), also
         Decr Rotary                                        'Encoder-Wert verringern
   End Select
         Rotary2 = &B1111_1111                              'Aktuelles (A,B) in vorheriges (A,B)
   End Select
End If
Return


Debounce Encoder_switch , 0 , Tastenauswertung , Sub        'Subroutine Art des Drueckens (Kurz/Lang/Doppel)

'*******************************************************************************
'***   HAUPTPROGRAMM                                                         ***
'*******************************************************************************


Do

Motakt = 24
If Rotary_last <> Rotary Then                               'Encoder gedreht?

   If Rotary_last > Rotary Then                             'Motor langsamer regeln
       If Motakt > 24 Then
         Motakt = Motakt - 10
       End If
   Else
   Motakt = 24
End If


If Rotary_last < Rotary Then                                'Motor schneller regeln
     If Motakt < 240 Then
         Motakt = Motakt + 10
     End If
   Else
   Motakt = 240
End If

Rotary_last = Rotary                                        'Neue Stellung merken

End If


Motakt_timer = Motakt / 240                                 '240 = pre 1 und 32203 für Timer1
Motakt_timer = Motakt_timer * 32203



'Tastendruckauswertung:
Select Case Gedrueckt                                       'Hier koennen beliebige Anweisungen erfolgen

   Case Kurz:                                               'Es wurde einmal kurz gedrueckt
   Motor_enable_output = 1                                  'Zur Demo hier LEDs
   Waitms 200

   Case Lang:                                               'Die Taste wurde lange gedrueckt
   Mot_dir = 1
   Waitms 200

   Case Doppel:                                             'Die Taste wurde doppelt gedrueckt
   Mot_dir = 0
   Waitms 200
End Select
   Portd.3 = 1                                              'und wieder auf Null setzen

Loop

End                                                         'end program



'*******************************************************************************
'***   ISR_TIMER1                                                           ***
'***   Takterzeugung                              ***
'*******************************************************************************

On Timer1 : Timer1 = Motakt_timer                           'Jeder Timer Überlauf macht den Takt für den Motor
On Int1 Mot_takt_toggeln                'Hier müsste jetzt D.2 takten und zwar nach der Vorgabe von Rotary
'Mot_takt_2 = Not Portd.2                                    'gegenläufiges Toggeln von




'bei (kurzem) Tastendruck an PinD.3 der Motor über Portd.4 enabled werden und mit 24/sec loslaufen

'bei langem Tastendruck - 1 sec. (gleicher PortPin wie oben, also  PinD.3) Ausgang Portd.5 = Dir toggelt, jeweils 3 sec in eine Richtung, dann 3 sec in andere Richtung.

'bei Doppelklick   stoppt das Hin und Her wieder - weiter in eine Richtung.
'sowie eine Routine die eine Led ansteuert - ist aber sekundär (wenn dann an PB0)

'Jetzt muss noch (für A3966) der Phase_2 Ausgang gegenläufig mitgehen...

'*******************************************************************************
'***   Subroutine                                                           ***
'***   Tastendruckauswertung                              ***
'*******************************************************************************
Tastenauswertung:                                           'Subroutine Tastenauswertung:
  Zaehler = 0
  Do
    Incr Zaehler
    Waitms 10
  Loop Until Encoder_switch = 0 Or Zaehler = Langzaehler

  If Zaehler = Langzaehler Then
      Gedrueckt = Lang                                      'lange gedrueckt

  Else                                                      'einmal kurz gedrueckt
      Zaehler = 0
      Do
      Incr Zaehler
         Waitms 10
      Loop Until Encoder_switch = 1 Or Zaehler = Doppelzaehler

      If Zaehler = Doppelzaehler Then                       'bleibt bei einmal kurz
      Gedrueckt = Kurz
      Else
      Gedrueckt = Doppel                                    'zweites Mal kurz gedrueckt
      End If

  End If

Return


'*******************************************************************************
'***   Subroutine                                                           ***
'***   LED-Ausgabe                                                          ***
'*******************************************************************************

'hier kommt noch was
Mot_takt_toggeln:
Return
Fehlerfrei kompilierbar mit Bascom-AVR 1.11.9.8