Code:
.include "m8def.inc"
.def temp = r16 ; Register für kleinere Arbeiten
.def zeichen = r17 ; in diesem Register wird das Zeichen an die
; Ausgabefunktion übergeben
.def adlow = r18 ; Register für lowbyte adc
.def adhigh = r19 ; Register für highbyte adc
.def impulsL = r20 ; Register für lowbyte timer
.def impulsH = r21 ; Register für highbyte timer
.def run = r22 ; Register für programmselektion
.equ F_CPU = 4000000 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate
; Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000) ; Fehler in Promille
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) ; max. +/-10 Promille Fehler
.error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
.org 0x000
rjmp main ; Reset Handler
.org URXCaddr ; Interruptvektor für UART-Empfang
rjmp int_rxc
; Hauptprogramm
main:
; Stackpointer initialisieren
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
out UBRRH, temp
ldi temp, LOW(UBRR_VAL)
out UBRRL, temp
; Timer Init
ldi temp, 0b00000110 ; CS10-12: Ext.Takt neg.Flanke
out TCCR1B, temp
; Frame-Format: 8 Bit
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB,TXEN ; TX aktivieren
ldi temp, (1<<URSEL)|(3<<UCSZ0)
out UCSRC, temp
sbi UCSRB, RXCIE ; Interrupt bei Empfang
sbi UCSRB, RXEN ; RX (Empfang) aktivieren
sei ; Interrupts global aktivieren
; ADC initialisieren: Single Conversion, Vorteiler 128
; Kanal 0, interne Referenzspannung AVCC
ldi temp, (1<<REFS0)
out ADMUX, temp
ldi temp, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
out ADCSRA, temp
loop:
cpi run, 0x0F ; run mit '0F' vergleichen (Send)
BREQ send ; wenn gleich, dann zu send
cpi run, 0xF0 ; run mit 'F0 vergleichen (Get
BREQ get ; wenn gleich, dann zu get
rjmp loop ; Endlosschleife
get:
sbi ADCSRA, ADSC ; den ADC starten
adc_warten:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
rjmp adc_warten
in adlow, ADCL ; LOW Byte lesen
in adhigh, ADCH ; High Byte lesen
;;HIER TIMER ROUTINE EINFÜGEN;;
send:
ldi zl,low(my_string*2); ; Z Pointer laden
ldi zh,high(my_string*2);
rjmp uart_warten
out UDR, adlow
rjmp uart_warten
out UDR, adhigh
rjmp uart_warten
out UDR, impulsL
rjmp uart_warten
out UDR, impulsH
rjmp uart_warten
serout_string:
lpm ; nächstes Byte aus dem Flash laden
and r0,r0 ; = Null?
breq serout_string_ende ; wenn ja, -> Ende
serout_string_wait:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp serout_string_wait
out UDR, r0
adiw zl:zh,1 ; Zeiger erhöhen
rjmp serout_string ; nächstes Zeichen bearbeiten
serout_string_ende:
rjmp loop ; zurück zum Hauptprogramm
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde
int_rxc:
push temp ; temp auf dem Stack sichern
in temp, sreg ; SREG sichern
push temp
in temp, UDR ; UART Daten lesen
cpi temp, 0x53 ; empfangenes Byte mit '53' (S) vergleichen
brne int_rxc_1 ; wenn nicht gleich, dann zu int_rxc_1
ldi run, 0x0F ; run auf 0F setzen (daten senden)
rjmp int_rxc_3 ; Zu int_rxc_3 springen
int_rxc_1:
cpi temp, 0x52 ; empfangenes Byte mit '52' (R) vergleichen
brne int_rxc_2 ; wenn nicht gleich, dann zu int_rxc_2
ldi run, 0xF0 ; run auf F0 setzen (daten erfassen)
rjmp int_rxc_3 ; Zu int_rxc_3 springen
int_rxc_2:
ldi run, 0x00 ; run auf 00 setzen (idle)
rjmp int_rxc_3 ; Zu int_rxc_3 springen
int_rxc_3:
pop temp
out sreg, temp
pop temp
reti
uart_warten:
sbis UCSRA,UDRE ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp uart_warten
ret
my_string: .db "Ende",10,13,0
Lesezeichen