Forum: Mikrocontroller und Digitale Elektronik Zwei 90S2313 verbinden und definierte Daten lesen


von Mo. (Gast)


Lesenswert?

Ich habe ein Problem, dass mir schon eine Woche schlaflose Nächte
bereitet und hoffe nun hier auf ein paar aufmunternde Worte und etwas
Hilfe.

a) Ich treffe die Annahme, dass ein AT90S2313 (getaktet mit 7,3728MHz)
jeweils einmal eine der folgenden Daten über TxD ausgibt. Dabei ist die
Ausgabe als Reaktion auf einen Tastendruck zu verstehen. Dabei handelt
es sich um:

0xC1 -> Ausgabe für Taste 1
0xC2 -> Ausgabe für Taste 2
0xC4 -> u.s.w.
0xC8 ->
0xD0 ->
0xE0 -> Ausgabe für Taste 6

(Anmerkung: 9600Bd, 8 Daten Bits, 1 Stop Bit, no Parity, LSB first)

b) Der in a) genannte Sachverhalt lässt sich leider nicht
beeinflussen/ändern

c) Ein zweiter AT90S2313 (gleiche Taktung) soll mit RxD direkt an den
TxD aus a) angeschlossen werden.

Was nun passieren soll, kann ich zunächst nur mal in Worte fassen. Er
soll in einer Routine prüfen, ob etwas an RxD empfangen wird, wenn ja -
ob es eins der o.g. 6 Stück ist - wenn ja, dann soll er an einem Pin ein
Relais oder einen Schaltkontakt herstellen und dann wieder prüfen, ob
etwas empfangen wird.

Also werden doch auch 6 I/O Pins als Ausgänge benötigt.

Ich habe absolut keine Idee, wie ich das in C umsetzen kann. Hab auch
schon das super WIKI-Tut durch, aber da ist nur das Senden mit dem UART
genauer beschrieben.

von crazy horse (Gast)


Lesenswert?

switch (received_byte){
case 0xC1: tu_irgend_was:break;
.
.
}

von Mo. (Gast)


Lesenswert?

Genau das tu_irgend_was würde mich genauer interessieren! Aber so
abzufragen ist ne gute Idee!

von Johannes Raschke (Gast)


Lesenswert?

C scheint mir dafür ein ziemlicher Overkill zu sein. Mit Assembler hat
man sowas in vielleicht 50 Zeilen schnell programmiert.

In C passiert im Prinzip dasselbe:
UCR richtig setzen, USR permanent abfragen ob es was neues gibt (RXCIE
(RX Complete Interrupt Enable)), wenn nein, weiter warten, ansonsten
UART Data Register lesen und eine case - Anweisung durchlaufen, in der
die Ausgangspins gesetzt werden.

Wo ist jetzt das Problem? Was hast Du denn bis jetzt programmiert? Was
klappt nicht? Was hast Du bisher getan, um die Ursache zu finden und
was hast Du herausgefunden?
Hast Du schonmal in ein "normales" C-Buch geschaut? Ich denke, das
wird im Tutorial ebenso vorausgesetzt wie ein bißchen
Programmiererfahrung...

von Johannes Raschke (Gast)


Lesenswert?

Hä??
tu_irgend_was könnte z.B. sein:
PORTB=0x01;

Wird unter
http://www.mikrocontroller.net/wiki/AVR-GCC-Tutorial#Ausg.E4nge

erklärt.

von Mo. (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für die ersten Antworten. Ich habe mal einen Wntwurf
gemacht. Ist der Ansatz so ok? Also wo ich noch mal ran muss ist die
Taktfrequenz (ist nicht 4000000) und die Aktion, die kommt, wenn Daten
empfangen werden. -> Es soll ja nur ein Pin gesetzt werden!

von Johannes Raschke (Gast)


Lesenswert?

Das sieht doch schon nicht schlecht aus.
Jetzt kannst Du z.B. schreiben:

data_received = USART_RECEIEVE();
    if(data_received == 0xC1) PORTB = 0b00000001;
    if(data_received == 0xC2) PORTB = 0b00000010;
    if(data_received == 0xC4) PORTB = 0b00000100;
    if(data_received == 0xC8) PORTB = 0b00001000;
    if(data_received == 0xD0) PORTB = 0b00010000;
    if(data_received == 0xE0) PORTB = 0b00100000;

und damit Pin 1 bis Pin6 an Port B schalten...

von Mo. (Gast)


Angehängte Dateien:

Lesenswert?

Danke! So macht es mal Spaß weiterzumachen ;)

Habe es jetzt so ergänzt. Wie lange soll er nach dem "Pin-freigeben"
denn warten, damit ein Schaltkontakt überhaupt zustande kommen kann?

von Johannes Raschke (Gast)


Lesenswert?

Um das zu entscheiden, müßtest Du mal sagen, was genau passieren soll.

- soll der Pin dauerhaft eingeschaltet bleiben, auch wenn ein neues
Zeichen empfangen wurde?
- Wie oder wann soll wieder  abgeschaltet werden?

So wie es jetzt ist, bleibt PortB in dem Zustand, in den er zuletzt
gesetzt wurde.

Wenn der Relais-Kontakt einfach nur kurz klappern soll müßtest du eine
Wartefunktion aufrufen und danach wieder eine 0 auf den Port
schreiben.

Relais erzeugen übrigens gerne Störungen, die den Controller abstürzen
lassen. Über die Forumssuche findest Du Infos, wie das zu vemeiden ist.

von Johannes Raschke (Gast)


Lesenswert?

Habe erst jetzt Deinen Code gesehen... Warte doch erstmal 500msec -
verkürzen kann man die Zeit immer noch. Oder wie sehen Deine
Anforderungen aus?

von Mo. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Johannes,

habe eine Warteschleife eingebaut WAIT(); aber ich weiß nicht, wie
lange die reale Wartezeit ist. Das muss ich testen. Danke für den Tipp
mit dem Relais. Ist es besser eine Transistor-Schaltung zu nehmen. Muss
im Prinzip insgesamt 6 Schalter/Taster bedienen können. Wenn ich das
über einen Transistor laufen lasse, kann ich mir Entprellen (oder wie
das heißt) sparen?

Neuer Code im Anhang ;)

von josef (Gast)


Lesenswert?

UDR ist ein Register, dass du in der for-Schleife direkt abfragen
kannst. Das solltest du auch mal löschen. Du solltes dieses auch auf
ungleich 0 abfragen.
Würde aber besser eine Bit-Variable bei jedem UART-Interrupt setzen und
nach Auswertung des empfangenen Zeichens diese Variable wieder löschen.
So kannst du auch die 0 auswerten. Geht ntürlich auch über das UART-RI
Bit.


SG Josef

von josef (Gast)


Lesenswert?

@ Johannes: Das löschen des PORTB bringt nichts, da niemand das
data_received Byte löscht.

von Dirk (Gast)


Lesenswert?

Hi,

es ist eben die Frage ob deine Ausgaenge galvanisch getrennt sein
muessen, wenn nicht reichen Transistoren oder Mosfets aus.

Vielleicht reichen aber auch Optocoupler mit Open Collector.

Mfg
Dirk

von Johannes Raschke (Gast)


Lesenswert?

@Josef: Hm, bei Assembler wird das RXC - BIT doch automatisch beim
Abholen des Zeichens gelöscht - bei C nicht? Wie war das doch
gleich...
Ich sehe gerade, ein UCSRA gibt es beim 2313 ebensowenig wie einen
USART. Vielleicht einfach nochmal ins Wiki gucken...
Ich würde das USR auf RXC prüfen. Wenn was gesetzt ist, UDR auslesen
und auswerten.

Transistoren gehen je nach Spannung ohne Probleme - bei AC klappt das
nicht. Du hast noch nicht geschrieben, was Du überhaubt machen willst.

von Johannes Raschke (Gast)


Lesenswert?

In ASM sieht das dann so aus:

loop:   in temp, USR
        sbrs temp, RXC  ;Daten empfangen -> Sprung nach loop
überspringen
        rjmp loop
        in temp, UDR
        rcall serout    ; echo (das Zeichen in Temp ausgeben)

anschließend in Abhängigkeit von temp was Tolles anstellen.

von Mo. (Gast)


Lesenswert?

@Dirk: Ich denke nicht, dass sie galvanisch getrennt sein müssen. Es
erfolgt ja lediglich nur eine Ausgabe gleichzeitig.

@ Josef: received_data wird doch immer "neu" gefüllt, d.h. man müsste
es eigentlich nicht löschen, oder? Falls doch, würde dann ein
received_data = ""; reichen?

von Dirk (Gast)


Lesenswert?

Hi,

naja vielleicht reicht dir ja der Logikpegel (5V/20mA)

ich wuerde die Daten anders loeschen ....

#define clear      0x00

received_data = clear;

von Mo. (Gast)


Lesenswert?

@ Johannes: Du hast Recht. USART kann ich vergessen. Leider finde ich im
Wiki nichts mehr darüber. Das einzige, was ich noch gemacht habe, dass
ich am Ende received_data = CLEAR; gesetzt habe (CLEAR ist zuvor mit
0x00 definiert).

Tja und nun stecke ich richtig fest!!!

von Dirk (Gast)


Lesenswert?

Hi,

die richtigen Registernamen solltest du im Datasheet finden.
Suchbegriff: UART .... bei den neueren AVR's heisst es USART.

Mfg
Dirk

von Johannes Raschke (Gast)


Lesenswert?

Wenn Du sowieso wartest, bis ein neues Zeichen da ist, brauchst Du IIRC
nichts löschen.
USART gibt's nicht, dafür den UART. Genau dieser wird auch im Wiki
beschrieben, und mehr brauchst Du ja auch nicht.
Wo ist denn jetzt jenau das Problem? Du brauchst im Prinzip nur noch
das, was  ich Dir beschrieben und in Assembler gepostet habe in C
umzusetzen. Wenn ich es richig sehe, mußt Du dazu lediglich UCSRA durch
USR ersetzen.
Die UART - Initialisierung wirst Du ja auch wohl irgendwo finden.
Am besten nicht nur irgendwoher kopieren, sondern auch mal ins
Datenblatt gucken und versuchen, etwas zu verstehen.
"Galvanisch getrennt" bedeutet übrigens, daß der Stromkreis vom
Controller und der von dem, was Du schalten willst, keinerlei
elektrische Verbindung haben. Je nachdem, was Du ansteuern willst ist
das unabdingbar.

Gute Nacht

Johannes

von Mo. (Gast)


Lesenswert?

Danke Dirk & Johannes,

werde morgen weitermachen und dann von meinen Ergebnissen berichten.

Gute Nacht,
Moritz

von Mo. (Gast)


Angehängte Dateien:

Lesenswert?

So,

habe es noch einmal abgeändert. Die UART-Initialisierung war wohl
korrekt, hatte nur USARD geschrieben und dann fälschlicherweise mit dem
"Begriff" weitergesucht ;)

Sollte es jetzt so gehen, oder wo ist noch Verbesserungsbedarf?

@ Johannes: Leider kann ich Deinen Assembler-Code nicht richtig
interpretieren. Ist schon in C relativ haarig für mich.

Zur Schaltung: Geschaltet werden sollen (zur Zeit noch SMD) Taster, die
ich gänzlich ersetzen möchte. Dabei läuft die externe Schaltung mit
3,9V. D.h. es ist besser, wenn ich die beiden Schaltkreise, die an sich
nichts miteinander zu tun haben, trenne. Ich denke, dass hier der von
Dirk empfohlene Optokoppler (hab mich auf elektronik-kompendium
informiert) eine gute Wahl ist ;)

von Johannes Raschke (Gast)


Lesenswert?

Bis auf die Tippfehler (|= und UARD_RECEIVE();) sieht das nach meinem
Verständnis gut aus. Compiliere das Programm doch mal und lade es in
Deinem Atmel oder Simulator!

Johannes

von Sebastian (Gast)


Lesenswert?

Hallo,

im include hast Du noch arv/io.h statt avr/io.h stehen, ist mir spontan
aufgefallen.

In der Wait-Schleife: time und x sind unsigned char, haben also einen
max. Wert von 256. WAIT(500) ist also nicht möglich/macht nicht das,
was Du erreichen willst.

Bei 4Mhz Takt braucht ein Befehl 250ns, damit kannst Du abschätzen, wie
lang der Ausgang geschaltet bleibt->sehr kurz! Ohne zu wissen, wieviele
asm-Befehle eine For-Schleife braucht (4?) würd ich schätzen, dass
Deine Wartezeit im us-Bereich liegt. Ob das reicht, musst Du selber
wissen.

Was passiert, wenn jd. einen Taster an a) dauerhaft drückt? Sendet der
uC1 dann immer wieder z. B. 0xC1...0xC1...0xC1 Oder nur 1x? Im ersteren
Fall macht Dein Programm aus einem Dauerhaft gedrückten Taster ein
AN........AUS.AN..........AUS.AN..........AUS.AN.......usw.

Ob das, was ich hier erzähle, in Deiner Schaltung relevant ist, musst
Du selber wissen.

Ich würds mal ausprobieren.

Gruß,
Sebastian

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
Noch kein Account? Hier anmelden.