Hallo, ich müsste 5 AVRs miteinander verbinden. Als Master dient ein ATMega128A mit 16Mhz externem Quarz Als Slaves gibt es 1 ATMega8 mit 1 Mhz interner Quarz 2 ATMega32 mit 1Mhz interner Quarz Hinzu kommt ein eDIPTFT70-ATP was 400khz I2C ebenfalls beherscht. In diesem ist auch ein ATMega128 verbaut. Eine kommunikation zwischen dem Master und Display habe ich schon. Wenn das Display Daten hat legt es einen PIN auf LOW und man liest die Daten aus zerlegt den String und hat seine Daten :) Wie aber funktioniert nun die Kommunikation? Das Display hat $DE (lesen) $Df (schreiben) als feste adressen. Die adressierung ist nicht das problem, vielmehr wie man die kommunikation aufbaut. Sagen wir Daten von Slave 1 müssen an Slave 2. Bisher habe ich immer nur daten vom Master an den Slave geschrieben, nie gelesen. Was ich nicht verstehe, wie lese ich die Daten vom Slave? Der Slave muss diese ja bereitstellen etc. und da verstehe ich es nicht mehr. Muss der master erst an den slave schreiben (ich brauche die daten xyz) dann arbeitet der Slave diesen befehl ab, tut die Daten "irgendwo" hin und dann redet der Master nochmal mit dem Slave mit "gib jetzt her die daten"? Wie sieht das dann in C aus? Ich danke euch schonmal.
Hallo, also ersteinmal die Grundlagen vom I2C-BUS Philips bzw. NXP genau lesen, wenns geht auch noch verstehen. Focus: Start-Bit ... Stop-Bit Re-Start und für Multimaster BUS-Arbitration. Immer der, der von anderen lesen oder schreiben will wird sozusagen der Master. Es ist ein multimaster system. Alle Devices die nicht gerade Master sein wollen sind Slaves und die Adresse, also Device-Adresse wird auf der Hardware ins Register geschrieben. Bei gleicher Adresse kommt dan ein Interrupt und das entsprechende Slave Device muss ganz schnell die Kommunikation mit einem ACK bestätigen. Danach können die Daten vom Master gelesen werden. Nun kann der Master über ein Stopbit die Kommunikation oder über ein NACK oder auch der Slave über ein NACK die Kommunikation beenden. Beim Master unterscheidet sich das ob er gerade lesen oder schreiben tut. Den wenn der Master ließt muss er ja das ACK oder NACK ausgeben. So weit mal nur das ganz Grobe. Weiteres Thema SCL erzwungene Clock Phase Verlängerung durch Slave. Gruß Sascha
Hi, danke schonmal. Also eine I2C Kommunikation mit dem Display habe ich schon hinbekommen. Auch habe ich es hinbekommen auf einem ATMega8 eine PWM mittels I2C zu steuern. Also der Master hat dem Slave gesagt PWM auf 100 und dann ging daa. Jedoch war es so das ich mit dem Master an den Slave eine "zahl" geschrieben habe und das war dann eben der PWM Wert. Das klappte perfekt. Nun ist aber der Fall das der Slave 3 PWMs hat. Dort muss ich dem Slave ja auch mitteilen welche PWM auf den Wert eingestellt wird der nun vom Master kommt. Nun könnte ich folgendes machen. 1001 oder 1100 senden und diese Zahl auf dem Slave zerlegen 1001 in 1 und 001 das wäre dann 1 für die PWM Nummer 001 der PWM Wert gleiches mit 2090 oder 1050 oder 3100 usw. Ok. Jetzt kommt aber noch dazu das der Slave einen DS18S20 und einen Fotowiderstand auswertet. Die Daten stehen dann im Slave in einer Variable. Wie nun komme ich vom Master da dran? Also wie sage ich dem Slave mit welche Daten der Master nun haben will? Danke euch.
Schau dir einfach mal das *Protokoll einer RTC oder eines kleinen EEProms an. Da werden Sklaven ausgelesen. *im Datenblatt
TWI mit einem AVR ist für alles außer einfachem Master-Slave-Verbindungen zu anderen Bausteinen problematisch. Nimm lieber SPI. Oliver
Rene H. schrieb: > 1001 oder 1100 senden und diese Zahl auf dem Slave zerlegen 1001 in 1 > und 001 das wäre dann 1 für die PWM Nummer 001 der PWM Wert gleiches mit > 2090 oder 1050 oder 3100 usw. Wenn du mir jetzt noch erklärst, wie du mit 1 Byte eine 16 Bit Zahl übertragen willst, dann sind wir fast dort. Ja. In dem Fall schreibst du eben 2 Bytes nacheinander zum Slave. Das erste Byte kann man als Kommando auffassen, das zweite als der zu schreibende Wert. Genausogut kann man eine Kommunikation nach dem Muster aufbauen: Erst mal schreibt der Master wovon oder wohin er lesen/schreiben will und dann kommt ein Reead oder Write hinten nach, mit dem dann der Wert übermittelt wird. Genauso wie du es im täglichen Leben auch machst. Wenn ein Slave nur einen Wert verwalten muss (1 Byte) dann ist alles klar. Denn dann gibt es keine Unterscheidungen. Mit dem Lesen ist alles klar was gelesen oder geschrieben werden soll. Gibt es mehrere Werte, dann muss halt mal irgendwer mitteilen welcher der 5 es sein soll.
Also für das Display habe ich folgenden Code:
1 | unsigned char SendDisplayData(char *buf) |
2 | {
|
3 | unsigned int len = strlen(buf); |
4 | unsigned char i, bcc, ret; |
5 | int daten = 0; |
6 | ret = i2c_start(DISPLAY_I2C_ADDR+I2C_WRITE); // set device address and write mode |
7 | if ( ret ) { |
8 | /* failed to issue start condition, possibly no device found */
|
9 | i2c_stop(); |
10 | /* do some error reporting.. led or whatever */
|
11 | } else { |
12 | /* issuing start condition ok, device accessible */
|
13 | i2c_write(0x11); // send DC1 |
14 | bcc = 0x11; |
15 | i2c_write(len); |
16 | bcc = bcc + len; |
17 | for(i=0; i < len; i++) // Send buf |
18 | {
|
19 | i2c_write(buf[i]); |
20 | bcc = bcc + buf[i]; |
21 | }
|
22 | i2c_write(bcc); // Send checksum |
23 | i2c_start(DISPLAY_I2C_ADDR+I2C_READ); // set device address and read mode |
24 | ret = i2c_readNak(); // read one byte |
25 | if (ret == DISPLAY_I2C_ACK) |
26 | {
|
27 | daten = 1; |
28 | } else { |
29 | daten = 0; |
30 | }
|
31 | i2c_stop(); |
32 | }
|
33 | return daten; |
34 | }
|
35 | |
36 | |
37 | |
38 | unsigned char ReadDisplayData(void) |
39 | {
|
40 | unsigned char bcc, ret, rettemp; |
41 | unsigned char len = 2; |
42 | ret = i2c_start(DISPLAY_I2C_ADDR+I2C_WRITE); // set device address and write mode |
43 | if ( ret ) { |
44 | /* failed to issue start condition, possibly no device found */
|
45 | i2c_stop(); |
46 | /* do some error reporting.. led or whatever */
|
47 | } else { |
48 | /* issuing start condition ok, device accessible */
|
49 | i2c_write(DISPLAY_I2C_DC2); // send DC2 |
50 | i2c_write(0x01); // send 1 |
51 | i2c_write(0x53); // send S |
52 | bcc = DISPLAY_I2C_DC2 + 0x01 + 0x53; // Set checksum |
53 | i2c_write(bcc); // Send checksum |
54 | bcc = 0; |
55 | i2c_start(DISPLAY_I2C_ADDR+I2C_READ); // set device address and read mode |
56 | ret = i2c_readAck(); // read ack byte |
57 | if (ret == DISPLAY_I2C_ACK) |
58 | {
|
59 | rettemp = i2c_readAck(); |
60 | bcc = bcc + rettemp; |
61 | ret = i2c_readAck(); // read len |
62 | bcc = bcc+ret; |
63 | unsigned char *buf = malloc(ret * sizeof(char)); |
64 | len += ret; |
65 | for (int i = 0; i < ret; i++) |
66 | {
|
67 | buf[i] = i2c_readAck(); // read data bytes |
68 | bcc = bcc + buf[i]; |
69 | }
|
70 | ret = i2c_readNak(); // read len |
71 | if (ret != len) { |
72 | // Checksum not matching
|
73 | }
|
74 | return buf; |
75 | } else { |
76 | // No Ack
|
77 | }
|
78 | i2c_stop(); |
79 | |
80 | }
|
81 | return 0; |
82 | }
|
83 | |
84 | void DisplayReset(void) |
85 | {
|
86 | PORTD &= ~(1<<PD3); |
87 | PORTD &= ~(1<<PD3); |
88 | PORTD &= ~(1<<PD3); |
89 | PORTD |= (1<<PD3); |
90 | |
91 | }
|
92 | |
93 | unsigned char ReadDisplayBufferStatus(void) |
94 | {
|
95 | int DisplayBufferStatus; |
96 | if ( !(PIND & (1<<PIND2)) ) |
97 | {
|
98 | DisplayBufferStatus = 1; |
99 | }
|
100 | else
|
101 | {
|
102 | DisplayBufferStatus = 0; |
103 | }
|
104 | |
105 | return DisplayBufferStatus; |
106 | }
|
Und damit kann ich ganze Strings senden. So in der Art aber auch zum lesen zwischen zwei ATMegas wäre schön.
So, ich habe mich dann mal am I2C versucht. Und was passiert? Nichts passiert. Es soll eigentlich nur was von Master zum Slave geschrieben werden, also ein recht kurzer Code. Jedoch passiert nichts. Laut Oszi bleibt der I2C Bus auch dauerhaft auf High. Den Bus ziehe ich mit 4,7k PullUps und 5V auf High. Ich habe die Codes mal angehangen. ATMega8 und ATMega32 sind Slaves ATMega128 ist der Master Ich hoffe mir kann einer weiter helfen.
Achso, was vielleicht noch wichtig ist, der ATMega8 sowie der ATMega32 laufen mit dem internen Oszilator mit 1Mhz. Der ATMega128 läuft mit einem 16Mhz externem Quarz.
Jetzt hab ich viel gelesen und keinen Schritt weiter -.- Also manchmal steht was von Pullups zu klein. Größere verwenden. Dann wieder, ne, 4,7k sind gut. Dann wieder was von Kapazitiver BUS und je nach Anzahl der devices muss der Pullup größer / kleiner. -.- Ich habe dann mal die PINS mit einem µC selber auf LOW gezogen und ich habe immernoch knapp 2V auf dem Bus. Ist der Pullup hier wirklich zu klein und ich muss diesen erhöhen?
Dein ic muss die Spannung gegen den pullup auf einen niedrigen spannungslevel ziehen. Wenn bei einem pullup auf 5v mit 4.7 kohm dann noch 2V übrig bleiben wird vermutlich ein anderer busteilnehmer den bus auf high ziehen. Prüfe ob alle anderen Teilnehmer den Port als tristate konfiguriert haben.
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.