mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430F2132 I2C Multi Master Senden und Empfangen


Autor: Lars (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen

Ich muss eine kommunikation über I2C machen, dabei bekomme ich kommandos 
von einem mainboard (ich als Slave) und muss das dann andere Slaves 
ansteuern.

Das klappt soweit eigentlich, nur gibts da ein paar Probleme.

1. wenn ich breakpoints setze funktioniert das senden an die slaves 
nicht mehr. Sobald ich die wegnehme läuft das testprogramm durch und 
alles wird gesendet.

2. ich kann zwar daten empfangen wenn ich im MultiMasterMode bin (UCMM), 
jedoch muss ich in der senden Funktion wieder alle Register auf master 
umschalten damit irgendwas gesendet wird.

3. muss ich nach jedem senden eine verzögerung einbauen, damit das Byte 
auch sicher ankommt. ich habe diese verzögerung einfach mit einer 
sinnlosen schleife gemacht welche 5 mal durchläuft. da dies jedoch 
unsauber ist, habe ich es durch ein while ersetzt ähnlich wie in den TI 
codesamples, nur das scheint auch nicht so richtig zu funktionieren.
// Multi Master:
void main(void){
  WDTCTL = WDTPW + WDTHOLD;                 // Stop wdt

  P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMM + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB0BR1 = 0;
  UCB0I2COA = 0x48;                         // Own Address is 048h
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  IE2 |= UCB0RXIE | UCB0TXIE;               // Enable RX & TX interrupt
  
  while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
  UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
  __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
  
  while(RXData != 0x12);

das programm wartet bis der uP 0x12 empfängt, das klappt wunderbar.
danach wird einem slave ein kommando geschickt (0x01) und dann dieser 
slave wieder ausgelesen. das funktioniert nur wenn vorher keine 
breakpoints gemacht werden.
  unsigned char ret = 0;
  ret++;                  // Wenn hier Breakpoint, dann klappts ned
  sendByte(0x01, 0xB);
  ret = readByte(0xB);
  ret++;                  // Wenn hier Breakpoint dann klappts
  return;
}


die send funktion:
void sendByte(char Byte, char slaveAdr){
  P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB0BR1 = 0; 
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  IE2 |= UCB0TXIE;                          // Enable TX interrupt

// alles oberhalb von hier sollte ja eigentlich nicht nötig sein, aber es geht sonst nicht

  UCB0I2CSA = slaveAdr;                     // set Slave Address
  
  g_TXData = Byte;
  g_TXByteCtr = 0x01;
  while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
  UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
  __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
                                          // Remain in LPM0 until all data is TX'd
  while (UCB0CTL1 & UCTXSTP);
  return;
}

am schluss dieser funktion bleibt der uP hängen, wenn ich breakpoints 
gesetzt habe [ while (UCB0CTL1 & UCTXSTP); ]. dieses while habe ich 
gemacht um die stop condition zu checken (wie weiter oben). nur ich habe 
keine ahnung ob das so stimmt, ohne wird einfach nichts gesendet, ausser 
ich mache eine kleine schlaufe mit ca 5 NOPs oder so, also einfach eine 
kleine verzögerung.

die empfangen funktion ist ähnlich, auch da muss ich wieder alle 
register umstellen.

die interrupt routine:
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void){
  if(UC0IFG & UCB0TXIFG){                     // check send or recieve
    if(g_TXByteCtr){
      UCB0TXBUF = g_TXData;                   // Load TX buffer
      g_TXByteCtr--;
    }else{
      UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
      IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
      __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
    }
  }else{
    RXData = UCB0RXBUF;                       // Get RX data
    __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
  }
}

hier kann ich zwar unterscheiden zwischen senden und empfangen, jedoch 
weiss ich nicht ob ich aktiv was lese (vom slave) oder ob ich was von 
einem anderen master empfange. muss ich da selber mit globalen variabeln 
das checken, oder gibts da ne elegantere lösung?

ich hoffe das war verständlich :D

danke für jede hilfe
lars

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.