Forum: Mikrocontroller und Digitale Elektronik PICs mit 2-Drahtleitung verbinden???????


von Tobias Möhring (Gast)


Lesenswert?

Hallo!

Ich bin auf der Suche nach einer Möglichkeit mehrere PICs mit einer
2-Drahtleitung zu verbinden und Daten austauschen zu lassen.

Ich denke mir das so, das einer als Master läuft und in der Lage ist
eine allgemeine Anfrage zu starten, woraufhin sich die anderen (ich
denk da erstmal an 3 Stück) mit ihrer Kennung (also da reicht mir echt
einfach durchnummeriert) melden.
Dabei möchte ich dann noch mit dem Master eine LED ansteuern, die
anzeigt das er gesendet hat und für jeden PIC eine, die anzeigt, das
sich der PIC gemeldet hat (aber das mit den LEDs soll ja erstmal nur
sein, damit ich was sehe und das bekomme ich auch noch hin).

Wenn das erledigt ist möchte ich den Master durch drücken eines Tasters
dazu bewegen eine Anfrage an den Slave zu senden, zu dem der Taster
gehört, den ich gedrückt habe (also der Taster soll am Master sitzen
und eine Anfrage an einen bestimmten Slave auslösen (bedeutet 3 Taster
für 3 Slave))

Scheint mir, als wäre das eine gute Aufgabe für einen I2C-BUS, aber
leider habe ich noch nirgends Infos darüber gefunden, wie ich so einen
BUS aufbaue und die Sende- und Empfangsroutine programmiere.
Ich kann mir nämlich grad gar nicht vorstellen, wie man sowas
aufsetzt.......

Wäre also schön, wenn mir das jemand erklären könnte, oder noch besser
einen Link zu einer Page hat, wo das erklärt ist oder für die Sende und
Empfangsroutine sogar ein Quellcode steht (irgendwer muß sowas ja
schonmal gemacht haben)

von leo9 (Gast)


Lesenswert?

>> Scheint mir, als wäre das eine gute Aufgabe für einen I2C-BUS

hat aber nur den Anschein, I2c braucht eine 3-Drahtleitung (Clk, Data
und Ground). google mal nach RS485, das sollt sich eine Lösung finden.

grüsse leo9

von KoF (Gast)


Lesenswert?

hmm sonst die uarts.

->master sendet befehl an slave,

->slave stellt fest, ob befehl für ihn ist.
 ->wenn ja
   befehl abarbeiten
 ->wenn nein
   befehl über 2.uart zum nächsten slave schicken.
   (dieser prüft dann erneut, ob er gemeint ist)

also pracktisch als kette.

von Philipp Sªsse (Gast)


Lesenswert?

2-Draht mit oder ohne Ground? Wenn insgesamt zwei, dann scheiden I2C und
RS-232 aus. Wenn Du auch noch ohne Treiberbaustein auskommen willst,
bleibt nur noch etwas 1-wire-Bus-artiges: eine Masseleitung und eine
Datenleitung, die von einem Widerstand auf ein Potential Deiner Wahl
gezogen wird und die Master und Client kippen dürfen.

1. Voraussetzung ist Kollisionsfreiheit, d.h. der Master darf keine
allgemeine Anfrage machen, sonst quasseln danach alle durcheinander.
Sondern: Master teilt seinen Kram mit, fragt dann, ob A etwas zu sagen
hat; wenn der schweigt oder mit seinem Kram fertig ist, gibt der Master
Client B die Chance usw.

2. Voraussetzung ist Gleichtakt. Je nach Voraussetzungen (kennt man die
Clients vorher, haben die halbwegs kalibrierte Quarze, ist die
Leitungsqualität bekannt?) kann man einen Takt vorgeben oder
Synchronisationsimpulse einbauen. Variante 1 hat (wie der 1-wire-Bus)
den Nachteil, daß man das Timing für alle Fälle großzügig auslegen muß,
es dann aber bei heftigen Störungen doch zu schnell sein kann. Variante
hat immer einen gewissen Overhead, da jedes Datenpaket einen Testimpuls
braucht, an dem die Zuhörer sich orientieren können. Je nachdem kann es
sogar besser sein, mit einem eineinhalbfachen Impuls zu starten (drei
Flanken), damit die Zuhörer sich auch auf unterschiedliche Laufzeiten
von positiven und negativen Flanken einrichten können.

von Tobias Möhring (Gast)


Lesenswert?

Ich habe insgesamt 2 Drähte. Werde also einen für Masse und einen für
den Datenstrom benutzen, denk ich. Mehr ist leider nicht zu
realisieren.

Dafür kann ich die PICs alle mit bekannten Oszillatoren ausstatten. Das
ist mir also freigestellt.

Wie sieht denn das aus, was ist wenn ich eine bekannte Sequenz (z.B. 11
high 3 low 10 high) sende und dann den Empfänger daraus die Taktzeit des
Senders im Verhältniss zur eigenen errechnen lasse? wie könnte ich davon
gebrauch machen um die richtig zu syncronisieren oder wie auch immer
dazu zu bringen, das sie ihre Daten korrekt austauschen (also
hauptsächlich in die richtige Bitfolge zerlegen was sie bekommen, weil
beim Senden dürfte das dann ja egal sein.......)

von Philipp Sªsse (Gast)


Lesenswert?

Sei der Bus idle mal o.B.d.A. (-; low.

Dann macht der Sender:

Bus high
Warte x µs
Bus low
Für jedes Bit:
  Warte x µs
  Bus gemäß Bit

Und der Hörer (hat die Leitung als Interrupt, solange idle):

Beim ersten Interupt:
  internen Zähler starten
  Interrupt auf fallende Flanke
Beim zweiten Interrupt:
  internen Zähler ablesen, Differenz als Taktlänge speichern
  internen Zähler auf 1,5 x Taktlänge setzen
  runterzählen lassen und Interrupt bei Null
Bei weiteren Interrupts (durch Zähler ausgelöst!):
  Bit vom Bus lesen
  wenn noch nicht letztes Bit:
    Zähler auf Taktlänge setzen
    runterzählen lassen und Interrupt bei Null
  wenn letztes Bit:
    Interrupt wieder auf steigende Flanke setzen


Damit wird immer in der Mitte des Bits ausgelesen und
Timingunterschiede spielen keine Rolle (zu lange sollte die Bitfolge
dahinter natürlich auch nicht werden, sonst können sich Rundungsfehler
addieren oder sonstige Tätigkeiten der Controller Sender und Empfänger
außer Takt bringen.

Timeout-Konditionen mußt Du Dir auch noch ausdenken, damit der
Empfänger nicht in einem "schlimmen" Zustand hängen bleiben kann.

Protokoll, Prüfsummen und Handshake nach belieben draufsetzen.

Die aufwendigere Variante kannst Du Dir selbst überlegen. Wenn der
Sender schickt:

_____|'''|___|'''XXXXXXX

und der Client empfängt (durch Asymmetrie in der Leitung; Flanken
werden unterschiedlich schnell übertragen):

_____|''''|__|''''XXXXXXX

Muß er halt (im Wissen, daß der Sender es mit gleichen Pulslängen
geschickt hat) den Abschaltzeitpunkt ausrechnen, so daß er in jedem
Fall möglichst weit von allen Flanken abtastet.


Noch fortgeschrittener: dreifache Überabtastung. Dadurch kann auch
während der Übertragung an jedem Flankenwechsel nachsynchronisiert
werden.


Ach, ich bekomme richtig Lust, einen Inter-µC Bus zu spezifizieren! (-:

von Dennis Brücke (Gast)


Lesenswert?

Nur mal so in die runde gehauen ;)

Vieleicht kann man ja das 1-Wire Protokoll von Maxim (Dallas)
implementieren ?!

1 Leitung für DATA
1 Leitung für GND

Gruß Dennis

von Tobias Möhring (Gast)


Lesenswert?

Aber für das Bit wegschreiben und Zähler wieder hoch setzen benötige ich
doch mehr als einen Takt?!?!?!?!

Wie lang soll ich denn dann ein Bit machen? 3 Takte? Ich glaub das
versteh ich nicht........

Und wie soll das mit dem Empfänger und dem Zähler gehen? Also ich
dachte immer der würde sich je Takt nur um eine Stelle ändern? Oder
geht dein Beispiel gerade davon aus, das ich die Bitlänge auf mehrere
Takte (z.B. 10) setze? dann versteh ich das glaub ich halbwegs, wenn es
auch in eine ganz andere Richtung geht, als ich bisher gedacht
habe............

von Philipp Sªsse (Gast)


Lesenswert?

Da habe ich mich wohl mißverständlich ausgedrückt: wenn ich da "Takt"
schreibe, meine ich den Bustakt, nicht den CPU-Takt. Der Bustakt sollte
dabei erheblich länger sein, eben z.B. 10 Takte, wie Du schreibst.

Wobei man bei einem so schnellen Bustakt dann eher nicht mit Interrupts
arbeiten würde beim Empfänger, denn die verbraten ja jeweils schon ein
paar Takte, dann wird das Timing nachher knapp. Außerdem: in so einem
Fall lohnt es sich ja gar nicht, zwischendurch etwas anderes zu tun!

Also, wenn Du den Bus so schnell machen willst, sieh noch eine
zusätzliche Flanke vor: die erste Flanke löst einen Interrupt aus (da
Interrupts auf vielen Architekturen eine undefinierte Verzögerung
haben, sollten wir diese Flanke nicht zum synchronisieren nehmen). Dann
warten wir untätig auf die zweite Flanke. Den Abstand zwischen zweiter
und dritter Flanke messen wir "von Hand".

Mal einen Versuch in Pseudoassembler:

Businterrupt:
  store reg3 <- 0         // Da wird das Byte reingeschrieben
  store reg4 <- 8         // Hier die empfangenen Bit gezählt
  set interrupt inactive  // Bzw. Timerinterrupt für Abbruch setzen
warte0:
  branch warte0, wenn Bus high

  store reg1 <- 0         // hier Takte als Referenz zählen
warte1:
  inc reg1
  branch warte1, wenn Bus low

  sub reg1 <- sub1 - XX   // Hier evtl. Taktausgleich
  copy reg2 <- reg1       // die Referenz wird jeweils abgezählt
  shift right reg2        // beim ersten Mal eineinhalbfach ...
  add reg2 <- reg1 + reg2 // ... damit in Pulsmitte getastet wird
warte2:
  dec reg2
  branch warte2, wenn reg2 nonzero

  branch nextBit, wenn Bus low  // Wenn der Bus high war ...
  inc reg3                // ... wird hier das Bit gesetzt
nextBit:
  shift left reg3         // Das erste Bit wird also MSB am Ende!
  copy reg2 <- reg1       // Zähler für nächste Runde setzen
  dec reg4
  branch warte2, wenn reg4 nonzero


Jetzt muß man noch die Ausführungstakte der einzelnen Blöcke zählen und
XX so wählen, daß die späteren Abtastintervalle genauso viele Takte
brauchen wie der Referenztakt.

Ich hoffe, das ist jetzt noch etwas klarer.

von Tobias möhring (Gast)


Lesenswert?

OK. Dann hab ich das glaub ich verstanden. Der Bustakt kann ruhig lang
sein also bis zu 200 CPU Takte kann ich mir glaub ich leisten....


Vielen Dank!

Aber eine Frage bleibt mir noch zum Reset des PICs, aber dazu mache ich
dann noch einen neuen Thread auf......

von Steffen (Gast)


Lesenswert?

Das einfachste bleibt trotzdem die UART zu verwenden. RXD und TXD kannst
Du problemlos verbinden. "Nachteil" dabei ist nur, dass der PIC seine
eigenen Daten empfängt.

Schau dir mal im Datenblatt die UART und den Multi-Prozessor Mode an.

Steffen

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.