Forum: Mikrocontroller und Digitale Elektronik mindestens 3 UARTs


von Sebastian Wille (Gast)


Lesenswert?

Hi,

ich benötige mindestens 3 UARTs (also normale serielle Schnittstellen) 
an meinem AVR (4433). Ich möchte, wenn's irgendwie geht, nicht einen 
"großen" AVR mit 2 UARTs verwenden. Gibt es da nicht auch eine Lösung 
per I2C?

Danke!

Sebastian

von Markus (Gast)


Lesenswert?

Was willst Du denn damit mache? Welche Datenrate brauchst Du denn?

von Sebastian Wille (Gast)


Lesenswert?

Hi Markus,

also 9600 Baud wären super!

Folgende Geräte müssen ran:
   - Handy (dient als Modem)
   - GPS-Gerät
   - PC
   - anderer AVR (eventuell)

Hast Du Ideen?

Danke!

Sebastian

von Markus (Gast)


Lesenswert?

Hm, also der 4433 hat ja einen Hardware UART. Bei Atmel gibt es eine 
AppNote für einen Software UART. Vielleicht kann man das ja irgendwie 
verdoppeln

von Christian (Gast)


Lesenswert?

Hallo
dein GPS Gerät sendet ja vermutlich nur jede sek. mal kurz - du könntest 
versuchen mit Transistoren eine Schaltung aufzubauen, die zwischen dem 
einem Gerät (gps) und dem anderen (PC) hin und herschalten kann - die 
Schaltung wird einfach durch einen Portpin gesteuert - dazu musst du 
natürlich wissen wann wer was sendet - beim GPS kannst du ja versuchen 
die Zeit zu messen oder aber du hängst die TX Leitung vom GPS an einen 
externen Interrupt - vielleicht geht das schnell genug.
2. Mgl.:
du verbindest den 2. AVR via SPI oder Parallel mit dem anderem und nutzt 
einfach dessen UART

3. Mgl.:
SoftUart

Viel Erfolg!!!!

von Sebastian Wille (Gast)


Lesenswert?

Hallo Christian,

danke für die Antwort! :-)

Wenn ich zwei AVRs per SPI verbinde, wie muß ich das dann (in Assmbler) 
programmieren? Und was heißt parallel?

SoftUART klingt sehr interessant! Wie genau soll das funktionieren? Wie 
lässt sich das (in Assembler) programmieren? Da habe ich aber keine 
Interrupts, oder?

Danke! :-)

Sebastian

von Christian (Gast)


Lesenswert?

Hallo,

tut mir leid aber ich habe fast keine Ahnung von Assembler für AVR - 
such doch mal im Netz da wirst du mit Sicherhiet fündig!!!

Mit Parallel hab' ich gemeint, dass du ähnlich wie bei einem Display 
beispielsweise jeweils einen ganzne Port deiner AVR's miteinander 
verbindest und dann noch ein paar pins zur Steuerung einsetzt 
(senden/empfnagen/aktiv......)
Ich denke schon dass du einen Empfangsinterupt verwenden kannst - nimm 
halt einen externen interrupt - wenn der hochgeht dann spring schnell in 
deine Empfangsroutine. Beim senden gibts natürlich keinen interrupt.....

mfg

Christian

von Andreas H (Gast)


Lesenswert?

Hallo Sebastian!

Ich bin gerade dabei, 2 AVR (AT90S8515)per SPI miteinander kommunizieren 
zu lassen. Wenn man es einmal gebacken gekriegt hat, ist es gar nicht so 
schwer... :)

Bei meiner Methode läuft das im Polling, da ich (noch) keine 
Zeitkritischen Abläufe habe und zwischendurch nix anderes machen muß. 
Eleganter wäre es sicher per Interrupt...

So funktioniert es programmtechnisch (bei mir):

1. Ein AVR muß als Master koviguriert werden, der andere als Slave. das 
geschieht über das SPCR (SPI-Control-Register). In diesem register 
stellt man auch noch ne ganze Menge anderer Sachen ein, wie: 
Taktfrequenz, Interrupt en-/dis-able, Phasenlage, etc.

2. Pro Durchgang wird ein Byte zwischen Master und Slave "getauscht". Du 
schreibst also ein Byte in das SPDR (SPI-Data-Register) des Slaves. 
Dieser Wartet dann einfach. (SPI muß natürlich enabled sein, das kann 
mit Schritt 1 zusammen machen, da gleiches Control-Register). 
Theoretisch kannst Du während des Wartens auch was anderes machen, kommt 
bei mir aber nicht vor. Achso, wichtig ist noch, daß der Eingang /SS am 
Slave-µC auf low gehalten wird, sonst is nix mit SPI...

3. Beim Master wird ebenfalls das SPI enabled (geschieht bei mir mit 
Schritt 1 zusammen) und anschließend in das SPDR-Register das zu 
übertragende Byte geschrieben. das schreiben des zu übertragenden Bytes 
startet automatisch die Hardware SPI. Nun kann man auch hier entweder 
abwarten (Schleife) oder was anderes machen.

4. Die Hardware überträgt jetzt im Hintergrund mit der in Schritt 1 
eingestellten Geschwindigkeit. Nachdem die Übertragung zu Ende ist, wird 
entweder ein Interrupt aufgerufen (wenn enabled) oder man kann das 
Status-Bit im SPSR (Status-Register) abrufen um zu prüfen, ob die 
Übertragung fertig ist. Letztere Methode benutze ich beim Warten, um zu 
prüfen, ob die Übertragung fertig ist.

5. Wenn alles erledigt ist, hast Du im Master SPDR (Data-Register)das 
Byte, welches vorher im Slave war, und im Slave jenes aus dem Master. 
Die Bytes wurden also in einem Rutsch zwischen master und Slave 
getauscht.

Hier ist meine Subroutine des Slaves. Wird sie aufgerufen, wartet sie 
eine gewisse Zeit lang darauf, daß der Master sendet. Sendet er nicht 
bis die Warteschleife abgelaufen ist, wird zu "Carderror" verzweigt. In 
dem Register "tosend" muß beim Aufrufen das Byte stehen, welches der 
Master bekommen soll. Nach der Übertragung und Beendigung der Subroutine 
steht im Register "recvd" das Byte, welches vom Master kommt. Klingt 
alles ganz kompliziert, ist aber ganz einfach:

; *************************  SPI Slave Routine  ************************

spislave:
        ldi temp, 0b01001001  ; SPI enable, Interrupt disable, Slave, 
Clock= f/16
    out SPCR, temp      ; Init-werte ins SPI-Control-Register
    out SPDR, tosend    ; das Byte für den Master bereit stellen
    ldi r17, $FF

waitSPI1:            ; **** warten, bis die Daten übertragen wurden
    dec r17          ; Zähler einen erniedrigen
    breq carderror      ; wenn zulange gedauert hat, dann fehler
    in temp, SPSR      ; Hole werte vom SPI Status Register
    sbrs temp, 7      ; Wenn SPIF gesetzt (=Übertragung Ende), dann...
    rjmp waitSPI1      ; ...verlasse schleife, sonst nochmal

    in recvd, SPDR      ; Byte vom SPI in "recvd" speichern
    ldi temp, 0b00001001  ; SPI disable
    out SPCR, temp      ; ->

  ret

; **********

(sorry, daß die Formatierung beim Posten verloren gehen... ich hoffe, 
man kann es lesen)

Hardware-technisch habe ich hierbei die SPI-Pins 
"Mosi(PB5)"/"Miso(PB6)"/"SCK(PB7)" beider µCs 1zu1 miteinander 
verbunden, Pin "/SS(PB4)" liegt auf Masse (wichtig!).

Der Code des Masters sieht genauso aus, nur ist hier die erste Zeile 
etwas anders, damit das Ding als Master arbeitet. Außerdem entfällt die 
Verzweigung zur Fehlerroutine, wenns zu lange dauert.

        ldi temp, 0b01011001  ; SPI enable, Interrupt disable, Master, 
Clock= f/16


So, ich hoffe, ich konnte die SPI-Geschichte etwas erklären. Keine 
Haftung/Garantie für Richtigkeit und Vollständigkeit ;)

ciao,
Andi

von Sebastian Wille (Gast)


Lesenswert?

Hi Andreas,

danke für die super Erklärung! :-)

Ich werde es in den nächsten Tagen mal nachbauen.

Sehe ich das mit SoftUART richtig: Ich definiere einfach zwei Ports als 
TX und RX und bastle mir dann mein Byte zusammen?

Danke! :-)

Sebastian

von XCyber (Gast)


Lesenswert?

Bei Maxim gibt es UART-Bausteine die an die SPI Schnittstelle 
angeschlossen werden können. Ich denke das würde für dein Vorhaben ideal 
sein.
Infos unter http://www.maxim-ic.com/quick_view2.cfm?qv_pk=1731

lG
XCyber

von Sebastian Wille (Gast)


Lesenswert?

Hi XCyber,

danke für den Tip, klingt super!

Die Frage ist nur, wie man die SPI-Schnittstelle ansteuert.

Was ist eigentlich der Unterschied zwischen SPI und UART? Mein C-Control 
habe ich immer per serielle Schnittstelle programmiert, deswegen ist SPI 
für mich neu.

Danke! :-)

Sebastian

von XCyber (Gast)


Lesenswert?

Wie du mit der SPI-Schnittstelle umgehst steht recht genau in den Atmel 
Datenblättern der einzelenen Prozessoren.

lG
XCyber

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.