Viel Unverständnis zu diesem Zustand (passt halt nur so ungefähr in diesen Thread):

I2C-Lesen braucht ne Pause.

Vorgeschichte: Bei meinem Archie hängen an einem I²C-Master (mega1284/20MHz) mehrere Slaves, einer davon eine Motor-Steuerplatine (mega328/20MHz) mit Treiberplatine für zwei Motoren je max 60W. Die Befehle für die Motoransteuerung der beiden Motoren gehen vom Master zur Motor-Steuerplatine per I²C, das läuft prächtig. Lesen des Slavepuffers - z.B. Encoderstand oder Ist-Speed - ging oft, meist, führte bisher stehts nach 1 bis etwa 20 (evtl. mehr?) Lesevorgängen zum Blackout des Masters. Blackout: TWI-Übertragung stoppte (z.B. belegt durch testweise Ausgabe per UART), aber ISR (TIMER2_COMPA_vect) lief weiter mit 20kHz-Interrupt, erkennbar am Toggeln der 1-sec-Heartbeat-LED.

Sonstige Angaben: 2 UARTkanäle laufen per Interrupt - 1x 115,2 kBd fürs Terminal und 1x 57,6 kBd für die PingPong-LED-Anzeigetafel, ISR (TIMER2_COMPA_vect) mit 20 kHz, ADC im free running mit rund 15 kHz, External Interrupt 20 für RC5, I2C nach PFleury mit 100 kHz.

Fazit bisher: Telegramme werden an die Slaves per I²C nur gesendet, es wird nichts zurückgelesen. Ein ziemlich unbefriedigender Zustand (aber Archie lief ziemlich gut).

Versuch einer Nachbesserung heute, dazu zuerst Versuch einer Identifizierung der Abbruchstelle. Um die Absturzstelle des Codes zu identifizieren wurden zuerst kurze UART-Telegramme in die I²C-Lesesequenz eingefügt. Die erste im Master gleich nach dem Schreiben der Adresse des ersten zu lesenden Pufferbytes. Und schon läufts klaglos. Ein einziges Millisekundenwait tat den gleichen Nutzen, mittlerweile tuts ein wait von 100 Mikrosekunden. Kontrolle: ohne Wait bekomme ich den Master nach 1 bis 15 Lesevorgängen ins Koma.

Derzeit wurde als Testsequenz tausend Mal auf den Puffer zugegriffen und stets jeweils die gleichen fünf Bytes der Motorplatine ausgelesen, Slaveadresse 130 dez = 0x82, Startbyte zum Lesen = 23. No Problem, mit UART-Ausgabe und einem Wait von 50 ms in der Leseschleife eine Sache von gut 60 sec (die ersten fünf brauche ich um den Befehl per RC5 an den Master zu senden). Das sieht zum Schluss am Terminal so aus, die Sekunden ist die aktuelle Boardzeit mit Start beim Power on:

PHP-Code:
    I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    985    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    986    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    987    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    988    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    989    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    990    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    991    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    992    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    993    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    994    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    995    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    996    Zeit  65 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    997    Zeit  66 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    998    Zeit  66 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    999    Zeit  66 sec
    
I2CMrid # 131/23    O-AL 23    O-AH 24    O-BL 25    O-BH 26    1000    Zeit  66 sec
    
Ende test841 
Fazit: diese tausend Lesevorgänge lassen vermuten, dass zuküftig keine Störungen mehr auftauchen.

Hier zur Erläuterung der Leseabschnitt der Funktion void I2CMrid ( void ) // I2C, Motordaten auslesen über I²C
Code:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//      Lesen vom Slave     
  if(!(i2c_start(SLAVE_MoCo+I2C_WRITE))) //Slave bereit zum schreiben/lesen?
  {                                     //
        i2c_stop();     // Dies scheint notwendig, um den Lesepointer korrekt
                        //      zu positionieren
    i2c_start(SLAVE_MoCo+I2C_WRITE);    // Slave bereit zum schreiben/lesen?
//  i2cdmy = i2c_write( 0x15 );         // Bufferadresse 15hex/21dez zum Lesen
//  i2cdmy = i2c_write( 0x04 );         // Bufferadresse 04hex/04dez zum Lesen
    i2cdmy = i2c_write( laddr );        // Lese Buffer ab Adresse laddr
        i2c_stop();                     //
//uputs0 ("\r\tLabel nach Start ");     // Nach Einfügen dieser Zeile lief es gut!
//  wms  (    1);                       //  daher statt der UART-Ausgabe das wait
    wmus (  100);                       //  kurzes Wait, ca. 0,1 ms
    i2cdmy  = i2c_start(SLAVE_MoCo+I2C_READ); // <<<### Lesen beginnen
    ipwm12  = i2c_read (ACK);           // Bytes lesen...
    soll12  = i2c_read (ACK);           //
    ipwm34  = i2c_read (ACK);           // 
    soll34  = i2c_read (ACK);           //
    i2cdmy  = i2c_read (NAK);           // letztes Byte lesen, NAK
        i2c_stop();                     // Zugriff beenden
  }                                     //
  else                                  // Wenn Fehler, dann nelde jetzt:
  {                                     //    Lesefehler, dazu Fehlerblinken
    uputs0("\r\n\t### Kein Lesen möglich.\r\n");     //
    i2cerr      = 0b00000001;           // Fehlercode zu i2c-read nicht möglich
  }                     // Ende if(!(i2c_start(SLAVE_MoCo+I2C_WRITE)))
Frage/Bitte:
Kann mir jemand bitte erklären wo ungefähr die Leseroutine sich durch eine zu knappe zeitliche Bemessung aufhängen könnte? Ich dachte, dass das