hallo!
bin noch anfänger in sachen assembler. habe ein beispiel prog fürs übertragen über RS232 gefunden.
hier:
Code:
.NOLIST
.INCLUDE "D:\m32def.inc"
.LIST
.equ fck = 4000000
.equ baudrate = 4800
.equ baudconst = (fck / (baudrate * 16)) - 1
.def w = R19 ; Arbeitsregister
.def wi = R20 ; Interrupt-Arbeitsregister
.def rs_buf = R21 ; Buffer für empfangenes Byte
.def a_flag = R25 ; Flagregister
.equ rs_recv = 0 ; 1 = Byte empfangen - 0 = kein Byte empfangen
; Interrupt-Adressen
.cseg
.org $0000
rjmp main
.org $0007 ; RS232 Empfangsinterrupt
rjmp rs232_recv ; RS232 Behandlungsroutinge wenn etwas empfangen wird
; I/O-Port Initialisierung:
hdw_init:
ldi w, 0b11111111
out PORTD, w ; alle Pins am Port D auf 1 setzen
ldi w, 0b11111110
out DDRD, w ; Datenrichtung am Port D festlegen: 1 = Ausgang; 0 = Eingang
; Pin 1 am Port D Empfangen (= 1) RX
; Pin 2 am Port D Senden (= 0) TX
ldi w, 0b11111111
out PORTB, w
ldi w, 0b11111111
out DDRB, w
; UART Initialisierung:
uart_init:
ldi w, baudconst
out UBRRL, w ; UBRR = USART Baud Rate Register
ldi w, 0
out UBRRH, w
ldi w, 0b00011000
out UCSRB, w ; RXEN und TXEN setzen
sbi UCSRB, RXCIE ; RS232 Interrupt freigeben
; PWM Initialisierung:
pwm_init:
ldi w, 0b10000001
out TCCR1A, w
ldi w, 0
out OCR1AH, w
ldi w, 1
out OCR1AL, w
ldi w, 0b00000001
out TCCR1B, w
sei ; gibt alle Interrups frei
ret
; Behandlung für empfangene Bytes:
rs_rec_up:
cbr a_flag, 1 << rs_recv; durch '1<<' wird eine '1' n-mal nach links geschoben
; für rs_recv = 0: 0b00000001
; für rs_recv = 1: 0b00000010
; --> das erste bzw zweite Bit in a_flag wird somit gelöscht
mov w, rs_buf ; empfangenes Byte in w
out PORTB, w ; an Port B ausgeben ?(kein PWM)?
out OCR1AL, w
rcall rs_send
ret
rs_send:
sbis UCSRA, UDRE ; überprüft, ob UDRE im Register UCSRA gesetzt ist, wenn ja (UDRE=1) überspringen
; UDRE = 1 Sender frei, UDRE = 0 Sender besetzt
rjmp rs_send
out UDR, w
ret
; Interruptroutine wenn Bytes empfangen werden:
rs232_recv:
in wi, SREG ; CPU-Status
push wi ; wi in Stackpointer
in wi, UDR ; Byte vom Empfänger laden
mov rs_buf, wi ; zwischenspeichern
sbr a_flag, 1<<rs_recv ; durch '1<<' wird eine '1' n-mal nach links geschoben
; für rs_recv = 0: 0b00000001
; für rs_recv = 1: 0b00000010
; --> das erste bzw zweite Bit in a_flag wird somit gesetzt
pop wi ; Stackpointer zurück in wi
out SREG, wi ; zurück zur CPU
reti ; Return from Interrupt
main:
ldi w, RAMEND ; RAMEND: Speicherende des Chips
out SPL, w ; in Stackpointer schreiben
clr a_flag
rcall hdw_init ; Hardware Initialisierung
endlos:
sbrc a_flag, rs_recv
rcall rs_rec_up ; wenn was empfangen wurde dann...
rjmp endlos ; sonst warten
die komentare sind von mir. können also auch falsch sein
geht man das prog schritt für schritt durch, springt er hier 'rcall hdw_init' in den initialisierungsteil. am ende von 'pwm_init:' steht ein 'ret'. an dieser stelle springt er aber dann nicht zurück zum 'rcall hdw_init' bzw in die endlosschleife, sondern springt ganz an den anfang zu: '.org $0000 rjmp main'
woran liegt das?
wird in 'main:' der stackpointer falsch beschrieben? was genau bedeutet denn RAMEND?
danke mal für eure geduld wenn ihr bis zum schluss gelesen habt! \/
freddy0815
Lesezeichen