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


von Lars (Gast)


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.
1
// Multi Master:
2
void main(void){
3
  WDTCTL = WDTPW + WDTHOLD;                 // Stop wdt
4
5
  P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
6
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
7
  UCB0CTL0 = UCMM + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
8
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
9
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
10
  UCB0BR1 = 0;
11
  UCB0I2COA = 0x48;                         // Own Address is 048h
12
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
13
  IE2 |= UCB0RXIE | UCB0TXIE;               // Enable RX & TX interrupt
14
  
15
  while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
16
  UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
17
  __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
18
  
19
  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.
1
  unsigned char ret = 0;
2
  ret++;                  // Wenn hier Breakpoint, dann klappts ned
3
  sendByte(0x01, 0xB);
4
  ret = readByte(0xB);
5
  ret++;                  // Wenn hier Breakpoint dann klappts
6
  return;
7
}


die send funktion:
1
void sendByte(char Byte, char slaveAdr){
2
  P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
3
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
4
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
5
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
6
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
7
  UCB0BR1 = 0; 
8
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
9
  IE2 |= UCB0TXIE;                          // Enable TX interrupt
10
11
// alles oberhalb von hier sollte ja eigentlich nicht nötig sein, aber es geht sonst nicht
12
13
  UCB0I2CSA = slaveAdr;                     // set Slave Address
14
  
15
  g_TXData = Byte;
16
  g_TXByteCtr = 0x01;
17
  while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
18
  UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
19
  __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
20
                                          // Remain in LPM0 until all data is TX'd
21
  while (UCB0CTL1 & UCTXSTP);
22
  return;
23
}

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:
1
#pragma vector = USCIAB0TX_VECTOR
2
__interrupt void USCIAB0TX_ISR(void){
3
  if(UC0IFG & UCB0TXIFG){                     // check send or recieve
4
    if(g_TXByteCtr){
5
      UCB0TXBUF = g_TXData;                   // Load TX buffer
6
      g_TXByteCtr--;
7
    }else{
8
      UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
9
      IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
10
      __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
11
    }
12
  }else{
13
    RXData = UCB0RXBUF;                       // Get RX data
14
    __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
15
  }
16
}

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

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
Noch kein Account? Hier anmelden.