Ich habe nun ein System laufen mit einem Atmega644 als Master, 3 Atmega48 und ein Atmega32 als Slaves per I2C. Ich verwende die TWI Quellen hier aus dem Forum. Das System funktioniert eigentlich recht gut, aber ab und an habe ich Hänger, so dass ich alles resetten muss. Nun ist es so: Der Master und 3 Slaves (AT48) haben die gleiche VCC und jeder Slave macht sein TWI Init 200 ms verzögert. Also 200, 400, 600 ms. Der Master macht sein Init direkt und wartet dann 1 Sekunde. Der Atmega32 hat eine andere (eigene) VCC. Hier hat sich gezeigt, dass das System am stabilsten funktioniert wenn ich den Atmega32 zuerst einschalte und dann den Master. Das versteh ich eigentlich schon nicht so ganz warum, aber hab es so hingenommen. Ach so einschub: Mit anderer VCC meine ich nur, dass die von nem eigenen Netzteil kommt. Alle VCC sind 5V. Nun habe ich in die TWI Routinen mal Timeouts reingemacht damit zumindest die anderen Funktionen noch gehen wenn es auf dem TWI Bus mal hängt. Meine Frage iist eigentlich wie ich in einem solchen Fehlerfall den TWI Bus komplett neu initialisieren kann um nicht jedesmal die Stecker ziehen zu müssen. Meine Fragen nochmal ganz konkret: 1. In welcher Reihenfolge sollten die TWI Teilnehmer initialisiert werden? 2. Wie kann man per Software auf Fehler reagieren und den Bus wieder lauffähig machen? 3. Würde es Sinn machen alle TWI Teilnehmer mit identischer VCC zu versorgen? 4. Evtl. die Slaves durch einen µC PIN ein und aus zu schalten? Mit nem BC247 dazwischen? Dann könnte ich im Fehlerfall nen Resett der Slaves machen. 5. Wie sichert ihr den TWI Bus gegen Fehler ab? Chris
Moin, Schaltplan, Kabellängen und verwendete Software. Sonst wird das ein Ratespiel. MfG
Okay: Schaltplan kann ich leider erst heute Abend liefern, da ich hier kein Zugriff drauf habe. Erklärung: vorab: Der Master ist der Pollin Webserver mit der Software von Ulli Radig. Hier habe ich die TWI Routinen aus dem Forum eingearbeitet. (Poste ich gleich hier). Die Slaves sind eigentlich minimal beschaltet. VCC, GND, SCL und SCA. Sie steuern RGB Led Strips über Hardware PWM. (OC0A, OC0B und OC2A) Der Mega32 steuert noch einige einzelne LEDs über Schieberegister. (Sternenhimmel). TWI PullUps habe ich am Master 10K an VCC. Kabellängen: Zu den 48er ca. 15 cm und zum 32 Vielleicht 50 cm. Kommunikation eigentlich sauber möglich. Ich nutze den Webserver über rs232 zu einstellen der Farben. Dann auf einmal nach einigen Stunden kommen entweder Timeouts oder er kann den Bus nicht zum schreiben/lesen starten. Quellcodes sind angehängt in folgenden Beiträgen zur Besseren Übersicht. Chris
Quellen des Atmega48 Slave Exakt so sieht auch das TWI beim Mega32 aus, daher lass ich diese Quellen mal weg sonst wird es zu viel.
Quelen des TWI Masters (nur die TWI Teile weil ich ja nicht den ganzen Webserver hochladen kann...) Hier die Teile aus der cmd.c welche TWI nutzen:
1 | void command_refresh (void) |
2 | {
|
3 | twi_send(LESESTERNE, TwiAdr_Sternenhimmel); |
4 | _delay_ms(TWI_DELAY); |
5 | twi_read_s(); |
6 | _delay_ms(TWI_DELAY); |
7 | twi_send(LESEROTBLAU, TwiAdr_Sternenhimmel); |
8 | _delay_ms(TWI_DELAY); |
9 | twi_read_rb(); |
10 | _delay_ms(TWI_DELAY); |
11 | twi_send(LESEWEISS, TwiAdr_Sternenhimmel); |
12 | _delay_ms(TWI_DELAY); |
13 | twi_read_w(); |
14 | usart_write("PWM Stufen Sterne: "); |
15 | for (uint8_t i=0;i<8;i++) |
16 | {
|
17 | usart_write("%4i ", pwmtableStars[i]); |
18 | }
|
19 | usart_write("\n\r"); |
20 | usart_write("PWM Stufen Weiss: "); |
21 | for (uint8_t i=0;i<8;i++) |
22 | {
|
23 | usart_write("%4i ", pwmtableWhite[i]); |
24 | }
|
25 | usart_write("\n\r"); |
26 | usart_write("PWM Stufen Blau: "); |
27 | for (uint8_t i=0;i<8;i++) |
28 | {
|
29 | usart_write("%4i ", pwmtableBlue[i]); |
30 | }
|
31 | usart_write("\n\r"); |
32 | usart_write("PWM Stufen Rot: "); |
33 | for (uint8_t i=0;i<8;i++) |
34 | {
|
35 | usart_write("%4i ", pwmtableRed[i]); |
36 | }
|
37 | usart_write("\n\r"); |
38 | }
|
39 | void command_rgb(void) |
40 | {
|
41 | char code[16]; |
42 | if ((*((unsigned int*)&variable[0]) >= 0) && (*((unsigned int*)&variable[0]) < 256)) |
43 | {
|
44 | if ((*((unsigned int*)&variable[1]) >= 0) && (*((unsigned int*)&variable[1]) < 256)) |
45 | {
|
46 | if ((*((unsigned int*)&variable[2]) >= 0) && (*((unsigned int*)&variable[2]) < 256)) |
47 | {
|
48 | code[0] = *((unsigned int*)&variable[0]); |
49 | code[1] = *((unsigned int*)&variable[1]); |
50 | code[2] = *((unsigned int*)&variable[2]); |
51 | twi_send(code, *((unsigned int*)&variable[4])); |
52 | }
|
53 | else
|
54 | {
|
55 | usart_write ("\n\rFalsche Eingabe\r\n"); |
56 | }
|
57 | }
|
58 | else
|
59 | {
|
60 | usart_write ("\n\rFalsche Eingabe\r\n"); |
61 | }
|
62 | }
|
63 | else
|
64 | {
|
65 | usart_write ("\n\rFalsche Eingabe\r\n"); |
66 | }
|
67 | // EssStrip[7][10][3]
|
68 | }
|
Vielleicht hat auch jemand ohne Schaltplan einen Tip wie er seine TWI Kommunikation Softwaremässig gegen Fehler absichert. Das ist ja eher ein allgemeines Thema. Chris
Hallo, Frühstückspause ist rum. Bin mal kurz über die Quellen geflogen. Auf den ersten Blick sieht es so aus das es keine Fehlerbehandlung für den TWI gibt. Klemm mal einen Slave ab und starte neu, hängt dann das ganze System? MfG
Das kann ich auch erst heute Abend testen. Aber danke für den Tip. Zur Fehlerbehandlung: Ich habe wenigstens mal dafür gesorgt dass er in keine Endlos While Schleife mehr läuft durch den Timeout. Der Master gibt dann über rs232 auch aus wo der Timeout aufgetreten ist. Sonst hab ich ich zur Zeit keine andere Idee der Fehlerbehandlung, weshalb ich da auf ne Anregung hier hoffe. Chris
Hangs treten bei einem Read auf? Wenn der Slave sich bei den Clocks verzählt und selbst SDA=0 setzt, kann er Stop/Start vom Master nicht sehen. In diesem Fall hilft es, 9 Clocks mit SDA=1 an den Slave zu senden, damit er mindestens ein NAK sieht. Danach sollte er auf Stop/Start wieder reagieren.
Klaus2m5 schrieb: > In diesem Fall hilft es, 9 Clocks mit SDA=1 an den Slave zu > senden, damit er mindestens ein NAK sieht. Danach sollte er auf > Stop/Start wieder reagieren. Ups. Wäre es unhöflich zu fragen wie das in C Code aussehen würde? Das muss ja sicher irgendwie manuell gemacht werden. Und mit Clocks ist ja sicher die TWI Frequenz gemeint. Kennt jemand ein Projekt welches TWI verwendet? Dann würde ich da mal ein wenig schnusen....
Christoph Hoell schrieb: > Wäre es unhöflich zu fragen wie das in C Code aussehen würde? Kann ich Dir leider nicht sagen, denn ich programmiere alles in Assembler. Im Prinzip werden SDA und SCL über DDR gesteuert (open collector). Dadurch ist SDA und SCL invertiert. Zwischen den SCL Impulsen ein Delay mit der halben Periode der I2C-Frequenz. SDA_DDR=0, SCL_DDR=0, 9*(SCL_DDR=1, SCL_DDR=0) Einfach einen Start/Write mit 0xFF machen geht leider nicht, da der Master wegen Bus-Arbitration denken würde, dass ein anderer Master SDA=0 setzt. Nach meiner Erfahrung wären auch kleinere Pullups hilfreich. Versuchs mal mit 1k8 (~3mA bei 5V)
Danke. Prima Tips. Da hab ich heute Abend einiges zu testen. Mit den Pull Ups bin ich nach einiger Lektüre erst von 4K7 auf 10K hochgegangen.
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.