.include "4433def.inc" ;***************************************************** ;Macro zum einstellen der Cursorposition .MACRO locate push temp1 ldi temp1, 0b10000000|(((@0)-1)<<6)|((@1)-1) rcall lcd_command pop temp1 .ENDMACRO ;***************************************************** .equ clk = 0 .equ reset = 5 .equ data = 6 .def rtc_reg = r16 .def rtc_reg1 = r17 .def rtc_reg2 = r18 .def command = r19 .def zeit = r20 .def rtc_std = r21 .def rtc_min = r22 .def rtc_sek = r23 . .def sek_e = r24 .def sek_z = r25 .def min_e = r26 .def min_z = r27 .def std_e = r28 .def std_z = r29 .def temp1 = r30 .def temp2 = r31 ;------------------------- ;***** Program Start ***** ;------------------------- ;############################################################# ldi temp1, RAMEND ;Stackpointer initialisieren out SPL, temp1 ldi temp1, 0xFF ;Port C = Ausgang out DDRC, temp1 rcall lcd_init ;Display initialisieren rcall lcd_clear ;Display löschen rcall rtc_main1 ;RTC Initialisieren ;--- locate 1,1 ;Cursor auf seile1, spalte1 stellen ldi temp1, 'Z' rcall lcd_data ldi temp1, 'e' rcall lcd_data ldi temp1, 'i' rcall lcd_data ldi temp1, 't' rcall lcd_data ldi temp1, ':' rcall lcd_data ;############################################################# ;*** Loop (Zeit --> LCD) *** ;--------------------------- t_loop: rcall rtc_main2 rcall rtc_auswertung rcall lcd_write rjmp t_loop ;--------------------------- lcd_write: locate 1,7 ;Cursor auf zeile1, spalte7 stellen mov temp1, rtc_sek ;Sekunden auf dem LCD ausgeben rcall lcd_data ret ;Zurück ;--------------------------- ;############################################################# ;---------------------- ;*** RTC - Routinen *** ;---------------------- rtc_start: nop ; 1us pause nop nop nop sbi portd, reset ; Reset Line high nop ;1 us Pause nop nop nop ret rtc_stop: sbi portd, clk nop nop nop nop cbi portd, reset nop nop nop nop ret rtc_read_bit: cbi portd, clk nop sbis pind, data cbr rtc_reg1,1<<7 sbic pind, data sbr rtc_reg1,1<<7 sbi portd, clk ret rtc_write: cbi portd, clk nop sbi portd, Data sbrs command, 0 cbi portd, data nop sbi portd, clk nop ret rtc_write_byte_init: ldi rtc_reg, 8 sbi ddrd, data rtc_write_byte: rcall rtc_write lsr command dec rtc_reg brne rtc_write_byte ret rtc_read_byte_init: ldi rtc_reg,8 ldi rtc_reg1, 0x00 cbi portd, data cbi ddrd, data rtc_read_byte: rcall rtc_read_bit lsr rtc_reg1 dec rtc_reg brne rtc_read_byte ret rtc_main1: cbi portd, reset cbi portd, clk rcall rtc_start ldi command, 0x8E ;Write Protect Bit in Register- rcall rtc_write_byte_init ;Control löschen ldi command, 0x00 rcall rtc_write_byte_init rcall rtc_stop rcall rtc_start ldi command, 0xBE ;Schreib-Burst-Modus aktivieren rcall rtc_write_byte_init ldi command, 0x00 ;Sekunden = 00 rcall rtc_write_byte_init ldi command, 0x00 rcall rtc_write_byte_init ;Minuten = 00 ldi command, 0x05 rcall rtc_write_byte_init ;Stunden = z.B 5 rcall rtc_stop ret rtc_main2: cbi portd, reset cbi portd, clk rcall rtc_start ldi command, 0xBF ;Lese-Burst-Modus aktivieren rcall rtc_write_byte_init rcall rtc_read_byte_init ;Sekunden einlesen mov rtc_sek, rtc_reg1 rcall rtc_read_byte_init ;Minuten einlesen mov rtc_min, rtc_reg1 rcall rtc_read_byte_init ;Stunden einlesen mov rtc_std, rtc_reg1 rcall rtc_stop ret rtc_auswertung: ldi zeit, 0x0F mov rtc_reg2, rtc_sek and rtc_sek,zeit sbr rtc_sek,3<<4 mov sek_e, rtc_sek swap rtc_reg2 sbr rtc_reg,3<<4 mov sek_z, rtc_reg2 mov rtc_reg2, rtc_min and rtc_min, zeit sbr rtc_min, 3<<4 mov min_e, rtc_min swap rtc_reg2 sbr rtc_reg2,3<<4 mov min_z, rtc_reg2 mov rtc_reg2, rtc_std and rtc_std, zeit sbr rtc_std, 3<<4 mov std_e, rtc_std swap rtc_reg2 sbr rtc_reg2, 3<<4 mov std_z, rtc_reg2 ret ;---------------------- ;*** LCD - Routinen *** ;---------------------- ;sendet ein Datenbyte an das LCD lcd_data: mov temp2, temp1 ;"Sicherungskopie" für ;die Übertragung des 2.Nibbles swap temp1 ;Vertauschen andi temp1, 0b00001111 ;oberes Nibble auf Null setzen sbr temp1, 1<<4 ;entspricht 0b00010000 out PORTC, temp1 ;ausgeben rcall lcd_enable ;Enable-Routine aufrufen ;2. Nibble, kein swap da es schon ;an der richtigen stelle ist andi temp2, 0b00001111 ;obere Hälfte auf Null setzen sbr temp2, 1<<4 ;entspricht 0b00010000 out PORTC, temp2 ;ausgeben rcall lcd_enable ;Enable-Routine aufrufen rcall delay50us ;Delay-Routine aufrufen ret ;zurück zum Hauptprogramm ;sendet einen Befehl an das LCD lcd_command: ;wie lcd_data, nur ohne RS zu setzen mov temp2, temp1 swap temp1 andi temp1, 0b00001111 out PORTC, temp1 rcall lcd_enable andi temp2, 0b00001111 out PORTC, temp2 rcall lcd_enable rcall delay50us ret ;erzeugt den Enable-Puls lcd_enable: sbi PORTC, 5 ;Enable high nop ;3 Taktzyklen warten nop nop cbi PORTC, 5 ;Enable wieder low ret ;Und wieder zurück ;Pause nach jeder Übertragung delay50us: ;50us Pause ldi temp1, $42 delay50us_:dec temp1 brne delay50us_ ret ;wieder zurück ;Längere Pause für manche Befehle delay5ms: ;5ms Pause ldi temp1, $21 WGLOOP0: ldi temp2, $C9 WGLOOP1: dec temp2 brne WGLOOP1 dec temp1 brne WGLOOP0 ret ;wieder zurück ;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden lcd_init: ldi zeit,50 ;register zeit weil sonst keins mehr frei war powerupwait: rcall delay5ms dec zeit ;register zeit um 1 bit erleichtern brne powerupwait ldi zeit, 0x00 ;register zeit wieder auf 0 setzen ldi temp1, 0b00000011 ;muss 3mal hintereinander gesendet out PORTC, temp1 ;werden zur Initialisierung rcall lcd_enable ;1 rcall delay5ms rcall lcd_enable ;2 rcall delay5ms rcall lcd_enable ;und 3! rcall delay5ms ldi temp1, 0b00000010 ;4bit-Modus einstellen out PORTC, temp1 rcall lcd_enable rcall delay5ms ldi temp1, 0b00101000 ;noch was einstellen... rcall lcd_command ldi temp1, 0b00001100 ;...nochwas... rcall lcd_command ldi temp1, 0b00000100 ;endlich fertig rcall lcd_command ret ;Sendet den Befehl zur Löschung des Displays lcd_clear: ldi temp1, 0b00000001 ;Display löschen rcall lcd_command rcall delay5ms ret