Es gibt zwei Möglichkeiten.
1. Es geht Dir um die Zeichen, die vom PC an den uC gesendet werden.
a) Sende das empfangene einfach zurück.
b) Lasse eine LED beim empfang eines bestimmten Zeichens bzw. einer
Zeichenkette an- oder ausgehen oder blinken.
c) Dein uC hat ein Display: zeige die empfangenen Zeichen auf dem
Display an.
2. Es geht Dir um die Zeichen, die vom uC an den PC gesendet werden.
a) Das ist einfacher. Starte ein Terminalprog und starte eine Aussendung
am uC.
Du kannst auch einfach nur das Kabel testen. Dann verbinde am anderen
Ende RX und TX (ich gehe davon aus, dass Du RTS, CTS nicht verwendest).
Danach musst Du auf dem PC die von dort gesendeten Zeichen sehen.
Denke in jedem Fall das Terminalprogramm es auf die richtige Datenrate
und sonstigen Parameter (Parity, Anzahl Datenbits, Anzahl Stopbits) zu
stellem.
Hi
>serout:> ldi temp, 1<<UDRE0> sts UCSR0A, temp ; Warten bis UDR für das nächste> ; Byte bereit ist> rjmp serout> sts UDR0, zeichen> ret ; zurück zum Hauptprogramm
Das ist falsch.
noury schrieb:
> super vielen danke es hat funktioniert, weiß du vielleich die leertaste> in ASCII code.
Googelst du nach "ASCII Tabelle"
Da findest du dann die Codes aller Zeichen.
Aber wozu brauchst du die eigentlich?
ldi zeichen, ' '
call serout
und raus geht ein Leerzeichen
noury schrieb:
> schön guten morgen erstmal,> ich habe das bekommen :> Hallo;World> und keine leertaste> mit diesem Befehl:> ldi zeichen, ''
Schau noch mal genau. Zwischen den ' szeht das Zeichen, dass du senden
willst.
ldi zeichen, 'a'
lädt den ASCII Code für a ins Register 'zeichen'
ldi zeichen, '?'
lädt den ASCII Code für ? ins Register 'zeichen'
und natürlich lädt
ldi zeichen, ' '
den ASCII Code vom Leerzeichen ins Register 'zeichen'.
Ein Leerzeichen ist auch nur ein Zeichen, so wie a, b, c, d, e, f, ...,
0, 1, 2, ... 9, 0, /, ( und was es sonst noch so gibt.
hallo nochmal
; Frame-Format: 8 Bit
ldi temp, (1<<USBS0)|(3<<UCSZ0)
out UCSR0C, temp
muss hier nich USBS0 auf 0 setzen wenn der Stoppbits auf 1 ist?
zweite Frage wenn ich den Register UCSR0B bitweise programmiere
( sbi UCSR0B,TXEN0) dann zeigt er mir einen Fehler:
error: Operand 1 out of range: 0xc1
und wenn ich so schreibe:
ldi temp, 1<<TXEN0
sts UCSR0B,temp
dann funktionniert...
GZ
Ist normal. Bei manchen AVRs liegen bestimmte Spezialregister wie hier
UCSR0B in einem Adressbereich, der mit OUT (oder IN) nicht erreichbar
ist. Dann hilft STS (LDS). "Bei Risiken und Nebenwirkungen fressen sie
das Datenblatt."
Mahlzeit,
ich habe das Programm mit zeichen senden jetzt verstanden, jetzt
versuche ich ein String zu senden: kann mir bitte jemanden zeigen wo der
Fehler in diesem Programm ist:
.include "m88def.inc"
.def temp = r16 ; Register für kleinere
Arbeiten
.def zeichen = r17 ; in diesem Register
wird das Zeichen an die
; Ausgabefunktion
übergeben
.equ F_CPU = 3686400 ; 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
; hier geht unser Programm los
; Stackpointer initialisieren
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp, LOW(RAMEND)
out SPL, temp
; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
sts UBRR0H, temp
ldi temp, LOW(UBRR_VAL)
sts UBRR0L, temp
; Frame-Format: 8 Bit
ldi temp, (1<<USBS0) | (3<<UCSZ00)
sts UCSR0C, temp
ldi temp, 1<<TXEN0
sts UCSR0B,temp
ldi temp, 1<<TXEN0 ; TX aktivieren
sts UCSR0B, temp
loop:
ldi zl,low(my_string*2); ; Z Pointer laden
ldi zh,high(my_string*2);
rcall serout_string
rjmp loop
; Ausgabe eines Strings aus dem Flash
serout_string:
lpm ; nächstes Byte aus dem Flash laden
and r0,r0 ; = Null?
breq serout_string_ende ; wenn ja, -> Ende
serout_string_wait:
ldi temp, 1<<UDRE0
sts UCSR0A, temp ; Warten bis UDR für das nächste
; Byte bereit ist
rjmp serout_string_wait
sts UDR0, r0
adiw zl:zh,1 ; Zeiger erhöhen
rjmp serout_string ; nächstes Zeichen bearbeiten
serout_string_ende:
ret ; zurück zum Hauptprogramm
; Hier wird jetzt der String definiert und im Flash gespeichert
my_string: .db "Test!",10,13,0
Danke
Hi
>kann mir bitte jemanden zeigen wo der Fehler in diesem Programm ist:
Hier:
>serout_string_wait:> ldi temp, 1<<UDRE0> sts UCSR0A, temp ; Warten bis UDR für das nächste> ; Byte bereit ist> rjmp serout_string_wait
Mache es doch so, wie ich es dir am 16.03.2010 15:04 geschrieben habe.
MfG Spess
hi,
meinst du so vielleich:
serout_string_wait: push temp
serout_string_wait10: lds temp,UCSR0A
sbrs temp,UDRE0
rjmp serout_string_wait10
sts UDR0,zeichen
pop temp
ret
noury schrieb:
> hi,> meinst du so vielleich:
Genau so hat spess53 das gepostet
Das ist ein Unterprogram, welches 1 Zeichen ausgeben kann. In deinem
Unterprogram zum Ausgeben eines Strings lädst du das jeweils nächste
Zeichen ins Register 'zeichen' und rufst genau dieses Unterprogram zur
Ausgabe dieses Zeichens auf.
So baut man das auf. Komplexere Funktionen, wie die Ausgabe eines
Strings, greifen auf einfachere Funktionen (die Ausgabe eines Zeichens)
zurück, um diese die eigentliche Arbeit tun zu lassen.
1
;
2
; einen String ausgeben
3
; Der Z-Pointer muss auf den Anfang des Strings zeigen
4
; Es werden so lange Bytes ausgegeben, bis ein 0 Byte angetroffen wird
nicht auch ein wenig seltsam vor? Gibt es eigentlich irgendeine
Möglichkeit, wann der 2te rjmp je ausgeführt werden kann?
Warum machst du denn nicht die Aufteilung in 'Zeichen senden' und
'String senden', wie es dir jetzt schon 2 Leute vorgeschlagen haben?
Schön guten Morgen alle zusammen,
ich übe immer noch mit diesem AVR-Tutorial, und bin gerade bei "
Empfangen von Zeichen per Interrupt " ich habe das Beispiel wenn es
schrieben ist koppiert und bischen nach meinem µc angepasst:
.include "m88def.inc"
.def temp = R16
.equ F_CPU = 3686400 ; 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 0x00
rjmp main
.org URXCaddr ; Interruptvektor für
UART-Empfang
rjmp int_rxc
; Hauptprogramm
main:
; Stackpointer initialisieren
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp, LOW(RAMEND)
out SPL, temp
; Port D = Ausgang
ldi temp, 0xFF
out DDRD, temp
; Baudrate einstellen
ldi temp, HIGH(UBRR_VAL)
sts UBRR0H, temp
ldi temp, LOW(UBRR_VAL)
sts UBRR0L, temp
; Frame-Format: 8 Bit
ldi temp, (1<<USBS0)|(3<<UCSZ00)
sts UCSR0C, temp
ldi temp,RXCIE0 ; Interrupt bei Empfang
sts UCSR0B ,temp
ldi temp,RXEN0 ; RX (Empfang) aktivieren
sts UCSR0B, temp
sei ; Interrupts global
aktivieren
loop:
rjmp loop ; Endlosschleife
; Interruptroutine: wird ausgeführt sobald ein Byte über das UART
empfangen wurde
int_rxc:
push temp ; temp auf dem Stack sichern
lds temp, UCSR0A
sbrs temp, UDRE0
sts UDR0, temp
; empfangenes Byte lesen,
; dadurch wird auch der
Interrupt gelöscht
out PORTD, temp ; Daten ausgeben
pop temp ; temp wiederherstellen
reti ; Interrupt beenden
aber das Programm läuft nicht weiter der bleibt bei dem Label Loop:
hängen und geht nicht weiter wenn man das Programm Schritt per Schritt
assembliert.
danke für eure Hilfe.
MFG Noury
1/ Wenn man seine Änderungen kennzeichnet, ist es wesentlich einfacher
für andere die Auswirkungen zu beurteilen.
> aber das Programm läuft nicht weiter der bleibt bei dem Label Loop:> hängen und geht nicht weiter wenn man das Programm Schritt per Schritt> assembliert.
Das Programm bleibt nicht hängen. Es führt genau die Aktion durch:
Springe zu loop. Und wieder. Und wieder... Das ist so programmiert und
so in Ordnung.
2/ Bis ein eintreffendes Zeichen den Interrupt auslöst und in die ISR
verzweigt wird.
Voraussetzung: Der Interrupt ist richtig initialisiert und das Ereignis
von außen tritt ein.
Bei der Kontrolle der Initialisierung würde 1/ helfen und bei 2/ muss
man im Simulator/Debugger das Ereignis simulieren z.B. durch Anklicken
des entsprechenden Interruptflags in der Registerdarstellung des
simulierten Prozessors.
Hi
>aber das Programm läuft nicht weiter der bleibt bei dem Label Loop:>hängen
Deswegen steht auch 'Endlosschleife' dahinter
> lds temp, UCSR0A> sbrs temp, UDRE0
beides nicht notwendig
> sts UDR0, temp ; empfangenes Byte lesen,
du willst das Register doch Lesen und nicht schreiben
> ; dadurch wird auch der Interrupt gelöscht
Nein.
> out PORTD, temp ; Daten ausgeben> pop temp ; temp wiederherstellen> reti ; Interrupt beenden
Teste mal das:
Karl heinz Buchegger schrieb:
> Seit wann, werden denn Einzelbits so>
1
> ldi temp,RXCIE0 ; Interrupt bei Empfang
2
> sts UCSR0B ,temp
3
> ldi temp,RXEN0 ; RX (Empfang) aktivieren
4
> sts UCSR0B, temp
5
>
> auf 1 gesetzt?>> Weiters. Was wird wohl passieren, wenn du an UCSR0B hintereinander 2> verschiedene Werte zuweist?
ich meine so..
ldi temp,(1<<RXCIE0 ) | (1<<RXEN0)
sts UCSR0B ,temp
ich habe nicht drauf gepasst.
danke
ich will eigentlich ein Programm schreiben das es so macht:
wenn ich in dem HyTer ein Zeichen oder ein Zahl gebe soll mir das
gleiche incrementieren: das heisst wenn ich schreibe a soll mir b geben
und so weiter....
Abdou Zahim schrieb:
> ich meine so..> ldi temp,(1<<RXCIE0 ) | (1<<RXEN0)> sts UCSR0B ,temp> ich habe nicht drauf gepasst.
:-)
> aber das Programm läuft nicht weiter der bleibt bei dem Label> Loop: hängen und geht nicht weiter wenn man das Programm Schritt> per Schritt assembliert.
Dann hast du hoffentlich etwas daraus gelernt.
* Jede Kleinigkeit ist wichtig
* bei Hardware-Einheiten im AVR kann auch ein Blick im Simulator, ob
auch wirklich die richtigen Bits gesetzt sind, so manches Problem
offenbaren.