Gast
#1637131
hallo, ich bin gerade bei dieser AVR - Tutorial: UART Übung, und habe dazu eine Frage wo kann ich sehen was ich gesendet habe? zb test!
|
Anzeige
|
uart mit atmega88
Gast
#1637131
hallo, ich bin gerade bei dieser AVR - Tutorial: UART Übung, und habe dazu eine Frage wo kann ich sehen was ich gesendet habe? zb test!
Gast
#1637150
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. Ich würds mal mit dem PC probieren, an den ich den µC per Kabel angeschlossen habe (achja, laufendes Terminalprogramm vorausgesetzt, zB hterm oä) vg
Gast
#1637189
danke,
ich habe das Beispiel getestet:
.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 = 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
; Stackpointer initialisieren
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, 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, (0<<USBS0)|(3<<UCSZ00)
sts UCSR0C, temp
ldi temp, 1<<TXEN0
sts UCSR0B,temp
; sbi UCSR0B,TXEN0 ; TX aktivieren
; sts UCSR0B,Zeichen
lds temp, UCSR0B ; TX aktivieren
sbr temp, (0<<RXCIE0)
sbr temp, (1<<RXEN0)
sbr temp, (1<<TXEN0)
sts UCSR0B, temp
loop:
ldi zeichen, 'T'
rcall serout ; Unterprogramm aufrufen
ldi zeichen, 'e'
rcall serout ; Unterprogramm aufrufen
ldi zeichen, 's'
rcall serout ; ...
ldi zeichen, 't'
rcall serout
ldi zeichen, '!'
rcall serout
ldi zeichen, 10
rcall serout
ldi zeichen, 13
rcall serout
rcall sync
rjmp loop
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
; kleine Pause zum Synchronisieren des Empfängers, falls
zwischenzeitlich
; das Kabel getrennt wurde
sync:
ldi r16,0
sync_1:
ldi r17,0
sync_loop:
dec r17
brne sync_loop
dec r16
brne sync_1
ret
und wenn ich Hterminal gehe und auf CAPTURE text starten macht er
nicht. wo kann ich das Word Test! sehen. das Programm lass sich
combiliern ohne Fehler.
danke
VGZ
Gast
#1637192
ich meine das Programm lass sich compilen
Gast
#1637262
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.
MfG Spess
Gast
#1637457
super vielen danke es hat funktioniert, weiß du vielleich die leertaste in ASCII code. danke 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
Gast
#1638327
ich schreibe statt test!, hallo world! und will leertaste dazwischen. danke
Gast
#1638338
schön guten morgen erstmal, ich habe das bekommen : Hallo;World und keine leertaste mit diesem Befehl: ldi zeichen, '' rcall serout 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.
Gast
#1638368
>ldi zeichen, ' '
Du mußt zwischen den ' natürlich ein Leerzeichen reinsetzen.
Gast
#1638403
gut, danke
Gast
#1638440
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."
Gast
#1638683
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
Gast
#1638695
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
Gast
#1638779
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.
Gast
#1638811
Hi
>meinst du so vielleich:
Ja.
Warum benutzt du nicht gleich deine 'serout'-Routine? Dann reduziert
sich deine Stringausgabe auf:
MfG Spess
Gast
#1638815
hi ,
sorry ich meinte so:
serout_string_wait: push temp
serout_string_wait10: lds temp,UCSR0A
sbrs temp,UDRE0
rjmp serout_string_wait10
sts UDR0 , r0
adiw zl:zh,1
pop temp
rjmp serout_string
serout_string_ende:
ret
Gast
#1638818
vergiss meine letzte Atwort, die habe ich geschickt bevor ich deine Anwort gelesen habe. danke
Gast
#1638948
jetzt habe ich das Programm so geschrieben:
.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
; 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 ; 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, UCSR0A ; Warten bis UDR für das nächste
; Byte bereit ist
sbrs temp,UDRE0
sts UDR0, r0
adiw zl:zh,1 ; Zeiger erhöhen
rjmp serout_string_wait ; nächstes Zeichen bearbeiten
rjmp serout_string
serout_string_ende:
ret ; zurück zum Hauptprogramm
my_string: .db "Hallo World!",10,13,0
Ts, ts. Unbelehrbar Kommt dir das hier
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?
Gast
#1638984
sorry ich habe deine Antwort nicht gelesen, ich habe jetzt wie du gemeint hast und es funktionniert supper.............. vielen dank MFG A.Z 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 hallo noury, ich habe auch das gleiche Problem und ich weiß nicht was ich machen soll!!!!!!!!!!!! ---vg sahra 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. Seit wann, werden denn Einzelbits so
auf 1 gesetzt? Weiters. Was wird wohl passieren, wenn du an UCSR0B hintereinander 2 verschiedene Werte zuweist?
Gast
#1644664
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:
MfG Spess Karl heinz Buchegger schrieb: > Seit wann, werden denn Einzelbits so >
> 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. Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|