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)
>> 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
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.
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.
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.......)
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! (-:
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
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............
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.
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......
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.