-
So, nach gefühlten 30 days of night war es am Ende doch nicht so schwierig, den Takt über HW auszugeben :?
Dafür wird der Timer0 im fast PWM Modus mit OCRA als Top betrieben. Bei Comparematch wird der Ausgang OC0A getoggelt. UMVERDRAHTEN von PD2 nach PB2
Der Drehgeber verändert mit seinen Impulsen aus der Links-/Rechtsroutine heraus das OCRA Register und ändert damit die Frequenz. Wahrscheinlich hat sich die Wirkung der Drehrichtung geändert. Die Wahl fiel auf PWM Modus, da hier das Update des OCRA nicht sofort geschieht, sondern nur zu einem bestimmten TCNT0 Stand.
Da hatte ich auch gewisse Schwierigkeiten. Nach Datenblatt für Tiny2313 findet der Update bei Zählerstand Top statt. Nun ist OCRA aber Top. Was passiert, wenn getoggelt wird und "gleichzeitig" OCRA verändert wird. Konnte ich dem Datenblatt nicht entnehmen.
Den Fall wird es selten geben, aber er ist vorhanden und wird deshalb auch eintreten (nach Murphy - und nach Drehencoderbetätigung). Vielleicht macht es nichts - Ausprobieren.
Bei zB einem Mega88 wird das OCRA nach Datenblatt bei Bottom upgedated. Da hätte ich überhaupt keine Bedenken.
Ganz sicher bin ich mir wie immer nicht, ob ich den Rest richtig umgeschrieben habe.
Wenn Du ein langes Wochenende hast, könnte es jetzt gelaufen sein ;):)
Code:
' BASCOM-Programm
' Stefan Hoffmann 2009
' Drehimpulsgeber/Encoder mit ENCODER-Befehl
'
' In: Drehimpulsgeber an d.0 und d.1 sowie Taster
' Testprogramm für A3967 Platine mit Dir Step und Enable
' Modifiziert von Searcher die dritte mit zusätzlichem Timer1
' Timer0 für HW-Step Ausgabe auf PB2(OC0A) im fast PWM genutzt !!!
' UMVERKABELN: Taktausgabe nun auf PB2 statt PD6
$regfile = "attiny2313.dat"
$framesize = 32
$swstack = 32
$hwstack = 34 '1. 32 nach 34 geändert
$crystal = 8000000 'Interner Osz. 8 MHz
'*** $baud = 9600 aktivieren nur wenn UART auch genutzt wird.
' Inputs: Drehimpulsgeber an d.0 und d.1 sowie Taster an d.3
'-----Deklarationen fuer Drehimpulsgeber:
Config Pind.0 = Input
Encoder_a Alias Pind.0 'Encoder Signal B an Pin 2
Config Pind.1 = Input
Encoder_b Alias Pind.1 'Encoder Signal A an Pin 3
Config Pind.3 = Input
Taster1 Alias Pind.3 'Taster
Portd.0 = 1 'Pullups für den Drehencoder
Portd.1 = 1 '2. pind nach portd geändert
Portd.3 = 1
'LED-Outputs stellvertretend für Step, Dir, Enable
'In der endgültigen Hardware liegen: Step/Takt auf PD.2(PB.2) / Taster auf PD.3 / Enable auf PD4 / Richtung auf PD5 /
Config Portb.2 = Output '!!!!!von PD2 nach PB2(OC0A) geändert !!!!!!!!!!!!
Config Portd.5 = Output
Portd.5 = 0 ' Pin 9 - Dir - Richtungssignal
Config Portd.4 = Output
Portd.4 = 0 ' Pin 16 - Enable - generelles Ein-Ausschaltsignal
Config Portb.0 = Output
Portb.0 = 0 'Pin 9 - LED_DE - am Drehencoder Anzeige
Chip_dir Alias Portd.5
Chip_enable Alias Portd.4
Dim Wert As Byte 'statt word als byte declariert
Wert = 127 'Mit mittlerer Geschwindigkeit anfangen, Startwert für den Drehencoder
Dim Zustand As Byte
'*****************Deklarationen für den Taster - am DE - für die Lang-kurz- und Doppelklickroutine
Dim Zaehler As Byte
Const Langzaehler = 100 'Danach gilt die Taste als lange gedrueckt
Const Doppelzaehler = 20 'Innerhalb dessen muss zweiter Klick erfolgen
Dim Gedrueckt As Byte 'Art des Drueckens (Kurz/Lang/Doppel)
Const Kurz = 1
Const Lang = 2
Const Doppel = 3
Dim I As Byte
Chip_enable = 1 'Motor aus
Chip_dir = 1 'Dir
'*******************************************************************************
'Neue Timer0 Konfiguration. Hab kein BASCOM Kommando für Timer0 - Fast PWM und OC0A Toggle gefunden
'deshalb "zu Fuß"
Tccr0a = Bits(com0a0 , Wgm01 , Wgm00) 'toggle OC0A, fast PWM
Tccr0b = Bits(wgm02 , Cs02 , Cs00) 'fast PWM - top OCR0A, prescale 1024
'*******************************************************************************
Const Anz_umschaltungen = 6 'Hier Anzahl der Laufrichtungsumschaltungen festlegen, mindestens 2
Dim Umschaltungen As Byte 'Zählt Laufrichtungsumschaltungen
Umschaltungen = 0 'initialiesieren (ist aber an dieser Programmstelle sowieso = 0)
Dim Sekunden As Byte 'Dient zum Abzählen von Sekunden in der Isr_Sekunden_takt
Sekunden = 1 'initialisieren
Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1 'Clear Timer on Compare Match
Compare1a = 31249 'Wert für eine Sekunde, Timer fängt nach einer Sekunde wieder bei 0 an
On Compare1a Isr_sekunden_takt
'Compare1a Interrupt wird erst in der Haupschleife enabled
Enable Interrupts
'***********Hauptschleife:**********
Do
Zustand = Encoder(pind.0 , Pind.1 , Linksroutine , Rechtsroutine , 0)
Debounce Taster1 , 0 , Tastenauswertung , Sub
Select Case Gedrueckt 'Hier koennen beliebige Anweisungen erfolgen
Case Kurz: 'Es wurde einmal kurz gedrueckt
Chip_enable = 0 'Motor ein bei einmal kurz gedrückt
Case Lang: 'Die Taste wurde lange gedrueckt
If Timsk.ocie1a = 0 Then 'Wenn Comparematchinterrupt nicht enabled, dann..
Toggle Chip_dir 'Sofort Laufrichtung umschalten
Incr Umschaltungen 'Zähler für Laufrichtungsumschaltungen erhöhen
Timer1 = 0 'Timercounter von Beginn an laufen lassen
Set Tifr.ocf1a
Enable Compare1a 'ISR für Sekundenzählen und Chip_dir Toggle einschalten
Else
If Umschaltungen = Anz_umschaltungen Then 'Wenn genug Umschaltungen, dann aufhören
Disable Compare1a 'Isr für Chip_dir toggle abschalten
Sekunden = 1 'Für nächsten Gebrauch initialisieren
Umschaltungen = 0 'Für nächsten Gebrauch initialisieren
Gedrueckt = Kurz 'In Normallauf schalten
End If
End If
Case Doppel: 'Die Taste wurde doppelt gedrueckt
Chip_enable = 1 'Motor aus wenn doppelt gedrückt
Disable Compare1a 'Isr für Chip_dir toggle abschalten
Sekunden = 1 'Für nächsten Gebrauch initialisieren
Umschaltungen = 0 'Für nächsten Gebrauch initialisieren
End Select
Loop
End
'**********************Interrupt-Routine Timer1 Sekundentakt *******************
Isr_sekunden_takt: 'ISR toggelt alle 6 Sekunden den Chip_dir
If Sekunden < 6 Then 'solange noch keine 6 Mal durchlaufen ...
Incr Sekunden '...nur inkrementieren
Else 'sonst ...
Sekunden = 1 'Sekundenzähler zurücksetzten und ...
Toggle Chip_dir '... Laufrichtung umschalten
Incr Umschaltungen 'Zähler für Laufrichtungsumschaltungen erhöhen
End If
Return
'***********************Sub-Routinen Drehencoder ******************************
Linksroutine:
If Wert > 21 Then Decr Wert
Ocr0a = Wert
Return
Rechtsroutine:
If Wert < 250 Then Incr Wert
Ocr0a = Wert
Return
'*****************Subroutine Tasterauswertung **********************************
Tastenauswertung:
Zaehler = 0
Do
Incr Zaehler
Waitms 10
Loop Until Taster1 = 1 Or Zaehler = Langzaehler
If Zaehler = Langzaehler Then 'lange gedrueckt
Gedrueckt = Lang
Else 'einmal kurz gedrueckt
Zaehler = 0
Do
Incr Zaehler
Waitms 10
Loop Until Taster1 = 0 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
PS: Und was ich gerade noch entdeckt habe: Mit der Angabe $baud initialisiert BASCOM die Register für UART. Du hast den Encoder auf RX und TX hängen. Hat anscheinend bisher nichts ausgemacht. Um Verwicklungen zu vermeiden könnte man das auskommentieren. Hab ich gerade noch im Code oben gemacht.
Gruß
Searcher