ein Byte senden aber wie?!

Gast #228484
Lesenswert?

Hallo!

Ich möchte ein Byte von einem AT90S2313 zu einem ATMEGA8535 schicken.
Es gelingt mir aber leider nicht. Ich bin mir sehr sicher dass die
Hardware korrekt verdrahtet ist. Ich möchte das Byte vom 8535 zum 2313
schicken und habe deshalb TxD vom 8535 mit RxD vom 2313 verbunden.
Wenn das stimmt glaub ich ist die initialisierug des Uart bzw Usart
falsch.
Ich würde gerne 8-bit Frames verwenden.
Wäre echt nett wenn sich mal jemand meine init methoden ankuken
könnte.
Ich stell sie hier mal rein.

AT90S2313:
-------------------------------------------
.equ CLOCK = 10000000   ;10 Mhz
.equ BAUD = 4882        ; UBRR  ca. 128
.equ UBRRVAL = CLOCK/(BAUD*16)-1  ; ==> Baudrate 4882,87

.def temp  = r21
.def RData = r22


;**********************************************************
;***  Methode die das  UART zum empfangen initialisiert ***
;***  und die Baudrate einstellt                        ***
;**********************************************************





init_UART:
 push temp


        ldi temp, UBRRVAL     ; Baudrate einstellen
        out UBRR, temp

        sbi UCR, RXEN         ; RX (Empfang) aktivieren

  pop temp
ret
-------------------------------------------


Jetzt der Code auf dem 8535:

----------------------------

;.equ CLOCK = 16000000   ;16 Mhz
;.equ BAUD = 4882        ; UBRR  ca. 203
;.equ UBRRVAL = CLOCK/(BAUD*16)-1  ; ==> Baudrate 4882,87


.equ CLOCK = 10000000   ;10 Mhz
.equ BAUD = 4882        ; UBRR  ca. 128
.equ UBRRVAL = CLOCK/(BAUD*16)-1  ; ==> Baudrate 4882,87



;*********************************************************************** 
**************
;*** Diese Methode Initialisert das Uart zum Senden mit einer Bausrate
vo ca 4882  ***
;*********************************************************************** 
**************

init_UART:

 push temp


        ; Baudrate einstellen
    ldi temp, 0x00
        out UBRRH, temp
        ldi temp, LOW(UBRRVAL)
        out UBRRL, temp


        ; Frame-Format: 8 Bit
        ldi  TEMP,  (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
        out UCSRC, temp

        sbi UCSRB,TXEN                    ; TX aktivieren

  pop temp
  ret

----------------------------

Wäre sehr nett wenn sich jemand die Mühe machen würd und sich das mal
anschaut. Vielen dank im Vorraus :-)
Gast #228486
Lesenswert?

kann es sein, dass Du TxD und RxD verwechselt hast?
Invertiert werden muss nix bei uC zu uC. Nur wenn ein Partner RS232
Pegel verwendet, also +-12V, dann wird logisch '1' zu -12V, was dann
mit einer Primitiv-Empfangsschaltung (z.B. Zenerdiode) halt invertiert
ist.
Gast #228487
Lesenswert?

Wer sagt denn hier was von RS232? Da war doch gar nicht die Rede von.
Nee, nee. Nicht verwirren lassen.

TxD vom Sender an RxD vom Empfänger ist goldrichtig. Dann kommuniziert
man eben mit 5V-Pegeln. Geht. Ganz klar. Eventuell aber ein 10k
Pull-Down, ich hatte da mal Probleme, allerdings mit wesentlich höheren
Baud-Raten.

Zu Deinem Code kann ich leider nix sagen, ich programmiere in C.

Bestimmt wird Dir hier noch geholfen.

Gruß,
Sebastian
Gast #228488
Lesenswert?

lässt du den 8535 jetzt mit 10 oder 16MHz laufen?
Irgendwie stehen da zwei ".equ"-Anweisungen.
Wie wäre es denn, wenn die Controller duplex verbindest, sprich: beide
TXD-Leitungen mit beiden RXD-Leitungen verbinden?
Gast #228489
Lesenswert?

Hallo,
also meiner meinung nach müssten deine inits auf beiden avrs gleich
sein. Auch würde ich vermeiden nur einzelne bits zu setzen ohne vorher
das register komplett zu initialisieren.

sbi UCSRB,TXEN                    ; TX aktivieren

so was z.B, du weist ja nie ob vorher wirklich alle low waren. Auch
sind deine registerbezeichnungen teilweise komisch, das UCSRB heißt
doch auch UCR ??? Und das UCBRR ist nur ein 8 Bit register. Da brauchts
kein high() und low()

mfg
Stefan
Gast #228490
Lesenswert?

Hallo!

Also ich bin mir sehr sicher dass ich TxD mit RxD verbunden habe. Ich
habs eben nochmal nachgschaut. Den 8535 hatte ich mal mit 16 Mhz und
hab gedacht es könnte evtl daran liegen dass es nicht geht. Ich hab ihn
dann an einen 10Mhz Quarz gehängt und gehofft dass es dann geht. Hat
aber nichts geholfen. Das mit den 16Mhz ist auskommentiert. Hab ich
vergssen wegzumachen g

Wo sollte ich den 10k Widerstand hinmachen?
Ich weiß zwar in etwa was Pull-down heißt aber ich
hab ehrlich gesgat keine Ahung wo der Widerstand da
jetzt hin sollte :-)

Was hätte ich den davon wenn ich beide Leitungen verbinde?
Das Problem daran wäre dass ich die Beiden anderen Pins schon benutze.
Ich müßte also nochmal an die Hardware ran. Ich würd das gern vermeiden
wenns geht. Ich kann doch asynchron senden und empfangen
dacht ich.

Die bezeichnungen für die Register hab ich aus dem Tutorial bzw aus dem
Datenblatt des 2313 übernommen. Das Low() ist da quatsch das stimmt :-)
Ich werd jetzt mal testen was passiert wenn ich die register vorher mit
0x00 beschreibe. Ich hab das Programm mit dem
Softwaredebugger vom AVR-Studio getstet. Da ist beim aufruf natürlich
alles null. g

vielen Dank für die Tipps. :-)
Gast #228491
Lesenswert?

Hallo.
Da fällt mir grade nochwas ein.
Wie ist das mit dem URSEL-bit?
Soweit ich das verstanden hab aus dem Datenblatt kann ich damit regeln
in welches Register ich schreibe. Entweder nach UBRRH oder UCSRC. Beim
AVR-Studio werden aber IMMER beide Register geschrieben. Liegt das an
meinem Programm oder ist das ein Fehler im AVR-Studio?

danke :-)
Gast #228492
Lesenswert?

Hallo!

Ich hab die Initmethoden jetzt verändert.
Was haltet ihr davon?

AT90S2313:


init_UART:
 push temp


        ldi temp, UBRRVAL     ; Baudrate einstellen
        out UBRR, temp

        ldi temp, 0x10
        out UCR, temp         ; RX (Empfang) aktivieren


  pop temp
ret


ATMEGA8535:


init_UART:

 push temp

        ; Baudrate einstellen
  ldi temp, 0x00
        out UBRRH, temp

        ldi temp, UBRRVAL
        out UBRRL, temp


        ; Frame-Format: 8 Bit
        ldi temp, 0x00
  out UCSRC, temp

        ldi  TEMP,  (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
        out UCSRC, temp

        ldi temp, 0x08
        out UCSRB,temp                    ; TX aktivieren

  pop temp
ret


Es geht übrigens trotzdem nicht :-)
Gast #228493
Lesenswert?

Deine Init im tiny2313 ist unvollständig, Du gibst keine
Frame-Informationen (Bytelänge, Stop, Parity...) an. Außerdem gibt es
Low- und High-Register für die Baudrate. Lies Dir mal das Datenblatt
durch ab Seite 110, da steht, wie´s gemacht wird.
Gast #228499
Lesenswert?

Hi!

Ich möchte wirklich nur ein Byte senden ....
Das restliche Programm ist recht groß und unübersichtlich. Es ist eine
Steuerung für einen 6 beinigen Laufroboter.
Das einzige was nicht funktioniert ist die Komunikation zwischen den
controllern. Ich zeige euch gerne noch die sende Methode. Wenn ihr
wirklich wollt stelle ich auch das ganze Programm rein. Aber ich glaub
das bringt nichts.  Also dann hier mal die Methode zum senden


;*******************************************************************
;*** Diese Methode versucht ein Byte über das UART zu senden.    ***
;*** Sie klemmt das Programm solange fest bei das Byte weg ist.  ***
;*******************************************************************


send_Data_UART:

sbis UCSRA,UDRE
rjmp send_Data_UART


ldi send_Data, 0x03
out UDR, send_Data
ret


und hier die Methode zum empfangen...



;**********************************************************
;***  Methode zum empfangen eines Datums über das Uart  ***
;***  Falls ein neues Datum vorhanden ist dann wird     ***
;***  der neue Bewegungsmodus festgelegt.               ***
;***  (es findest keine Überprüfung auf Framfehler      ***
;***    oder Overflow statt!!)                          ***
;**********************************************************


receive_DATA:

        sbis USR, RXC
        ret


        push RData

        in RData, UDR
        ldi MovementMode, 0x00
        ADD MovementMode, RData
        pop RData
ret

Ansonsten benutze ich nur noch das Register Movementmode außerhalb
dieser Routinen. Ich denk mal dass es dann daran liegen muß wie ich
sende oder Empfange.

SPI möchte ich nicht benutzen weil ich noch nciht weiß ob ich später
irgendwann noch mehr Controller anhängen möchte.
Also wenn jemand eine Idee hat wäre ich für Voschläge dankbar :-)
Gast #228500
Lesenswert?

[aussem Tutorial übernommen]

receive_loop:
        sbis UCS[RA], RXC   ; warten bis ein Byte angekommen ist
        rjmp receive_loop
        in temp, UDR      ; empfangenes Byte nach temp kopieren
        out PORTD, temp   ; ... und an Port D ausgeben.

Einmal reinspringen und dann warten :) vielleicht ja endlos..
Oder richte mal nen IRQ für RXC ein, wäre vielleicht sogar sicherer.
Gast #228501
Lesenswert?

IRQ?  :-)

Ich mach in meinr recevie Methode glaub ich das selbe.
Ich warte nur nicht endlos, sondern wenn nix da ist sprioge ich aus der
Methode wieder raus. Ich seh sonst keinen UNterschied. Ich habs übrigens
auch aus dem Tutorial g
was ist denn ein IRQ?
#228502
Lesenswert?

"was ist denn ein IRQ?"

Nee...?

Ein IRQ ist ein Interrupt-Request. Kann von einem Timer oder einem
anderen Ereignis (siehe Datenblatt, Interruptquellen) ausgelöst werden
und verzweigt über die am Programmanfang stehende
Interrupt-Sprungtabelle...

So machst du das doch, oder willst du etwa behaupten, dass du solch
komplexe Steuerungen wie einen 6-beinigen Laufroboter ohne Interrupts
machst?

...
Gast #228504
Lesenswert?

Hallo,
also ich finde das sieht eigendlich sehr gut aus. Probier mal

.equ UBRRVAL = 128

eventuell kommt dein Assembler ja nicht mit dem rechnen klar. Der Init,
das senden und empfangen sollte so funktionieren, zumindest beim 2313.
Hast du den TxD Pin als Ausgang mit Pull-Up definiert und den RxD am
anderen Prozzi als Eingang? Ich mach das zumindest immer, ich weis
nicht obs auch ohne geht.

mfg
Stefan
Gast #228505
Lesenswert?

HI!
Ja stimmt ich mach das mit interrupts.
Ich wußte nur nicht dass das IRQ heißt :-)

Ich weiß ich führe ret aus. Wenn ich es so wie im tutorial mache dann
muß ich evtl ewig warten. So wie ich es mache springt er wieder raus
wenn er nix empfangen hat. Ich fand das so besser.

Im Datenblatt steht dass es egal ist ob man den PIN als Engang oder
ausgang definiert sobald man das UART eingeschaltet hat. Ich hab das
auch mal getestet. Es hat sich nix geändert. Das mit dem 128 probier
ich mal aus. Ich würd dann allerdings nicht vertsehen warum es geht...
g
Gast #228506
Lesenswert?

Wie ich das teste dass es nicht geht?
ganz einfach g
Die beiden Programme auf den beiden contollern machen genau das was sie
sollen wenn ich die werte die ich vom uart bekommen soll einfach fest
einspeichere. Sobald die Werte mit dem UART eingelesen werden sollen
geht nixmehr. Daraus schließe ich dass es an der komunikation liegen
muss. Das ist ja das einzige was ich ändere......
#228507
Lesenswert?

Jetzt "zerpflück" ich mal deine Routine:

;**********************************************************
;***  Methode zum empfangen eines Datums über das Uart  ***
;***  Falls ein neues Datum vorhanden ist dann wird     ***
;***  der neue Bewegungsmodus festgelegt.               ***
;***  (es findest keine Überprüfung auf Framfehler      ***
;***    oder Overflow statt!!)                          ***
;**********************************************************


receive_DATA:

        sbis USR, RXC
        ret


        push RData

        in RData, UDR
        ldi MovementMode, 0x00
        ADD MovementMode, RData
        pop RData
ret

Die Routine wird alsp mit (r)call aufgerufen.
Wenn das Interrupt-Flag RXC in USR nicht gesetzt wurde, dann wird
sofort zurückgesprungen. Das ist erstmal richtig, obwohl das Überprüfen
dieses Flags in der Mainloop "billiger" wäre, also jede Menge (r)call
und ret ersparen würde, die ja nicht gerade wenig Takte verbrauchen.
Nun kommt push & pop von RData. Wäre richtig, wenn man RData brauchen
würde. Braucht man aber nicht. Denn du könntest die Daten auch sofort
in das Register MovementMode einlesen, denn der Umweg über Löschen und
Addieren kommt aufs Selbe raus.

Statt

        push RData

        in RData, UDR
        ldi MovementMode, 0x00
        ADD MovementMode, RData
        pop RData
ret

würde also

 in MovementMode,UDR
 ret

völlig reichen.

Noch sparsamer wäre es in der Mainloop:

mainloop:
 ;irgendwelche anderen Jobs...
 sbis usr,rxc              ;Byte empfangen? ja...
 rjmp mainloop1            ;nein, weg hier...
 in MovementMode,udr       ;ja, Byte übernehmen
mainloop1:
 ;weitere Jobs der Mainloop
 rjmp mainloop             ;nochmal...

Du sparst bei gleicher Funktionalität einen UP-Aufruf (7 Takte), der ja
länger dauert als die eigentliche Arbeit.

...
#228508
Lesenswert?

Und andersherum wird es noch billiger:

 ;andere Mainloop-Jobs
 sbic usr,rxc             ;neues Byte empfangen?
 in MovementMode,udr      ;ja, Byte übernehmen
 ;weitere Mainloop-Jobs

Diese 2 Zeilen kosten dich ganze 2 Takte Rechenzeit und bewirken das
Selbe wie deine Routine.

Hat aber den Nachteil, dass man keine weiteren Programmzeilen einfügen
kann, z.B. das Setzen eines Flags, um andere Programmteile zu
informieren, dass sich etwas geändert hat.

...
Gast #228509
Lesenswert?

also wenn ich das reichtig verstadanden hab ich das so wie ich es
geschrieben hab sehr umständlich aber es sollte funktionieren? :-)
bzw du siehts keinen Grund warum es nciht gehen soll?
Gast #228510
Lesenswert?

Hallo,

Den Pull-down zwischen die TxD-RxD-Verbindung und GND.
Aber daran muss es nicht liegen.

Grundsätzlich solltest Du überprüfen:
a) identische Baudrate eingestellt?
b) externe Takte (Quarze oder Quarzoszillatoren) verwenden! Die
internen Oszillatoren in den AVRs sind zu ungenau.
c) gleiche Frames (z.B. 1 Startbit, 8 Datenbits, 2 Stoppbits)?

Deine beiden AVRs laufen aber an, oder? Nicht, dass einer der Beiden
aus irgendwelchen Gründen gar nicht arbeitet?

Ansonsten kann ich mich meinen Vorrednern nur anschließen: In den
Datenblättern sind Beispiele, wie man die USART auch in Assembler
initialisiert und programmiert. Das soll kein RTFM sein, die können das
nur besser erklären als ich ;-)

Weiterhin viel Erfolg.
Gruß,
Sebastian
#228512
Lesenswert?

> 0,54 euro porto können nie schadn

Für jedes Bit oder jedes Byte?

Ich habe übrigens nicht geschrieben, dass es funktionieren müsste, nur
dass es dasselbe tut wie deine Routine.

Um Aussagen zur Funktion machen zu können bräuchte ich das gesamte
Programm, viel Zeit und ein Motiv, warum ich mir diese Arbeit aufhalsen
sollte. Denn woher soll ich wissen, ob diese Routine auch jemals
aufgerufen wird?

Ansonsten schließe ich mich Sebastian an.

...
Gast #228513
Lesenswert?

Ich benutze externe osilatoren und abe die selbe baudrate eingestellt.
Es könnte natürlich an unterschiedlichen frmes liegn. Ich hab aber
leider im Tutorial vom AT90S2313 nix dazu gefunden was für frames er
sendet! Ich dachte deshalb dass er wohl 8 Bit frames sendet. Ist das
falsch? Wie bekomme ich das raus? :-)
#228514
Lesenswert?

Hmmm...

Also ich hatte kürzlich das Problem, dass ein 3,6864MHz-Quarz (mit
22pF-Kondensatoren) an einem Mega8535 mit dreifachem Tempo rannte. Da
ging die serielle Verbindung mit dem PC auch nicht. Erst Kondensatoren
von 330pF am Quarz brachten Abhilfe. Warum das so ist, weiß ich nicht,
die Quarze stammen aus einem Sortiment von Pollin.

Es wäre also nicht schlecht, wenn du die Taktfrequenz mal überprüfen
würdest.

...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren