Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie können zwei µC miteinander komunizieren
HannoHupmann
30.03.2010, 13:18
Hallo,
aufbauend auf meinem Thread der sich mit µC mit mehr als 50 Ports beschäftigt bin ich nun dazu übergegangen eine Lösung zu suchen, wie ich mehrere µController (genauer mega32) miteinander Komunizieren lassen kann.
Das Bussystem ist mir dabei fast egal, wobei ich i2c favorisiere. Leider ist es mit meinen Programmierkenntnissen nicht so gut bestellt wie bei der Mechanik. Daher brauch ich jetzt eure Hilfe:
Ich suche einen möglichst einfachen Code (so einfach, dass auch ich ihn verstehe) mit dem ich oben genannte Komunikation realisieren kann.
Das TWI Tutorial im avr-gcc RN Wissen hat mir leider nicht wirklich weiter geholfen, den ich bekomm es nicht hin, bzw. ich versteh es nicht (wie es funktionieren sollte schon, nur den Code nicht!). Ich bekomm beim I2C Slave immer Fehler beim Compilieren und weis nicht was die Lösung ist.
Wenn also jemand eine einfachere Lösung die auch funktioniert wäre ich sehr dankbar. Auch Erfahrungen mit anderen Bussystemen die Funktionieren sind hilfreich.
Verständlicherweise helfen mir Vorschläge wie: "Einfach über I2C oder über CAN verbinden" nicht weiter, da es bei der konkreten Umsetzung in C-Code hapert.
ich hoffe inständig auf eure Hilfe weil davon meine weiteren Projekte abhängen :(
Grüße
Hanno
nechegris
30.03.2010, 14:05
Hallo,
ich bin in dieser Sache auch gerade am Experimentieren, leider bisher ohne Erfolg. :(
Ich werden den Thread mit Spannung verfolgen, und sofort Meldung geben, wenn sich bei mir was tut. :cheesy:
Hi,
am allereinfachsten ist's eigentlich über die UART.
Hardwaremässig muss man nur TxD von Prozessor A mit RxD von Prozessor B verbinden und umgekehrt.
Softwaremässig ist das auch recht einfach zu realisieren. Wenn interesse besteht, bastel ich mal einen Beispielcode zusammen. Allerdings steht auch im RN Wissen einiges an Code dazu drin: http://www.rn-wissen.de/index.php/UART_mit_avr-gcc
Gruß,
askazo
TWI-Master Routinen kann ich hier gerne posten. Bei den Slave wirds dann aber etwas schwieriger. Es kommt auf deine Anwendung an, wie der Code empfangen/zwischengespeichert/gesendet wird. Außerdem kommt es darauf an, ob der Master nur senden, oder auch empfangen können soll.
Wenn du deine Anwendung beschreibst, könnt ich dir sicherlich bei der Erstellung eines Protokolls helfen, was geeignet ist.
Hier schonmal der TWI-Master code
Header-Datei:
#include <avr/io.h>
#define READ 1
#define WRITE 0
#define TWI_READY (TWCR & (1<<TWINT))
void TWIInit(void);
void TWIStart(uint8_t addr, uint8_t RW);
void TWIStop(void);
//Byte senden
uint8_t TWIWrite(uint8_t data );
//Byte empfangen
uint8_t TWIReadAck(void);
//letztes zu empfangendes Byte empfangen
uint8_t TWIReadNack(void);
.c Datei:
void TWIInit(void){
PORTC |= 0x03; //PULLUP Widerstaende (für ATmega32 geeignet)
TWBR = 0xFF;
}
void TWIStart(uint8_t addr, uint8_t RW){
uint8_t temp = 1;
while(temp == 1){
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //START
while(!TWI_READY);
if(TWSR == 0x00) {TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);}
if(TWSR != 0x08 && TWSR != 0x10) {continue;}
TWDR = addr + RW;//LCD_BOARD_ADR; //send ADR+W
TWCR = (1<<TWINT) | (1<<TWEN);
while(!TWI_READY);
if(TWSR == 0x00) {TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);}
if(TWSR != 0x18 && TWSR != 0x40) {continue;}
temp = 0;
}
}
void TWIStop(void){
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
while(TWCR & (1<<TWSTO));
}
//Byte senden
uint8_t TWIWrite(uint8_t data ){
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!TWI_READY);
if(TWSR != 0x28){return 1;}
return 0;
}
//Byte empfangen
uint8_t TWIReadAck(void){
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
while(!TWI_READY);
return TWDR;
}
//letztes zu empfangendes Byte empfangen
uint8_t TWIReadNack(void){
TWCR = (1<<TWINT) | (1<<TWEN);
while(!TWI_READY);
return TWDR;
}
Auf einem ATmega32 hab ich den Code noch nicht getestet, allerdings sollte das keine Probleme machen.
Zuerst muss eine Start-Anweisung ausgeführt werden, die dem Slave sagt, was zutun ist. READ: Master liest, WRITE: Master schreibt.
Wenn Master schreibt, dann musst du die TWIWrite Funktion verwenden, um ein Byte zu senden. Wenn er liest, dann musst du die TWIReadAck Funktion verwenden, um Bytes zu lesen (außer das letzte Byte), für das letzte Byte verwendest du die TWIReadNack Funktion.
Am Ende kommt eine stop-Anweisung.
Wenn du einfach nur etwas an den Slave senden möchtest und nichts zurück erwartest, würde ich dir aber eher den SPI-Bus empfehlen, er ist deutlich schneller und für diesen Zweck am einfachsten zu programmieren.
Gruß, Yaro
Hallo ihr beiden,
zuerst einmal die Hardwareseite: Da der Bus ja in beide Richtungen geht, kann niemand die Leitung auf "High" ziehen, ohne zu riskieren dass sein Ausgang abraucht weil der Gegenüber gerade beschlossen hat, "Low" ausgeben zu wollen. Daher werden die beiden Leitungen SDA (Daten) und SCL (Takt) über einen Pullup von ~10kOhm (je nach Anwendung/Geschwindigkeit/Leitungslänge) auf "High" gezogen.
Die Kommunikationspartner ziehen die Leitung also nur noch auf "Low", der "High"-Pegel stellt sich von alleine wieder ein.
Dann die Softwareseite: Ich denke am sinnvollsten wäre es, einmal das Kapitel zum TWI im Datenblatt durchzulesen, evtl. noch die I2C-Spezifikation (auch wenn das im Datenblatt eigentlich schon ausreichend abgehandelt wird).
Informationen (und die aktuelle Bus-Spezifikation) findet ihr unter http://www.i2c-bus.org/
mfG
Markus
Mit uart ist es nur mit ziemlichen Krampf möglich mehrere Prozessoren
zu verbinden. Da muss man dann dafür sorgen (Protokoll) das immer
nur der eine Antwortet da adressiert war. Also letztendlich schwieriger
als I²C. Dafür klappt i²C eher nur über kurze Leitungswege. :-(
RS 485 kann gut 1200 m, CAN in etwa auch bei 485 muß man aber
auch das Protokoll selber schreiben (entwickeln) und braucht bei
voll Dublex 4 Daten Leitrungen. Beim CAN - Bus gibt es ein Protokoll,
das ist aber extrem aufwändig und braucht da eher spezielle Harware
und ODER nen AVR mit intregierten CAN Interface.....
Bei kurzen Verbindungen ist also I²C die einfachste und beste Methode,
leider kann ich kein c und in Bascom sieht das recht einfach aus. Ich
habe vor ca 20 Jahren einmal i²c auf einem PIC in Assemler selber
geschrieben, sehr schwer war das nicht. Die Start,senden, empfangen,
Stopp Signale sind ja sehr einfach und gut beschrieben.
Aber ich vermute stark das sich auch für C Bibliotheken finden lassen
in denen i²c schon wie in Bascom "vorgekaut" enthalten sind. :-)
Gruß Richard
HannoHupmann
30.03.2010, 16:40
@yaro das sieht zumindest für mich schon mal verständlicher aus als der Code im Wiki.
@markusj die Spezifikation von einem I2C Bus ist nicht meine Sorge, ich weis genau wie der funktioniert und wann wo welche Leitung auf High für wie lange gelegt werden muss. Mein Problem ist, dass ich dieses Wissen nicht in einen C-Code verwandeln kann.
@Richard deswegen auf I2C und kein Uart bei meinem ersten Versuch. Ich versuch gerade entsprechende Programme bzw. Bibliotheken zu finden aber komm nicht weiter.
Im Prinzip such ich ein Programm das beim Master einen Tastendruck einliest und beim Slave ne LED angehen lässt und umgekehrt. Anhand so eines Beispielprogramms könnte ich vermutlich alle anderen Funktionen extrapolieren. Ich fände es nur etwas zu dreist jemanden um so etwas zu bitten.
Versuche es einmal bei http://openpdf.com/ebook/gcc-i2c-avr-pdf.html
Der 4..5...Eintrag?
Gruß Richard
So schwer ist das auch nicht, sich ein passendes UART-Protokoll zu basteln. (im einfachsten Fall 1.Byte = Adresse, 2.Byte = Daten). Das Senden und Empfangen geht über eine simple State Machine.
Aber ich merke schon, gegen die I2C-Fraktion habe ich keine Chance ;)
Gruß,
askazo
So schwer ist das auch nicht, sich ein passendes UART-Protokoll zu basteln. (im einfachsten Fall 1.Byte = Adresse, 2.Byte = Daten). Das Senden und Empfangen geht über eine simple State Machine.
Aber ich merke schon, gegen die I2C-Fraktion habe ich keine Chance ;)
Gruß,
askazo
Stimmt, aber für i²c gibt es deutlich mehr Hardware wie Sensoren,
Uhren, eeproms.........dafür jedes mal eigne Hardware und ein eigenes
Protokoll zurecht fummeln ist echt mühsam. :-)
Gruß Richard
Wenn es dir nur darum geht, ein einfaches Beispielprogramm zu schreiben, dann braucht man dabei nicht allzuviele C-Kentnisse.
Als Sender kannst du ja die geposteten Routinen verwenden.
Als Empfänger schaltest du am Besten den TWI-Interrupt an. Dieser wird aufgerufen, wenn ein TWI-Ereignis aufgetreten ist. Dann wertest du in diesem Interrupt den Ereigniscode aus (im TWSR) und entscheidest, was getan werden soll (Was getan werden kann, steht im Datenblatt, da gibts ganze Tabellen für die Fehlercodes). Das gute an TWI ist, dass der Slave die SCL-Leitung solange auf LOW hält, bis er fertig ist, was dazu führt, dass der Interrupt nicht unbedingt besonders schnell ausgeführt werden muss.
Im Grunde genommen kann man den Interrupt fast ausschließlich mit if-else Anweisungen schreiben. Übersichtlicher wird es mit einer switch-Anweisung.
Schreib doch mal auf, wie dein Empfänger auf die einzelnen Ereignisse reagieren soll. Wenn du das nicht schaffst, in C-code zu übersetzten, helfen wir dir auf die Sprünge.
Gruß, Yaro
HannoHupmann
30.03.2010, 22:21
@yaro genau soviel zur Theorie, das bekomm ich auch immer hin ich kann mir alles genau vorstellen wie das funktionieren muss. ABER ich
kann das nicht in C Schreiben. Ich kann die Syntax nicht, ich weis die Kommandos nicht! Es scheitern nicht daran, dass ich nicht weis wie es funktioniert sondern daran dass ich kaum und nur sehr sehr rudimentäre C Kenntnisse diesbezüglich hab.
Ich weis zwar was dein Beispielprogramm macht, aber nicht wie. Hoffentlich wird nun deutlicher wo mein Problem liegt.
Mehr als Lampe An, Lampe AUS bische if than else hab ich einfach noch nicht mit nem Mega32 in C gemacht und ich muss gestehen, es macht mir auch keine Freude, aber da meine Projekte nun mal zu komplex für einen µC werden muss irgendwie mehr Leistung und Ports bekommen.
HannoHupmann
30.03.2010, 22:29
Ist es vielleicht der falsche Weg für mich es in C zu machen und ich sollte es in einer anderen Sprache machen? Ich mein mit Bascom hab ich bisher noch weniger gearbeitet.
RP6conrad
30.03.2010, 22:35
Den RP6 hat eine functionierende code für Master - Slave ueber I2C, beide Mega32. Das ist in C geschrieben und auch gut documentiert. Kan men downloaden bei www.arexx.com. Diese code wird verwendet beim RP6 basis + erweiterungsplatine M32. Die basis ist dan der Slave und M32 der Master. Da gibt auch eine schone pdf manual dazu. Aber du muss naturlich sich ein bischen einarbeiten in C.
Hanno, ich glaube nicht.
Du hast zwei Optionen:
1. Du nimmst eine fertige Bibliothek und beschränkst dich auf die Verwendung dieser (es gibt einige fertige Bibliotheken). Wenn du diesen Weg einschlägst, bekommst du sicherlich Hilfe wenn du die verwendete Bibliothek angibst.
2. Du schlägst den interessanteren aber schwereren Weg ein und versuchst das Protokoll selbst zu implementieren. Im Endeffekt besteht ein großteil der Ansteuerung nur darin, Bits zu setzen/löschen, Werte in Register zu schubsen oder aus Registern auszulesen und auszwerten.
Die größte Schwierigkeit ist nicht, das ganze in C zu "gießen". Die größte Schwierigkeit besteht vermutlich eher in der berücksichtigung der Feinheiten des Protokolls. Und wenn du auf die Implementierung von Corner-Cases wie Multi-Master verzichtest, sollte das relativ einfach sein.
mfG
Markus
Wenn du wirklich noch relativ unsicher beim Programmieren bist und nicht vor hast, allzuviel daran zu arbeiten, würde ich dir eher Basic vorschlagen, da gibt es viele vorgefärtigte Routinen, mit denen man schnell kleine Projekte zusammenbauen kann.
Ich würde aber empfehlen, sich einfach ein bisschen mit C auseinanderzusetzen, sich ein Buch zu holen und es durchzuarbeiten, dann macht das alles auch gleich viel mehr Spass!
Ich hatte als allererstes Projekt einen Asuro zusammengebaut, konnte aber kaum programmieren und habe gleich den Spass daran verloren, bis ich mir ein Programmierbuch geholt und es durchgearbeitet habe, danach war auf einmal alles viel einfacher, als ich es geglaubt hatte.
Gruß, Yaro
HannoHupmann
05.04.2010, 20:02
Zusammen mit uwegw habe ich den TWI Artikel im Wiki getestet und soweit korrigiert und abgeändert, dass er nun funktioniert. Sollte jetzt also für alle die das gleiche Problem haben kein Problem mehr sein. Code funktioniert bei mir jetzt ohne Probleme und ich kann das nächste Code-Problem angehen: wie steuer ich dieses DMF6104N Optrex Display hier an?
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.