.include "m16def.inc" .def akku = r16 .def zaehlA = r18 .def zaehlB = r19 .def zaehl = r24 .equ anz = 8 ;Länge der Zeichenkette OVERFLOW .cseg rjmp Start .org 0x002A Start: ldi akku,LOW(RAMEND) out SPL,akku ldi akku,HIGH(RAMEND) out SPH,akku ldi akku,0x00FF ;Bitmuster 1111 1111 out DDRB,akku ;Richtung Ausgang ldi ZL,LOW(ftab*2) ;Z<-Tabellenadresse Flash befüllt ldi ZH,HIGH(ftab*2) ldi XL,LOW(stab) ldi XH,HIGH(stab) clr zaehl ;Zeichenzähler löschen clr zaehlA ;Zähler löschen clr zaehlB ;Zähler löschen rcall Posn1Zeile rcall Posn2Zeile ;LCD initialisieren ldi r20, 0b11111111 out DDRB, r20 sbi DDRC, 0 sbi DDRC, 1 sbi DDRC, 2 rcall Schleife50milis ;INITIALISIERUNG AUFRUFE ldi r17, 0x30 rcall Kommando rcall Kommando rcall Kommando ldi r17, 0x38 rcall Kommando ldi r17, 0x0D rcall Kommando ldi r17, 0x01 ;Display löschen rcall Kommando ;Definition der Pin's ;PINC 3: A ;PINC 4: B ;PINC 5: = ; Hauptprogramm Anfang LOOP: sbic PINC,PINC3 ;Überspringe wenn Taste low rjmp Taste3 ;Wartet solange high ist sbic PINC,PINC4 rjmp Taste4 ;Wartet solange high ist sbic PINC,PINC5 rjmp Taste5 ;Wartet solange high ist rjmp LOOP ;Unterprogramme Taste3: cpi zaehlA,255 ;Abfrage ob Wert erreicht breq Taste3a ;Zähler hat Endwert erreicht inc zaehlA ;um eins erhöhen Taste3a: mov akku,zaehlA ;r16<-dual rcall Posn1Zeile ;für die Ausgabe von A Taste3b: sbic PINC,PINC3 ;sprung bei low rjmp Taste3b ;warte solange Taste high rjmp LOOP Taste4: cpi zaehlB,255 ;Abfrage ob Wert erreicht breq Taste4a ;Zähler hat Endwert erreicht inc zaehlB ;um eins erhöhen Taste4a: mov akku,zaehlB ;r16<-dual rcall Posn2Zeile ;für die Ausgabe von B Taste4b: sbic PINC,PINC4 ;sprung bei low rjmp Taste4b ;warte solange Taste high rjmp LOOP Taste5: ;1) LCD Löschen, Home setzen ldi r17, 0x01 ;Display löschen rcall Kommando ;2) Ausgabe A + B= ldi zaehlA,10 mov akku,zaehlA rcall dual2bcd rcall Datum ldi r17,'+' mov akku,r17 rcall Datum mov akku,zaehlB rcall dual2bcd rcall Datum ldi r17,'=' mov akku,r17 rcall Datum ;3) Rechnen A+B und Ausgabe von A mit Ergebnis add zaehlA,zaehlB brcs fehler mov akku,zaehlA rcall dual2bcd rcall Datum rjmp Ende Fehler: Loop1: lpm ;r0<-Konstante aus Flash tst r0 ;Endemarke Null? breq lab1 ;ja:fertig cpi zaehl,anz+1 ;nein:max. Listenlänge? brsh lab1 ;ja:abbrechen st x+,r0 ;nein: nach SRAM Adrsse +1 adiw ZL,1 ;Flashadresse +1 inc zaehl ;Zähler +1 rjmp Loop1 ;Kopierschleife ;Listenlänge speichern und ablegen lab1: sts lang,zaehl ;Zeichenzähler vor Liste ablegen Loop2: ldi XL,LOW(stab) ldi XH,HIGH(stab) lds zaehl,lang clr zaehl ldi r17, 0xC5 ;0xCn = Cursor an Position 5 in 2. Zeile rcall Kommando Meldung: ld akku,X+ ;akku<-Listenelement rcall Datum ;beim 1. Durchlauf: 1.Zeichen wird ausgegeben, weil sbic wenn 0 Befehl überspringt inc zaehl tst r0 ;Endemarke Null? breq Ende rjmp Meldung ;LCD KOMPONENTEN!!! Kommando: ldi r20, 0b00000000 out PortC, r20 out PortB, r17 ldi r20, 0b00000001 ;Display löschen out PortC, r20 nop ldi r20, 0b00000000 out PortC, r20 rcall Schleife5milis ret ;Ausgabe des aktuellen Wertes Datum: ldi r20, 0b00000010 out PortC, r20 out PortB, akku ldi r20, 0b00000011 out PortC, r20 nop ldi r20, 0b00000010 out PortC, r20 rcall Schleife50mikros ret Schleife50mikros: ;Schleife 50mikrosekunden ;2000 cycles: ; ----------------------------- ; delaying 1998 cycles: ldi R21, $03 WGLOOP5: ldi R20, $DD WGLOOP6: dec R20 brne WGLOOP6 dec R21 brne WGLOOP5 ; ----------------------------- ; delaying 2 cycles: nop nop ; ============================= ret Schleife5milis: ; 20000 cycles: SIND 5millisekunden ; ----------------------------- ; delaying 19998 cycles: ldi R21, $21 WGLOOP3: ldi R20, $C9 WGLOOP4: dec R20 brne WGLOOP4 dec R21 brne WGLOOP3 ; ----------------------------- ; delaying 2 cycles: nop nop ; ============================= ret Schleife50milis: ;50milisekunden ; ----------------------------- ; delaying 199998 cycles: ldi R17, 0b00000110 WGLOOP0: ldi R20, $37 WGLOOP1: ldi R21, $C9 WGLOOP2: dec R21 brne WGLOOP2 dec R20 brne WGLOOP1 dec R17 brne WGLOOP0 ; ----------------------------- ; delaying 2 cycles: nop nop ; ============================= ret ;LCD Cursorbefehle Posn1Zeile: ldi r17, 0x80 ;0x8n = Cursor an Position 0 in 1. Zeile rcall Kommando mov akku,zaehlA rcall dual2bcd rcall Datum ret Posn2Zeile: ldi r17, 0xC0 ;0xCn = Cursor an Position 0 in 2. Zeile rcall Kommando mov akku,zaehlB rcall dual2bcd rcall Datum ret Ende: ;Konstanten hinter den Befehlen ftab: .DB "Overflow",0,0 ;Nullterminierter String ;hier externe Unterprogramme einbinden .include "dual2bcd.asm" ;Dualzahl in BCD-Codierte Dezimalzahl ;Variablen deklaration .dseg lang: .BYTE 1 ;1 Byte für Listenlänge stab: .BYTE anz ;anz Byte für Daten .EXIT