Code:
.include "m8def.inc"
;UBRR = Taktfrequenz / 16 * Baudrate -1
.def rBin1L = R1 ;Wird gebraucht um bin -> ascii zu rechnen
.def rbin1H = R2 ;Wird gebraucht um bin -> ascii zu rechnen
.def rbin2H = R3 ;Wird gebraucht um bin -> ascii zu rechnen
.def rbin2L = R4 ;Wird gebraucht um bin -> ascii zu rechnen
.def tmp = R16 ;universalregister
.def statusreg = R17 ;Statusregister um die Interrupts zu signalisieren
.def rmp = R18 ;universalregister für die Umrechnung
.equ sramanfang = 0x0060
.equ bumper = 7 ;Bit 7 von statusreg signalisiert INT1 Interrupt
.equ CLOCK = 8000000
.equ BAUD = 2400
.equ UBRRVAL = CLOCK / (BAUD*16)-1
.org 0x000
rjmp reset
.org INT1addr
rjmp kolision ;Ext Interrupt Vector Address
reset:
;Stackpointer
ldi tmp,LOW(RAMEND)
out SPL,tmp
ldi tmp,HIGH(RAMEND)
out SPH,tmp
;sram pointer
ldi ZH,HIGH(sramanfang)
ldi ZL,LOW(sramanfang)
;Baudrate einstellen
ldi tmp,UBRRVAL
out UBRRL,tmp
;di tmp,HIGH(UBRRVAL)
;ut UBRRL,tmp
;Frameformat 8Bit
ldi tmp,(1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
out UCSRC,tmp
sbi UCSRB,TXEN ;TX aktivieren
;AD converter Init
ldi tmp,(1<< ADEN) | (1<<ADPS1) | (1<<ADPS2)
out ADCSRA,tmp
ldi tmp,(1<<REFS0) | (1<<MUX2)
out ADMUX,tmp
;Einstellen Low Level Interrupt für Tastenabfrage
ldi tmp,(1<<INT1)
out GICR,tmp
sei
loop_:
;sram pointer
ldi ZH,HIGH(sramanfang)
ldi ZL,LOW(sramanfang)
loop:
sbrs statusreg,bumper ;prüfe statusregister ob bit 7 -> bumper gesetzt ist wenn ja dann springe
rjmp loop
in tmp,GICR ;Schalte INT1 interrupt ab
andi tmp,0x7f
out GICR,tmp
ldi statusreg,0 ;lösche statusregister bumper
cli ;Interrupts allgemein ausschalten
sbi DDRD,PD3 ;schalte pin PD3 als Ausgang
sbi PORTD,PD3 ;und setze es auf HIGH
ldi R16, $85 ; 10 ms abwarten
L1: ldi R18, $C7
L2: dec R18
brne L2
dec R16
brne L1
sbi ADCSRA,ADSC ;Starte ADC
warte:
sbis ADCSRA,ADIF
rjmp warte
;fertig und lese Ergebnis ein
in rBin1L,ADCL
in rBin1H,ADCH
cbi PORTD,PD3 ;Pin PD3 wieder LOW
cbi DDRD,PD3 ;und wieder als Eingang
sei ;Interrups wieder an
rcall berechne ;Rechne Ergebnis in ascii um und schreibe
;es in sram
rcall serout ;gib das Ergebnis über UART aus
in tmp,GICR ;Schalte Interrupts auf INT1 wieder ein
ori tmp,0x80
out GICR,tmp
rjmp loop_ ;wenn fertig wieder von vorne anfangen
serout:
ldi tmp,0x00 ;Zähler für Anzahl der CHAR
serout_:
cpi tmp,0x05 ;Vergleiche Zähler mit 0x05
breq rausuart ;Wenn gleich springe
ld R0,Z ;Hole ASCII kodierte Zahl aus den SRAM
serout__:
sbis UCSRA,UDRE ;Springe wenn UDR gesetzt ist
rjmp serout__
out UDR,R0 ;schiebe R0 in UDR
adiw ZL,1 ;Z++
inc tmp ;Zähler ++
rjmp serout_
rausuart:
sbis UCSRA,UDRE ;Springe wenn UDR gesetzt ist
rjmp rausuart
ldi tmp,10 ;sende Zeilenvorschub
out UDR,tmp
rausuart_:
sbis UCSRA,UDRE
rjmp rausuart_
ldi tmp,13 ;sende Wagerücklauf
out UDR,tmp
ret
;Diese Routine stammt von Gerd Schmidt http://www.avr-asm-tutorial.net/avr_de/index.html
;Danke dafür
berechne:
rcall Bin2ToBcd5 ; wandle Binärzahl in BCD um
ldi rmp,4 ; Zähler auf 4
mov rBin2L,rmp
Bin2ToAsc5a:
ld rmp,z ; Lese eine BCD-Ziffer
tst rmp ; prüfe ob Null
brne Bin2ToAsc5b ; Nein, erste Ziffer ungleich 0 gefunden
ldi rmp,' ' ; mit Leerzeichen überschreiben
st z+,rmp ; und ablegen
dec rBin2L ; Zähler um eins senken
brne Bin2ToAsc5a ; weitere führende Leerzeichen
ld rmp,z ; Lese das letzte Zeichen
Bin2ToAsc5b:
inc rBin2L ; Ein Zeichen mehr
Bin2ToAsc5c:
subi rmp,-'0' ; Addiere ASCII-0
st z+,rmp ; und speichere ab, erhöhe Zeiger
ld rmp,z ; nächstes Zeichen lesen
dec rBin2L ; noch Zeichen behandeln?
brne Bin2ToAsc5c ; ja, weitermachen
sbiw ZL,5 ; Zeiger an Anfang
ret ; fertig
Bin2ToBcd5:
push rBin1H ; Rette Inhalt der Register rBin1H:L
push rBin1L
ldi rmp,HIGH(10000) ; Lade 10.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 5.Stelle durch Abziehen
ldi rmp,HIGH(1000) ; Lade 1.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(1000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 4.Stelle durch Abziehen
ldi rmp,HIGH(100) ; Lade 100 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(100)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 3.Stelle durch Abziehen
ldi rmp,HIGH(10) ; Lade 10 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 2.Stelle durch Abziehen
st z,rBin1L ; Rest sind Einer
sbiw ZL,4 ; Setze Zeiger Z auf 5.Stelle (erste Ziffer)
pop rBin1L ; Stelle den Originalwert wieder her
pop rBin1H
ret ; und kehre zurück
Bin2ToDigit:
clr rmp ; Zähler auf Null
Bin2ToDigita:
cp rBin1H,rBin2H ; Vergleiche MSBs miteinander
brcs Bin2ToDigitc ; MSB Binärzahl kleiner, fertig
brne Bin2ToDigitb ; MSB Binärzahl größer, subtrahiere
cp rBin1L,rBin2L ; MSB gleich, vergleiche LSBs
brcs Bin2ToDigitc ; LSB Binärzahl kleiner, fertig
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtrahiere LSB Dezimalzahl
sbc rBin1H,rBin2H ; Subtrahiere Carry und MSB
inc rmp ; Erhöhe den Zähler
rjmp Bin2ToDigita ; Weiter vergleichen/subtrahieren
Bin2ToDigitc:
st z+,rmp ; Speichere das Ergebnis und erhöhe Zeiger
ret ; zurück
kolision:
ori statusreg,0x80
reti
Schmeiß den Quatsch mit int1 raus, pass das Programm leicht an und fertig.
Lesezeichen