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 :-)
Stimmt die Hardware? Ich glaube mich zu erinnern, irgendwo hier mal gelesen zu haben, dass man eine der RS232-Leitungen invertieren müsste, falls man keine MAX232-ICs benutzt. Ist aber jetzt reine Spekulation. ...
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.
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
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?
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
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. :-)
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 :-)
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 :-)
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.
Es ist kein Tiny2313 sondern ein AT90S2313. Aber das kommt davon, wenn man die Bezeichnungen nicht korrekt nennt. Dann verwechselt man das schnell mal... ...
Beim AT90S2313 kann ich ja keine Frames und sowas einstellen. Ich geh mal davon aus dass der immer auf 8-Bit Frames läuft. Stimmt das?!
Stackpointer initialisiert ? Gut wäre es, wenn du mal das ganze Programm anhängen würdest...
Übrigens: wenn du nur zwischen 2 Controllern Daten austauschen willst, nimm doch SPI. Ist etwas einfacher.
Davon wäre ich jetzt nicht so überzeugt :) Aber es wäre wirklich mal interessant, wie du denn überhaupt feststellst, dass das nich läuft :)
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 :-)
[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.
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?
"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? ...
Ich mach in meinr recevie Methode glaub ich das selbe. Öh ne. Du führst andauernd einen ret aus!?
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
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
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......
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. ...
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. ...
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?
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
Fällt mir gerade ein, teste doch mal auf frame-Errors, evtl. gibt das Hinweise darauf, was genau nicht stimmt. Gruß nochmal, Sebastian
> 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.
...
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? :-)
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. ...
coole sache... danke für den Tipp .... Wie teste ich die? Mit einem Oszyloskop oder gibts da noch andere Möglichkeiten?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.