PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : über seriell empfangene Zeichen im Speicher ablegen?



pacer_one
30.01.2008, 22:40
Hallo,

da es inzwischen mit dem Senden und Empfangen klappt, würde ich mein Programm gern ein bisschenaussbauen und die empfangenen Zeichen speichern.
Ich nehme an, dass sich hierfür der SRAM am besten eignet. Doch wie bekomme ich die Zeichen da rein? Vielleicht hat ja jemand ein paar Codeschnipsel für mich.

Später soll dan sowas rauskommen wie: "Sie haben folgenden Text eingegeben: Assembler macht Spass"

Grüße, JK

Biometriker
31.01.2008, 00:41
Wie sieht dein momentaner Code aus?

pacer_one
31.01.2008, 09:13
das isser:


.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


;------------------------------------------------------
; 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


;------------------------------------------------------
; HAUPTSCHLEIFE
;------------------------------------------------------
Hauptschleife:


rjmp Hauptschleife


;------------------------------------------------------
; Subroutinen / ISRs
;------------------------------------------------------

;Auslesen der Zeichen und bereitstellen in ZEICHEN
;Erhöhen des Z-Pointers; bei leerem Zeichen --> Zurücksetzen des Z-Pointers

serout: ; (ISR)
lpm ; Erstes Byte des Strings nach R0 lesen

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
cbi UCSRB,UDRIE ; Interrupt für "Puffer leer"

sprung_a:
out UDR, ZEICHEN ; Zeichen auf UART ausgeben
reti


serin: ; (ISR)
in temp, UDR ; Zeichen auslesen
st x+, temp ; im SRAM speichern

cpi temp,0x8D ; prüfen ob Enter gedrückt wurde
brne no_enter ; ISR beenden wenn nicht Enter gedrückt wurde

ldi ZEICHEN, '>' ; diese Zeichen als Antwort der ISR ausgeben
out UDR, ZEICHEN

sbi UCSRB,UDRIE ; Interrupt für "Puffer leer" freigeben
ldi ZL, LOW(Daten*2) ; Adresse des ersten Strings in den
ldi ZH, HIGH(Daten*2) ; Z-Pointer laden

no_enter:
reti ; Beim Verlassen wird sofort in die ISR für Senden gewechselt, UDRE=1
; und der Interrupt freigegeben ist


;------------------------------------------------------
; Datenbereich
;------------------------------------------------------
Daten:
.db "du hast folgendes Zeichen eingegeben: " ,10,13,0


.DSEG
input: .Byte 20 ; 20 Byte unter den Namen 'input' reservieren

soweit funktioniert das Programm ja, allerdings weiß ich nicht, ob die Zeichen korrekt im RAM abgelegt werden. Deshalb würde mich noch interessieren wie ich den Inhalt des RAM-Speichers interpretieren soll. Ich simuliere mit VMLab.

pacer_one
03.02.2008, 08:53
inzwischen läuft es...

.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