Code:
.NOLIST ; List-Output unterdrücken
.INCLUDE <m8def.inc> ; das gibt es für jeden Controllertyp
; .include "C:\PROGRA~1\VMLAB\include\m8def.inc
.def temp = R16 ; für Interrupt
.def ZEICHEN = R17
.def merker_isr = R18 ;Merker dass im SRAM gespeicherte Zeichenkette gesendet wurde
;------------------------------------------------------
; Peripherie initialisieren
;------------------------------------------------------
.equ F_CPU = 7372800 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; Berechnen des Teilers für die Baudrate
.LIST ; List-Output wieder aufdrehen
.CSEG ; was nun folgt, gehört in den FLASH-Speicher
;------------------------------------------------------
; Start Adresse 0000 /Interruptvektoren
;------------------------------------------------------
.org 0x000 ; Interruptvektoren überspringen
rjmp Init
.org 0x00B ; UART Receive Complete Interrupt
rjmp serin
.org 0x00C ; USART Data Register Empty
rjmp serout
;------------------------------------------------------
; INITIALIZE
;------------------------------------------------------
INIT:
;Stack Pointer setzen
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp
; Frame-Format: 1 Stop-Bits, 8 Bit
ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)
out UCSRC, temp
sbi UCSRB,RXEN ; Freigabe Empfangen
sbi UCSRB,RXCIE ; Interrupt für "Zeichen empfangen"
sbi UCSRB,TXEN ; Sender aktivieren
sei ; globale Interruptfreigabe
ldi XL, LOW(input*2) ; Adresse für Ablegen des ersten Zeichens in den
ldi XH, HIGH(input*2) ; X-Pointer laden
ldi merker_isr,0 ;Initialisierung der var, wichtig für vmlab
;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:
rjmp Hauptschleife
;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------
serin: ; (ISR)
in temp, UDR ; Zeichen zwischen speichern
out UDR, temp ; Zeichen ausgeben
st x+, temp ; im SRAM speichern
cpi temp,0x0D ; prüfen ob Enter gedrückt wurde
brne no_enter ; ISR beenden wenn nicht Enter gedrückt wurde
; --- Block abarbeiten wenn Zeichenkette vollständig gesendet ---------------
ldi ZEICHEN, '>' ; dieses Zeichen als Antwort der ISR ausgeben
out UDR, ZEICHEN
sbi UCSRB,UDRIE ; Interrupt für "Sendepuffer leer" freigeben
ldi ZL, LOW(Daten*2) ; Z-Pointer zurücksetzen
ldi ZH, HIGH(Daten*2)
ldi XL, LOW(input*2) ; X-Pointer zurücksetzen
ldi XH, HIGH(input*2)
no_enter: reti ; Sobald Enter gedrückt wurde, wird beim Verlassen der ISR 'serin' sofort in die ISR 'serout' gewechselt, (UDRE=1)
; weil Interrupt (UDRIE) freigegeben wird
serout: ; (ISR)
cpi merker_isr,1 ; wenn Zeichenkette aus Programmspeicher gesendet, dann springen zum nächsten Block
breq string1_ready
; --------- diesen Teil abarbeiten, wenn String im Programmspeicher noch nicht gesendet wurde ----------
lpm ; nächstes Byte des Strings nach R0 lesen (Z-Pointer)
mov ZEICHEN,R0
adiw ZL,1 ; Adresse des Z-Pointers um 1 erhöhen
tst R0 ; Inhalt von R0 auf Null testen
brbc 1,sprung_a ; nächten Befehl ausführen wenn kompletter String gesendet
ldi merker_isr,1
sprung_a:
out UDR, ZEICHEN ; Zeichen auf UART ausgeben
rjmp sprung_b ; springe zum Ende, da Zeichenkette noch nicht fertig gesendet
; ---------- hier weitermachen wenn String im Programmspeicher gesendet wurde ----------------------
string1_ready:
ld ZEICHEN,X+
out UDR, ZEICHEN ; Zeichen auf UART ausgeben
cpi ZEICHEN,0x0D ; wurde Ende des Strings erreicht? (Enter im Speicher)
brne sprung_b ; ja --> beim nächsten Befehlsblock weitermachen; nein --> ISR verlassen für nächstes Zeichen
; ---------- wenn String gesendet, diesen Teil abarbeiten ------------------------------------------------------
wait1:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste Byte bereit ist
rjmp wait1
ldi temp,0x0a ; Line Feed
out UDR,temp
wait2:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste Byte bereit ist ;
rjmp wait2
ldi temp,0x0d ; Zeilenumbruch
out UDR,temp
cbi UCSRB,UDRIE ; Interrupt für "Sendepuffer leer" sprerren
ldi XL, LOW(input*2) ; Adresse für Ablegen des ersten Zeichens in den
ldi XH, HIGH(input*2) ; X-Pointer zurücksetzen
ldi merker_isr,0 ; Merker zurücksetzen
sprung_b: reti
;------------------------------------------------------
; Datenbereich
;------------------------------------------------------
Daten: .db "du hast folgende Zeichen eingegeben:",0,0
.DSEG
input: .Byte 20 ; 20 Byte unter den Namen 'input' reservieren
Lesezeichen