'******************************************************** '* LCD Uhr mit Polin Drehencoder '* Encoder Routine vom Screwdriver * '******************************************************** '******************************************************** '* ATMEGA8 * '******************************************************** ' -------------- ' (Reset) PC6 - | 1 28 | PC5 (ADC5) ' (RXD) PD0 - | 2 27 | PC4 (ADC4) ' (TXD) PD1 - | 3 26 | PC3 (ADC3) ' (INT0) PD2 - | 4 25 | PC2 (ADC2) ' (INT1) PD3 - | 5 24 | PC1 (ADC1) ' (XCK) PD4 - | 6 23 | PC0 (ADC0) ' VCC - | 7 22 | GND ' GND - | 8 21 | AREF ' (XTAL1) PB6 - | 9 20 | AVCC ' (XTAL2) PB7 - | 10 19 | PB5 (SCK) ' (T1 ) PD5 - | 11 18 | PB4 (MISO) ' (AIN0) PD6 - | 12 17 | PB3 (OC2) ' (AIN1) PD7 - | 13 16 | PB2 (OC1B) ' (ICP1) PB0 - | 14 15 | PB1 (OC1A) ' -------------- $regfile = "m8def.dat" $crystal = 16000000 $hwstack = 100 $swstack = 100 $framesize = 100 Dim Rotary0 As Byte 'Phasenzustand des Drehencoders Dim Rotary1 As Byte 'Zähler der Phasenwechsel Dim Rotary2 As Byte 'Hilfsvariable Dim Rotary As Byte 'Encoder-Wert Dim Rotary_last As Byte 'Letzter Encoder-Wert (nur für Demo) Dim Menuezaehler As Byte Dim Menuezaehler_temp As Byte Dim Sekunde As Byte Dim Minute As Byte Dim Stunde As Byte Dim A_sekunde As Byte Dim A_minute As Byte Dim A_stunde As Byte Dim S1 As String * 2 'Sekunde ' Dim S2 As String * 2 'Minute Dim S3 As String * 2 'Stunde Dim S4 As String * 2 'Alarm Sekunde Dim S5 As String * 2 'Alarm Minute Dim S6 As String * 2 'Alarm Stunde Dim X As Byte 'Blinkzähler Dim Alarmzaehler As Byte Config Lcdpin = Pin , Db7 = Portb.0 , Db6 = Portd.7 , Db5 = Portc.2 , _ Db4 = Portc.3 , E = Portc.4 , Rs = Portc.5 Config Lcd = 16 * 2 Cls Cursor Off 'System-Timer für periodische Encoder-Abfrage Config Timer0 = Timer , Prescale = 256 On Timer0 Isr_timer0 Enable Timer0 Const Timer0_reload = 224 'Timer für Uhr Config Timer1 = Timer , Prescale = 256 Enable Timer1 On Timer1 Takt Enable Interrupts Timer1 = 3036 Declare Sub Encoder2() 'Routine zur Anpassung des ENCODER-Befehls Enable Interrupts 'LED an PD0 Led Alias Portd.0 Portd.0 = 1 Config Led = Output Config Pind.1 = Input Taster Alias Pind.1 Portd.1 = 1 'Speaker an PD2 Speaker Alias Portd.2 Portd.2 = 1 Config Speaker = Output Stunde = 12 A_minute = 1 Do Led = 0 Call Encoder2() 'Wird zyklisch im Hauptprogramm aufgerufen If Rotary_last <> Rotary Then 'Encoder gedreht? Rotary_last = Rotary 'Neue Stellung merken Print Rotary 'und Encoder-Wert ausgeben End If S1 = Str(sekunde) 'Uhr Sekunde S1 = Format(s1 , "00") '---------------------------------- S2 = Str(minute) 'Uhr Minute S2 = Format(s2 , "00") '------------------------------------ S3 = Str(stunde) 'Uhr Stunde S3 = Format(s3 , "00") '-------------------------------------- S4 = Str(a_sekunde) 'Alarm Sekunde S4 = Format(s4 , "00") '---------------------------------- S5 = Str(a_minute) 'Alarm Minute S5 = Format(s5 , "00") '------------------------------------ S6 = Str(a_stunde) 'Alarm Stunde S6 = Format(s6 , "00") '-------------------------------------- Locate 1 , 1 Lcd "Uhr: " ; S3 ; ":" ; S2 ; ":" ; S1 'Stunde-Minute-Sekunden Locate 2 , 1 Lcd "M:" ; Menuezaehler ; " " ; "Al:" ; S6 ; ":" ; S5 ; ":" ; S4 'Alarm Stunde-Minute-Sekunden If Taster = 0 Then Gosub Menue End If Select Case Menuezaehler Case 1 : Gosub Alarm_stunde_stellen Case 2 : Gosub Alarm_minute_stellen Case 3 : Gosub Alarm_sekunde_stellen Case 4 : Gosub Uhr_stellen Case 5 : Gosub Minute_stellen Case 6 : Gosub Sekunde_stellen End Select If Stunde = A_stunde And Minute = A_minute And Sekunde = A_sekunde Then Alarmzaehler = 60 End If If Alarmzaehler > 0 Then Gosub Alarm End If Loop End Menue: Waitms 50 Incr Menuezaehler_temp If Menuezaehler_temp = 2 Then Menuezaehler = 1 'Uhr stellen If Menuezaehler_temp = 4 Then Menuezaehler = 2 'Stunde stellen If Menuezaehler_temp = 6 Then Menuezaehler = 3 'Sekunde stellen If Menuezaehler_temp = 8 Then Menuezaehler = 4 'Alarm Stunde stellen If Menuezaehler_temp = 10 Then Menuezaehler = 5 'Alarm Minute stellen If Menuezaehler_temp = 12 Then Menuezaehler = 6 'Alarm Sekunde stellen If Menuezaehler_temp > 14 Then Menuezaehler_temp = 0 Return Uhr_stellen: Stunde = Rotary Return Minute_stellen: Minute = Rotary Return Sekunde_stellen: Sekunde = Rotary Return Alarm_stunde_stellen: A_stunde = Rotary Return Alarm_minute_stellen: A_minute = Rotary Return Alarm_sekunde_stellen: A_sekunde = Rotary Return Alarm: Toggle Led Waitms 500 Alarmzaehler = Alarmzaehler - 1 Return Takt: Timer1 = 3036 Incr Sekunde If Sekunde = 60 Then Sekunde = 0 Minute = Minute + 1 If Minute = 60 Then Minute = 0 Stunde = Stunde + 1 If Stunde > 23 Then Stunde = 0 End If End If End If Return '******************************************************************************* '*** ISR_TIMER0 *** '*** Periodische Auswertung des Dreh-Encoders *** '******************************************************************************* Isr_timer0: Timer0 = Timer0_reload Rotary0 = Encoder(pinc.0 , Pinc.1 , Links , Rechts , 0) Return '******************************************************************************* '*** Unterprogramme *** '******************************************************************************* Rechts: 'Bei Rechtsdrehung Rotary1 = Rotary1 + 1 If Rotary > 59 Then Rotary = 0 End If 'Zählvariable Phasenwechsel erhöhen Return Links: 'Bei Linksdrehung Rotary1 = Rotary1 - 1 'Zählvariable Phasenwechsel vermindern Return '******************************************************************************* '*** Routine zur Anpassung des ENCODER-Befehls an POLLIN Drehencoder *** '******************************************************************************* Sub Encoder2() Disable Interrupts Rotary2 = Rotary1 'Zählvariable Phasenwechsel kopieren Rotary1 = Rotary1 And 1 'Ggf.Phasenwechsel zwischen Rastungen stehenlassen push r0 'BASCOM kann kein arithmetisches Rechtsschieben lds r0,{rotary2} 'Aber der AVR kanns! asr r0 'ASR= Rechtsschieben mit Berücksichtigen sts {rotary2},r0 'des Vorzeichens, also teilen durch 2 pop r0 'eines signed byte Rotary = Rotary + Rotary2 'Encoder-Wert um Anzahl Rastungen erhöhen/vermindern Enable Interrupts End Sub Return