hi, ich habe mal ne Frage ich möchte eine Verbindung zwichen meinem Atmega und meinem taschenrechner herstellen. Ich hätte dazu zwei Fragen: 1. Ich brauche: 1 startbit, 8 databits, no parity, 2 stopbits, 9600 baud wie stell ich das ein Ich weis nur wie das mit der Baudrate geht. 2. ich muss z.B. laut protokoll 13h senden was kann damit gemeint sein? nur 13 13 und h oder steht das h für hexa also 19? hier der Link dazu: http://users.pandora.be/gp/casio/
Die Einstellungen nimmst Du im UART-Modul vor. Siehe Datenblatt ATMEGAxxx. Dort sind Beispiele in Assembler und C abgedruckt. 13h heißt 13 hexadezimal, was dezimal der 19 entspricht, richtig!
also ich habe mir das datenblatt mal durchgelesen...aber so richtig verstehe ich das nicht.
Ist da nicht sogar ein Beipiel im Datenblatt? Jetzt reiss Dich mal zusammen :-)
ao richtig vertanden was was bewirkt habe ich noch nicht.,..aber ist das richtig. ldi r16, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0) out UCSRC,r16
Hallo Florentin, hier steht es mit Beispielen: http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART "10" und "13" sind nicht in hex - es ist dezimal, wobei "10" = LF (line feed - Zeilenvorschub) und "13" = CR (carriage return - Wagenrücklauf) Gruss Otto
@ Florentin Schirmer (tuxianer) >wie stell ich das ein Ich weis nur wie das mit der Baudrate geht. Steuerregister des USART. >2. ich muss z.B. laut protokoll 13h senden was kann damit gemeint sein? Bit du sicher, dass du mit dem AVR umgehen kannst, wen du schon über 13h stolperst? 13h heisst 13 in hexadezinaler Darstellung. 0x13 oder $13, dezimal 19 >nur 13 13 und h oder steht das h für hexa also 19? ja. MfG Falk
nein, nicht hex: rcall serout ldi temp, 10 rcall serout ldi temp, 13 Gruss Otto
also mit dem 0x13 ist klar das hatte cih auch so gemacht, ich wollt mich nur nochmal versichern ich habe mich vlt blöd ausgedrückt. Leider funktioniert mein programm nicht so wie es soll...zumindestens gehen keine Dioden an und auf dem Re4chner bekomme ich ein error...
1 | |
2 | .include "m32def.inc" ; bzw. 2333def.inc |
3 | |
4 | .def temp = R16 |
5 | .def RX = R17 |
6 | .def TX = R18 |
7 | .equ CLOCK = 16000000 |
8 | .equ BAUD = 9600 |
9 | .equ UBRRVAL = CLOCK/(BAUD*16)-1 |
10 | |
11 | .org 0x00 |
12 | rjmp main |
13 | |
14 | .org URXCaddr ; Interruptvektor für UART-Empfang |
15 | rjmp int_rxc |
16 | |
17 | ; Hauptprogramm |
18 | main: |
19 | ldi temp, LOW(RAMEND) |
20 | out SPL, temp |
21 | ldi temp, HIGH(RAMEND) |
22 | out SPH, temp |
23 | |
24 | ldi temp, 0xFF ; Port D = Ausgang |
25 | out DDRD, temp |
26 | |
27 | ldi temp, 0xFF |
28 | out PortD, temp |
29 | |
30 | ; Baudrate einstellen |
31 | ldi temp, HIGH(UBRRVAL) |
32 | out UBRRH, temp |
33 | ldi temp, LOW(UBRRVAL) |
34 | out UBRRL, temp |
35 | |
36 | ; Frame-Format: 8 Bit |
37 | ldi r16, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0) |
38 | out UCSRC, temp |
39 | |
40 | sbi UCSRB, RXCIE ; Interrupt bei Empfang |
41 | sbi UCSRB, RXEN ; RX (Empfang) aktivieren |
42 | sbi UCSRB, TXEN ; TX (Senden) aktivieren |
43 | |
44 | sei ; Interrupts global aktivieren |
45 | |
46 | loop: rjmp loop ; Endlosschleife |
47 | |
48 | ; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde |
49 | int_rxc: |
50 | push temp ; temp auf dem Stack sichern |
51 | cbi PORTD, 5 |
52 | in RX, UDR ; Empfangenes Byte in RX speichern |
53 | |
54 | cpi RX,0x16 |
55 | |
56 | breq Transmit |
57 | |
58 | pop temp ; temp wiederherstellenerrupt beenden |
59 | reti ; Int |
60 | |
61 | |
62 | |
63 | Transmit: |
64 | |
65 | ldi TX, 0x13 |
66 | sbis UCSRA,UDRE ; Warten bis UDR für das nächste Byte bereit ist |
67 | rjmp Transmit |
68 | out UDR, TX |
69 | cbi PORTD, 6 |
70 | reti ; zurück zum Hauptprogramm |
breq Transmit pop temp ; temp wiederherstellenerrupt beenden reti ; Int Transmit: ldi TX, 0x13 sbis UCSRA,UDRE ; Warten bis UDR für das nächste rjmp Transmit out UDR, TX cbi PORTD, 6 reti ; zurück zum Hauptprogramm das funktioniert nicht, weil Du am Ende von Transmit kein "pop" ausführst..... Otto
was kann da falsch sein...beim assembolieren bekomme ich keinen Error aber wenn ich den Simulator starte kommt das. AVR Simulator: Invalid opcode 0xffff at address 0x003802 AVR Simulator: Invalid opcode 0xffff at address 0x003804 AVR Simulator: Invalid opcode 0xffff at address 0x003806
so...ich habegerade gemerkt aus TX kommt dauerhaft strom ist das normal??? ich dachte es liegt daran das habe ich mal geändert. ldi temp, 0b01100000 out PortD, temp aber es kommt immer noch strom... so es geht jetzt bis zur ersten LED allerdings wenn ich die LED nach erfolgreichen Vergleich schlate gehts nicht...
und der Fehler kommt immer noch... AVR Simulator: Invalid opcode 0xffff at address 0x000004 AVR Simulator: Invalid opcode 0xffff at address 0x000004 AVR Simulator: Invalid opcode 0xffff at address 0x000004 AVR Simulator: Invalid opcode 0xffff at address 0x000004 AVR Simulator: Invalid opcode 0xffff at address 0x000004
> so es geht jetzt bis zur ersten LED allerdings wenn ich die LED nach > erfolgreichen Vergleich schalte gehts nicht... zeig mal den Code... Otto
1 | .include "m32def.inc" ; bzw. 2333def.inc |
2 | |
3 | .def temp = R16 |
4 | .def RX = R17 |
5 | .def TX = R18 |
6 | .equ CLOCK = 16000000 |
7 | .equ BAUD = 9600 |
8 | .equ UBRRVAL = CLOCK/(BAUD*16)-1 |
9 | |
10 | .org 0x00 |
11 | rjmp main |
12 | |
13 | .org URXCaddr ; Interruptvektor für UART-Empfang |
14 | rjmp int_rxc |
15 | |
16 | |
17 | ;Hauptprogramm |
18 | main: |
19 | ldi temp, LOW(RAMEND) |
20 | out SPL, temp |
21 | ldi temp, HIGH(RAMEND) |
22 | out SPH, temp |
23 | |
24 | ldi temp, 0xFF ; Port D = Ausgang |
25 | out DDRD, temp |
26 | |
27 | ldi temp, 0b01100000 |
28 | out PortD, temp |
29 | |
30 | ; Baudrate einstellen |
31 | ldi temp, HIGH(UBRRVAL) |
32 | out UBRRH, temp |
33 | ldi temp, LOW(UBRRVAL) |
34 | out UBRRL, temp |
35 | |
36 | ; Frame-Format: 8 Bit |
37 | ldi r16, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0) |
38 | out UCSRC, temp |
39 | |
40 | sbi UCSRB, RXCIE ; Interrupt bei Empfang |
41 | sbi UCSRB, RXEN ; RX (Empfang) aktivieren |
42 | sbi UCSRB, TXEN ; TX (Senden) aktivieren |
43 | |
44 | sei ; Interrupts global aktivieren |
45 | |
46 | loop: rjmp loop ; Endlosschleife |
47 | |
48 | ; Interruptroutine: wird ausgeführt sobald ein Byte über das UART empfangen wurde |
49 | int_rxc: |
50 | |
51 | push temp ; temp auf dem Stack sichern |
52 | |
53 | cbi PORTD, 5 |
54 | in RX, UDR ;Empfangenes Byte in RX speichern |
55 | |
56 | cpi RX,0x16 |
57 | |
58 | breq Transmit |
59 | |
60 | pop temp ; temp wiederherstellenerrupt beenden |
61 | reti ; Int |
62 | |
63 | |
64 | |
65 | Transmit: |
66 | cbi PORTD, 6 |
67 | ldi TX, 0x13 |
68 | sbis UCSRA,UDRE ; Warten bis UDR für das nächste Byte bereit ist |
69 | rjmp Transmit |
70 | out UDR, TX |
71 | |
72 | reti ; zurück zum Hauptprogramm |
1. das funktioniert so nicht, weil Du am Ende von Transmit kein "pop" ausführst..... SIEHE OBEN ! 2. Wo hängen denn wie viel LED dran und ist ein Transistor dazwischen ? Otto
also daran kanns ja nicht liegen mit dem Pop aber danke für den hinweis...temp wird ja eh nirgendwo anders verwendet...und ich habe 2 Dioden über widerstand zu Ground an Portd 5 und 6 Ps.: im Moment leuchtet Diode 1 nur wenn ich die TX Leitung abklemme
>also daran kanns ja nicht liegen mit dem Pop aber danke für den
Ich glaube es hackt ! Zu JEDEM PUSH gehört genau ein POP.
Egal wo, aber es muss getan werden. Sonst läuft dir der Stack über !
sorry das wusst ich noch nicht...und jetzt geht auch die Diode mal wieder, wenn TX drann ist...
Hallo Florentin, weshalb fragst Du überhaupt, wenn Du alles weißt ? Gruß Otto
es tut mir wie gesagt leid davon habe ich als Anfänger noch nix gehört ich habe die ganzen Push und pops mal weg gemacht aber es geht leider immer noch nicht weiter als bis zu LED1
Du mußt auch bei erfolgreichem Vergleich das Temp-Register wieder pop'en Und so ist schöner:
1 | int_rxc: |
2 | push temp ; temp auf dem Stack sichern |
3 | |
4 | cbi PORTD, 5 |
5 | in RX, UDR ;Empfangenes Byte in RX speichern |
6 | cpi RX, 0x16 |
7 | brne ende |
8 | |
9 | cbi PORTD, 6 |
10 | ldi TX, 0x13 |
11 | Transmit: |
12 | sbis UCSRA, UDRE ; Warten bis UDR ist |
13 | rjmp Transmit |
14 | out UDR, TX |
15 | ende: |
16 | pop temp ; temp wiederherstellen |
17 | reti ; zurück zum Hauptprogramm |
Allerdings brauchst du nur die Register zu pushen, die du auch benutzt ;) hth. Jörg
Hallo Florentin, es kann auch nicht weitergehen, da Du die LED's nur einmal aus- aber nie wieder einschaltest... cbi PORTD, 5 cbi PORTD, 6 Otto
@Otto, hetz nicht so ;-) Immer schön ein Schritt nach dem anderen. scnr Jörg
jetzt bin ich etwas verwirt... schalte ich sie nicht hier aus: ldi temp, 0b01100000 out PortD, temp und mit cbi PORTD, 5 cbi PORTD, 6 jeweils ein oder verdrehe ich da was... Ps: Jörgs variante geht leider auch nicht.
also es hängt definitiv am Vergleich...es Springt direkt zu Ende...
hier schaltest Du sie ein (wenn sie vom Port gegen Masse liegen): ldi temp, 0b01100000 out PortD, temp bloß da kommst Du NIE wieder hin.... erst beim nächsten RESET Otto
>erst beim nächsten RESET
Soll er halt den Watchdog aktivieren ;)
Nee, mach das bloß nicht !
ich habe mich blöd ausgedrückt...es ist genau anders herum: Controller-->Widerstand-->Diode-->VCC
Es wird nur dann nicht gesprungen wenn 0x16 empfangen wird (das ist kein druckbares ASCII zeichen, btw) und um den Empfang zu simulieren müsstest du Stimuli-Files benutzen (dabei kann ich dir nicht helfen) oder nach dem "in RX, UDR" das Register RX mit 0x16 von Hand beschreiben. Wenn du direkt mit dem AVR "redest" solltest du vielleicht 0x16 in ein druckbares zeichen ändern, z.B. 'A' (MIT ' in den Code schreiben) hth. Jörg
also wie gesagt so genau weis ich nicht wie der rechner arbeitet...ich habe leider nur den Link: http://users.pandora.be/gp/casio/ mit Druckbaren zeichen ist leider auch schlecht die 22 ist ein Syn oder so ähnlich...
einfach geht es erst mal so: loop: ldi temp, 0b01100000 ; LED aus out PortD, temp ; rjmp loop ; Endlosschleife int_rxc: push temp ; temp auf dem Stack sichern cbi PORTD, 5 in RX, UDR ;Empfangenes Byte in RX speichern cpi RX, 0x16 brne ende cbi PORTD, 6 ldi TX, 0x13 Transmit: sbis UCSRA, UDRE ; Warten bis UDR ist rjmp Transmit out UDR, TX ende: pop temp ; temp wiederherstellen reti ; zurück zum Hauptprogramm Otto
mit den zeilen geht es nich ohne geht es bis zur ersten LED. ldi temp, 0b01100000 ; LED aus out PortD, temp ;
Bitte etwas genauer: 1. die LED werden ausgeschaltet 2. bei Empfang irgendeines Zeichens geht LED 1 an 3. bei Empfang "0x16" LED 2 - aber "0x16" kannst Du wahrscheinlich nicht senden. Versuche, den AVR an den PC anzuschliessen und arbeite z. B. mit Hyperterminal, bis alles läuft. Dann kannst Du, wie Joerg riet, auf 'A' abfragen und siehst anschliessend auch das "13" (CR) Otto
also hexa abfragen muss gehen...her hat mal jemand etwas änliches für den gleichen rechner gemacht: http://www.mikrocontroller.net/attachment/7211/casio.asm
ich seh gerade da ist das auhc anders: (1<<URSEL0)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00)
ja, kann schon sein, aber Deinen Casio kenne ich leider nicht.... Otto
"hex abfragen" geht natürlich beim AVR - die Frage ist, ob Du das Zeichen senden kannst. Anders ist die Anzahl der Stoppbits: ; Set frame format: 8data, 2stop bit ldi r16, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0) Gruß Otto
Hallo, das kann nicht gehen. Der Rechner will immer einen kompletten Block haben mit Checksumme usw. Du sendest nur 1 byte und dann nix mehr. -> Error Dann läuft das Programm auch sehr schnell, da wirst du keine LED An/Aus erkennen. Wenn doch, dann stimmt was nicht mit der Clockrate oder so. Nicht stören lassen, der Taschenrechner kommt mit 1 und 2 Stoppbits zurecht. Condi
Also zum Senden komm ich ja garnicht...wenn ich eine LED nach den Vergleich setzte springt diese nicht an. Die Cehcksum kommt erst im Header soweit bin ich leider noch nicht. Und wie muss die Einstellung nun lauten für die Stopbits? die LED wird ja angeschalten wenns klappt und leibt dann an! Siehe die erste.
Beschreib mal deinen Aufbau: Was ist womit verbunden (v.A. der USART)?, Wo/Wie sind die LEDs angeschlossen? Wenn dein Atmega auf bestimmte Zeichen reagieren soll: wo kommen diese Zeichen her (Taschenrechner, PC...)? Indem Beispielcode den du (ganz weit) oben verlinkt hast, wird ein Atmega162 verwendet, der hat 2 USART: einer ist mit dem PC verbunden, der andere mit dem Taschenrechner. Deshalb komm ich auf die Frage: Was hast du eigentlich vor? hth. Jörg
Also das hatte ich eigentlich alles schon beschrieben...ist leider etwas verstreut deshalb nochmal: ich will vom GTR Variablen ec. an den Controller senden. Der ist via Kabel an den RX und TX Port verkabelt PortD0 und 1. Die Leds hängen nach folgendem Schema an PortD 5/6: Controller-->Widerstand-->-Diode+-->VCC
So wie ich das sehe, hast du 2 Baustellen. Die eine die UART am AVR, die andere das Protokoll welches du einhalten musst um mit dem Casio zu kommunizieren. Das ist nicht gut, weil du nie weist, wo denn ein Fehler liegt. Ich würde mal hergehen und eine Baustelle stilllegen: An den AVR einen MAX232 anschliessen und damit eine serielle Verbindung zum PC aufbauen. Am PC läuft dann ein einfaches Terminalprogramm, welches alles was von der Seriellen kommt mitprotokolliert. Dadurch hast du schon mal das Casio-Protokoll Problem weg und kannst dich nur auf die UART am AVR konzentrieren. Läuft die dann irgendwann, dann gehts wieder zurück auf die Casio Schnittstelle und das Protokoll ist drann. Das andere: Wenn ich mir deinen Assembler-Code und das daraufhin gezeigte Verständnis so ansehe, wäre vielleicht eine Programmierung in C nicht das schlechteste.
Sorry, aber dann hat er noch eine Baustelle mehr ! Da ist einfach etwas Zeit erforderlich um sich einzuarbeiten - und ich persönlich halte assembler für sehr sinnvoll um die Hardware erst mal kennenzulernen. C vielleicht dann mal später. @ Florentin: Also nicht aufgeben - notfalls erst mal ein einfacheres Thema angehen !!! Gruß Stefan
nein der tip ist nicht schlecht die Teile habe ich auch da...das werde ich mal probieren...und wenn ich via terminal 0x16 sende sehe ich ja ob 0x13 zurückkommt. Und so komplex fidne ich das Thema garnicht ich halte es für eine gute Übung.
Stefan wrote: > Sorry, aber dann hat er noch eine Baustelle mehr ! Einen Max232 anschliessen ist aber keine Raktentechnik. Das wär mir auf jeden Fall lieber als mit einem Gerät zu kommunizieren, welches ein bestimmtes Protokoll erwartet und ich nicht weiss ob meine UART grundsätzlich funktioniert oder ob ich im Protokoll einen Fehler hab. Die Hilfs-Baustelle Mega - MAX232 - Kabel - PC - Hyperterminal ist in 20 Minuten befahrbar und: da kann eigentlich nicht viel schief gehen (ausser der ewigen Frage: Modem oder Nullmodem- Kabel). Wenn die UART an dieser Baustelle nicht funktioniert, dann wird sie auch an der Casio Baustelle nicht funktionieren. Umgekehrt: Wenn die PC Baustelle funktioniert, dann hab ich bei einem Casio-Baustellenproblem schon mal eine Fehlerquelle weniger. Und: Im Schlimmsten Fall hat man damit auf dem PC mit HTerm ein mächtiges Werkzeug um sich anzusehen, was denn der AVR/Casio nun wirklich sendet und kann dann am PC auch mal die Gegenstelle vorgaukeln. Aber: Jeder wie er mag.
ich bin der gleichen Meinung...ich werde mir da am besten ne Lochradter holen und nen Max gleic auflöten mit elkos! Und Man braucht ein Modemkabel oder?
Florentin Schirmer wrote: > ich bin der gleichen Meinung...ich werde mir da am besten ne Lochradter > holen und nen Max gleic auflöten mit elkos! Und Man braucht ein > Modemkabel oder? Kommt drauf an, wie du die Signale vom MAX auf deine RS232 Stecker/Buchse legst. Hier ist das beschrieben: http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART
wie die richtige Stopbit einstellung ist weis ich übrigens immer noch nicht...
Stoppbit ist nur für den Sender interessant. Mit Stoppbits wird im Grunde eine kleine Pause zwischen den einzelnen Bytes eingelegt, sodass der Empfänger eine kleine 'Verschnaufpause' kriegt. Wenn du 2 einstellst bist du daher auf jeden Fall auf der sicheren Seite.
so ich hattes am PC...wenn ich 16h sende geht die 2. LED an! empfangen ahbe ich aber glaube noch nix...
super es geht jetz!!! ich glaube ich ahtte doch was an den Startbits oder so verkehrt keine Ahnung...
Also der Mega162 wurde gewählt da 2 Taschenrechner sich in einem Programm nicht direkt unterhalten können. Er dient so als Puffer und Umsetzer. Und nochmals, auf dem Rechner kommt immer ein Error wenn du nicht den Start und Stop Header sendest. Es ist dabei vollkommen egal ob du ein Programm, Matrix oder nur eine Variable sendest. In der main loop von otto werden die LED's ausgeschalten. Nun kommt ein Zeichen und der geht in den interrupt. Da wird die LED 1 eingeschalten. Wenn keine 0x16 empfangen wurde, geht der wieder ind die Main und die LED's gehen aus. Wurde 0x16 empfangen, setzt er die LED 2 auf ein sendet und geht in die Main wo die LED's ausgeschalten werden. Das geht so schnell, da kann man höchstens ein sehr kurzes flackern sehen. Bleiben die LED's an, dann läuft der Stack über oder das UDR wird nie leer.... oder du hast nen komplett anderen Code. Condi
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.