www.mikrocontroller.net

Forum: Compiler & IDEs Probleme mit TWI Kommunikation zwischen ATMEGAS


Autor: Jakob (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute

Ich versuche jetzt schon seit Wochen immer wieder mal eine Saubere 
TWI-Kommunikation zwischen einem Master und zwei Slaves aufzubauen ...
Mittlerweile bin ich mal so weit dass ich es hinbekommen habe zwei Bytes 
zu verschicken und zwei Bytes zu empfangen ... nur macht danach mein 
Master komplett dicht und ich muss alle drei Teilnehmer reseten um das 
Programm nochma schnurren lassen zu können ...

Erst mal zum konkreten Vorhaben

Der Master hat zwei Bytes (HauptVektor, ForceVektor) die er an die 
Slaves verschicken möchte.
   Der Hauptvektor wird über General Call an beide gleichzeitig 
verschickt
   Der Forcevektor wird nur an den ersten Slave geschickt
(Die "Vektoren" sind einfach irgendwelche codierten Zusätnde die 
praktischerweise in Bytes untergebracht sind)

Danach holt sich der Master zwei Bytes vom ersten Slave in einem Zug
   Einmal den den den Sensorvektor und den Motorvektor

Ab jetzt ist keine TWI Operation mehr möglich. Ich denke dass es am 
Master liegen muss.

Eigentlich müsste der Master dann noch zwei Bytes vom nächsten Slave 
holen die Funktion hängt sich aber beim setzten der Startbedingung auf.

Was ist mein Fehler ... wer kann mir helfen.


Ich denke das Problem liegt an folgendem Codeschnipsel
weiter unten sind weitere Teile des Codes für den Master und für einen 
Slave dargestellt ... Im Anhang ist dann noch das ganze Programm für den 
Master.

Vielen Dank schon mal für Eure Hilfe
// Master als Receiver ==========================================================


void getValue(unsigned char SlaveAdress, char numLoops)

{

unsigned char i = 0;

  for(i=0; i<=2; i++)              // Löschen des Variablenvektors zu Beginn
  {
    Value3[i]=0;
  }

    TWCR =  START;              // Sende Startkondition

  do {}
  while (!(TWCR & (1<<TWINT)));        // Bis TWINT Flag gesetzt ist
 


  if ((TWSR & 0xF8) == TW_START)        // Startbedingung gesendet
  {

    TWDR = (SlaveAdress | TW_READ);      // Slaveadresse und Schreibbedingung
    TWCR = TRANSACK;            // Aktivieren des Sendevorgangs
    
    do {}
    while (!(TWCR & (1<<TWINT)));

    if ((TWSR & 0xF8) == TW_MR_SLA_ACK)    // Slaveadresse mit Lesebedingung gesendet
    {                    // ACK vom Slave bekommen


      for(i=1; i<=numLoops; i++)
      {

        TWCR = TRANSACK;        // Sendebefehl mit Acknowledge-Anweisung


        do {}
        while (!(TWCR & (1<<TWINT)));

        if ((TWSR & 0xF8) == TW_MR_DATA_ACK)  // Datenpacket von Slave wurde erhalten
        {                    // ACK wurde an Slave gesendet

          Value3[i] = TWDR;          // den gegenwertigen Registerwert in eine Temporäre Variable übernehmen

        }

        else if ((TWSR & 0xF8) == TW_MR_DATA_NACK)  // Datenpacket von Slave wurde erhalten
        {                    // Kein ACK wurde an Slave gesendet
          displayString("Daten Fehler",0,"reagiert nicht",0,500);   
        }
        else
        {
             displayString("SRG1 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
        }
      }
    }
    else if ((TWSR & 0xF8) == TW_MR_SLA_NACK)  // Slaveadresse mit Lesebedingung gesendet
    {                    // Kein ACK vom Slave bekommen
         displayString("Slave Fehler",0,"reagiert nicht",0,500);
    }
    else
    {
         displayString("SRG2 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
    }
  }
  else 
  {
       displayString("STA Fehler",0,"nicht gesendet",0,500);
  }

  TWCR = STOP;                // Transmit Stop
  _delay_us(50);

}


















Hier noch das Programm zum Master
weiter unten bilde ich noch das Programm zum ersten Slave ab

int main(void)
{

  initAll();                // Initialisieren diverser Funktionen
  sensorVektor   = 0;  
  motorVektor   = 0;  
  panelVektor   = 0;  
  akkuVektor     = 0;  


  while(1)                // unendliche Schleife
  {

      displayString("waiting ",0,"for user",0,500);
    do
    {
      readAllButtons();
    }
    while(sw1_slope == 0);        // Warte auf Eingabe
    sw1_slope = 0;    

    hauptVektor = 0b00110001;      // Zustandsvektor der Hauptplatine
    forceVektor = 0b00000001;

     displayString("Send",0,"in progress",0,1);

    sendData();              // Versenden des eigenen Zustandsvektors und der ForceBefehle

    displayString("Get",0,"in progress",0,1);
    
    getData();              // 

     displayString("Sensorvektor",0,"",0,0);
    printValue(sensorVektor,1000);
     displayString("Motorvektor",0,"",0,0);
    printValue(motorVektor,1000);
     displayString("Panelvektor",0,"",0,0);
    printValue(panelVektor,1000);
     displayString("Akkuvektor",0,"",0,0);
    printValue(akkuVektor,1000);

  }
  return 0;

}



// Daten senden ========================================================================

void sendData(void)              // Versenden des eigenen Zustandsvektors und der ForceBefehle
{

    displayString("sende Haupt",0,"in progress",0,1000);

  sendValue(0, hauptVektor);        // Versenden des Eigenen Zustandes über General Call

       displayString("Sende Force",0,"in progress",0,1000);

  sendValue(80, forceVektor);        // Versenden der ForcWerte an die Motorsteuerung (SensorCPU)


}


// Werteanforderung  ========================================================================

void getData(void)          // Start der Funktion
{

  displayString("Hole Sensor",0,"in progress",0,1000);

  getValue(80,2);      // Einholen der Zusatndsvektoren vom Sensor
  sensorVektor = Value3[1];
  motorVektor = Value3[2];

  displayString("Hole Spannung",0,"in progress",0,1000);

  getValue(96,2);      // Einholen der Zusandsvektoren vom Panel
  panelVektor = Value3[1];
  akkuVektor   = Value3[2];

}



/*********************************************************************************************/
// TWI Master Übergriffe ==================================================================
/*********************************************************************************************/


// Master als Transmitter ==========================================================

void sendValue(unsigned char SlaveAdress, unsigned char Value)

{


  TWCR =  START;              // Sende Startkondition
  do {}
  while (!(TWCR & (1<<TWINT)));        // Bis TWINT Flag gesetzt ist


  if ((TWSR & 0xF8) == TW_START)        // Startbedingung gesendet
  {


    TWDR = (SlaveAdress | TW_WRITE);    // Slaveadresse und Schreibbedingung
    TWCR = TRANSMIT;            // Aktivieren des Sendevorgangs
    
    do {}
    while (!(TWCR & (1<<TWINT)));


    if ((TWSR & 0xF8) == TW_MT_SLA_ACK)    // Slaveadresse mit Schreibbedingung gesendet
    {                    // ACK vom Slave bekommen


      TWDR = Value;            // Übermittlungswert in Schiftregister
      TWCR = TRANSMIT;          // Aktivieren des Sendevorgangs
 

      do {}
      while (!(TWCR & (1<<TWINT)));    // Bis TWINT Flag gesetzt ist

        if ((TWSR & 0xF8) == TW_MT_DATA_ACK)// Daten wurde versendet
        {                  // ACK vom Slave bekommen

        }
        else if ((TWSR & 0xF8) == TW_MT_DATA_NACK)// Daten wurde versendet
        {                  // Kein ACK vom Slave bekommen
             displayString("Daten Fehler",0,"reagiert nicht",0,500);   
        }
        else
        {
             displayString("SRG Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
        }                  // Registerinhalt passt überhaupt nicht zu dem Kontext 
    }
    else if ((TWSR & 0xF8) == TW_MT_SLA_NACK)  // Slaveadresse mit Schreibbedingung gesendet
    {                    // Kein ACK vom Slave bekommen
         displayString("Slave Fehler",0,"reagiert nicht",0,500);
    }
    else
    {
         displayString("SRG Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
    }                      // Registerinhalt passt überhaupt nicht zu dem Kontext
  }
  else 
  {
       displayString("STA Fehler",0,"nicht gesendet",0,500);
  }


  TWCR = STOP;        // Transmit Stop          
  _delay_us(50);


}


// Master als Receiver ==========================================================


void getValue(unsigned char SlaveAdress, char numLoops)

{

unsigned char i = 0;

  for(i=0; i<=2; i++)              // Löschen des Variablenvektors zu Beginn
  {
    Value3[i]=0;
  }

    TWCR =  START;              // Sende Startkondition

  do {}
  while (!(TWCR & (1<<TWINT)));        // Bis TWINT Flag gesetzt ist
 


  if ((TWSR & 0xF8) == TW_START)        // Startbedingung gesendet
  {

    TWDR = (SlaveAdress | TW_READ);      // Slaveadresse und Schreibbedingung
    TWCR = TRANSACK;            // Aktivieren des Sendevorgangs
    
    do {}
    while (!(TWCR & (1<<TWINT)));

    if ((TWSR & 0xF8) == TW_MR_SLA_ACK)    // Slaveadresse mit Lesebedingung gesendet
    {                    // ACK vom Slave bekommen


      for(i=1; i<=numLoops; i++)
      {

        TWCR = TRANSACK;        // Sendebefehl mit Acknowledge-Anweisung


        do {}
        while (!(TWCR & (1<<TWINT)));

        if ((TWSR & 0xF8) == TW_MR_DATA_ACK)  // Datenpacket von Slave wurde erhalten
        {                    // ACK wurde an Slave gesendet

          Value3[i] = TWDR;          // den gegenwertigen Registerwert in eine Temporäre Variable übernehmen

        }

        else if ((TWSR & 0xF8) == TW_MR_DATA_NACK)  // Datenpacket von Slave wurde erhalten
        {                    // Kein ACK wurde an Slave gesendet
          displayString("Daten Fehler",0,"reagiert nicht",0,500);   
        }
        else
        {
             displayString("SRG1 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
        }
      }
    }
    else if ((TWSR & 0xF8) == TW_MR_SLA_NACK)  // Slaveadresse mit Lesebedingung gesendet
    {                    // Kein ACK vom Slave bekommen
         displayString("Slave Fehler",0,"reagiert nicht",0,500);
    }
    else
    {
         displayString("SRG2 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
    }
  }
  else 
  {
       displayString("STA Fehler",0,"nicht gesendet",0,500);
  }

  TWCR = STOP;                // Transmit Stop
  _delay_us(50);

}



/*********************************************************************************************/
// Initialisierungsroutinen ==================================================================
/*********************************************************************************************/


// TWI Initialisierung

void setTWIMaster(void)  
{

  sei();              // Generelles einschalten der Interrupts
  TWCR = (1<<TWEN);        // TWI Schnittstelle schon mal einschalten
  TWBR = 0x10;          // BitrateRegister auf 16 setzten
  TWSR = 0x02;          // TWI Prescaler auf 16 setzen

                  // Mit dieser Einstellung lassen sich immer noch 
                  // ca. 1400 Pakete pro Sekunde verschicken
}






nun noch das dazugehörige Slaveprogramm

--------------------------------------------------



int main(void)
{

  initAll();                  // Initialisieren diverser Funktionen
  
    sensorVektor = 0b00100101;
    motorVektor = 0b00000001;
    hauptVektor   = 0;
    forceVektor    = 0;

    DDRB |= (1<<DDB2);
    PORTB |= (1<<PB2);

    displayString("Warte auf Master",0,"",0,0);

  while(1)                  // unendliche Schleife
  {
    displayString("Hauptvektor",0,"",0,0);
    printValue(hauptVektor,1000);
    displayString("Forcevektor",0,"",0,0);
    printValue(forceVektor,1000);


  }
  return 0;

}

ISR (TWI_vect)
{

  TWCR = (1<<TWEA) | (1<<TWEN);
  cli();

  if ((TWSR & 0xF8) == TW_ST_SLA_ACK)
  giveValue();
  else
  receiveValue();

  sei();
  TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);  // Setze das TWI Statusregister
  TWDR = 0;

}

/*********************************************************************************************/
// TWI Master Zugriffe ==========================================================================
/*********************************************************************************************/


// Slave als Receiver ==========================================================

void receiveValue()
{

  if ((TWSR & 0xF8) == TW_SR_GCALL_ACK)    // General Call erfasst 
  {                      // ACK wurde zurückgesendet


    TWCR |= (1<<TWEA);
    while (!(TWCR & (1<<TWINT)));

    if ((TWSR & 0xF8) == TW_SR_GCALL_DATA_ACK)  // Daten erhalten (nach dem generellen Ansprechen durch Master)
    {                       // ACK wurde zurückgesendet

      hauptVektor = TWDR;            // Übernehmen des Datenregisters in den Zustands-Hauptvektor

    }
    else if ((TWSR & 0xF8) == TW_SR_GCALL_DATA_NACK)  // Daten erhalten (nach dem generellen Ansprechen durch Master)
    {                      // Kein ACK wurde zurückgesendet
         displayString("Slave Fehler",0,"NACK nach GC",0,500);
    }

  }

  else if ((TWSR & 0xF8) == TW_SR_SLA_ACK)      // Eigene Slave-Adresse mit Schriebbedingung erhalten
  {                      // ACK wurde zurückgesendet

    TWCR |= (1<<TWEA);

    while (!(TWCR & (1<<TWINT)));


    if ((TWSR & 0xF8) == TW_SR_DATA_ACK)    // Daten erhalten (nach dem Ansprechen durch Master)
    {                      // ACK wurde zurückgesendet

      forceVektor = TWDR;            // Übernehmen des Datenregisters in den Forcevektor

    }
    else if ((TWSR & 0xF8) == TW_SR_DATA_NACK)    // Daten erhalten (nach dem Ansprechen durch Master)
    {                      // Kein ACK wurde zurückgesendet
         displayString("Slave Fehler",0,"NACK nach SLA+W",0,500);
    }

  }


  TWCR = ((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));

}



// Slave als Transmitter ==========================================================




void giveValue(void)
{



  if ((TWSR & 0xF8) == TW_ST_SLA_ACK)      // Eigene Slave-Adresse mit Lesebedingung erhalten
  {                      // ACK wurde zurückgesendet

    TWDR = sensorVektor;          // Einladen des Sensor-Zustandvektors in das Senderegister


    TWCR = TRANSACK
    while (!(TWCR & (1<<TWINT)));


    if ((TWSR & 0xF8) == TW_ST_DATA_ACK)    // Daten im TWDR wurden versendet
    {                    // ACK vom Master wurde erhalten

      TWDR = motorVektor;          // Einladen des Sensor-Zustandvektors in das Senderegister

      TWCR = TRANSACK;
      while (!(TWCR & (1<<TWINT)));


      if ((TWSR & 0xF8) == TW_ST_DATA_NACK)    // Daten im TWDR wurden versendet
      {
           displayString("Slave Fehler",0,"NACK nach Daten",0,500);
      }

    }

    else if ((TWSR & 0xF8) == TW_ST_DATA_NACK)    // Daten im TWDR wurden versendet
    {                      // Kein ACK vom Master wurde erhalten
         displayString("Slave Fehler",0,"NACK1 nach Daten",0,500);
    }

    else if ((TWSR & 0xF8) == TW_ST_LAST_DATA)    // Letztes Datenpacket im TWDR wurden versendet
    {                      // Kein ACK vom Master wurde erhalten
         displayString("Slave Fehler",0,"NACK2 nach Daten",0,500);
    }


  }

  TWCR = ((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));    // Setze das TWI Statusregister

}




/*********************************************************************************************/
// Initialisierungsroutinen ==================================================================
/*********************************************************************************************/



// TWI Initialisierung

void setTWISlave(unsigned char SlaveAdress)  
{
  sei();                    // Generelles einschalten der Interrupts
  TWAR = (SlaveAdress | 1);            // Setzen der Slave-Adresse mit General Call Enable
  TWAMR = SlaveAdress;            // Setzten der Adressenmaskierung
  
  TWDR = 0;

  TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE);  // Setze das TWI Statusregister
                        // TWI ACK und Interrupt wird eingeschaltet 
}


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.