This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430 I2C communication with LSM9DS1 gyroscope/accelerometer/magnometer

Other Parts Discussed in Thread: MSP430F2274, MSP430F5529

Hi,

I am working on I2C communication with the msp430 and the LSM9DS1 chip. I am using the ez430-cc2500 evaluation board. I am using the msp430 in master receive mode, trying to receive the data from the LSM chip. The problem I am having is my interrupt is never called when data should be coming in, meaning no data is coming in. My code walks through the steps needed for I2C and seems to receive all slave acknowledgements from the LSM, but it gets trapped in never receiving the data. The LSM has a specific operation for I2C as outlined in my code below. It operates find through the last SAK, but then never receives data which is the next operation. 

#include <msp430.h>

unsigned char RXData;
unsigned char RXCompare;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P3DIR |= 0x0F;							// disable cc2500
  P3SEL |= 0x06;                            // Assign I2C pins to USCI_B0
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC + UCA10 + UCSLA10;     // I2C Master, synchronous mode, 10 bit mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB0BR1 = 0;
  UCB0I2CSA = 0xD4;                         // Slave Address is 048h
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  IE2 |= UCB0RXIE;                          // Enable RX interrupt
  RXCompare = 0;                            // Used to check incoming data

  while (1)
  {
	  /*1) start
	  	2) slave address + W
	  	3) slave ack
	  	4) slave subaddress
	  	5) slave ack
	  	6) start repeat
	  	7) slave address + R
	  	8) slave ack
	  	9) data
	  	10)NMAK
	  	11)stop
	  	*/

    UCB0CTL1 |= UCTXSTT + UCTR;             // 1) I2C start condition
    UCB0I2CSA = 0xD4;                       // 2) Send Slave address + W
    while (UCB0CTL1 & UCTXSTT);             // 3) Start condition sent?
    UCB0I2CSA = 0x35;		            // 4) Send slave sub-address
    while (UCB0CTL1 & UCTXSTT);		    // 5) Slave ack?
    UCB0CTL1 |= UCTXSTT + UCTR;		    // 6) start repeat (restart)
    UCB0I2CSA = 0xD5;                       // 7) Send Slave address + R
    while (UCB0CTL1 & UCTXSTT);		    // 8) Slave ack?
    //UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
   // while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent

    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts

  }
}

// USCI_B0 Data ISR
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
#else
#error Compiler not supported!
#endif
{
  RXData = UCB0RXBUF;                       // Get RX data
  __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
}

Any thoughts as to what the problem could be? Thanks!

  • Hello Micah,

    Since I'm assuming that the MSP430 is not part of a multi-master system and will never be addressed, setting the UCA10 bit inside of UCB0CTL0 is not necessary. However the real root cause of your issue has to deal with the slave address and I2C start conditions. UCSLA10 should not be used since the LSM9DS1 uses a 7-bit addressing mode (7-bit address and 1 R/W bit).

    Every time the UCTXSTT bit is set it generates a START condition, which transmits the slave address. This means that after every change in the UCB0I2CSA you need to send a new START condition (UCB0CTL1 |= UCTXSTT;) that will trigger the correct slave functionality (accelerometer, gyroscope, magnetometer) and command (read, write). If you are issuing a write command, UCTR needs to be set. If a read command, expect data to be coming into the MSP430 ISR and reset UCTR. If issuing a read command you also need to make sure you receive all of the correct bytes and issue a stop command before moving on to the next transaction. Review all of the msp430x22x4_uscib0_ic2 code examples and Section 17.3.4.2 of the User's Guide and start simple when re-working your code.

    Regards,
    Ryan
  • Thank you Ryan for your detailed answer. I will look into this and post if I have more questions. 

  • Hi Micah and Ryan,

    I also work with a MSP430 and a LSM9DS1, but I can't start the communication with I2C. I modified your programm.

    Can someone help me? Maybe Micah yours working now?







    WDTCTL = WDTPW + WDTHOLD; // Stop WDT P4DIR |= 0x06; // P4OUT |= 0x06; // CS_AG, CS_M P3DIR |= 0x40; // P3OUT |= 0x40; // SD0_M, SD0_AG P3DIR |= 0x0F; // disable cc2500 P3SEL |= 0x03; // 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 UCB0BR0 = 24; // fSCL = SMCLK/24 = 50kHz UCB0BR1 = 0; UCB0I2CSA = 0xD4; // Slave Address is UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation //UCB0IE |= UCTXIE; // Enable RX interrupt RXCompare = 0; // Used to check incoming data UCB0I2CSA = 0xD4; // 2) Send Slave address + W (SAD+W) UCB0CTL1 |= UCTR + UCTXSTT; // 1)Start condition while (UCB0CTL1 & UCTXSTT); // 3) Slave ack UCB0I2CSA = OUT_X_L_ACC; // 4) Slave SUB Adresse UCB0CTL1 |= UCTXSTT; // 6) Start repeat while (UCB0CTL1 & UCTXSTT); // 5) Slave ack UCB0I2CSA = 0xD5; // 7) Send Slave address + R UCB0CTL1 |= UCTXSTT; while (UCB0CTL1 & UCTXSTT); // 8) Slave ack UCB0CTL1 &= ~UCTR; UCB0CTL1 |= UCTXSTP; // 11) I2C stop condition while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent

  • Hi Anita,

    You have to provide a lot more information to receive help with your issue. Are you using a MSP430F2274? Your P3SEL bits are incorrect if so, they should be set for BIT 1 & 2 (0x06) and as initialized it is doubtful that you are outputting the I2C clock. You also seem to indicate that SA0 is set to 1 through your P3DIR & P3OUT settings, your slave address for writes on the LSM9DS1 accelerometer and gyroscope would therefore be 0xD6. Further debugging is required on your end and you should only return with additional questions once you can identify a specific issue with your setup and preferably provide oscilloscope or logic analyzer screen shots.

    e2e.ti.com/.../msp-i2c-getting-started-guide

    Regards,
    Ryan
  • Hi Ryan,

    I work with Anita on a Project for oure Bachelor studdy.

    We try to establish a i2c communication between a msp430 and a lsm9ds1 as well. Im using the MSP430F5529 Launchpad Evaluation Kit.

    I seperated the communication in functions for receiving and sending bytes. The master is sending an adress (can be seen on oscilloscope). There is just 0 on  the serial monitor when i check out the sensor register content. I think i dont receive anything from the Sensor. 

    I think there is something wrong with the " unsigned char i2c_write_bytes (unsigned char addr, unsigned char data_write[]) " function.

    regards.

    Timo

    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    // ++
    // ++   Projekt: UW-Navi
    // ++
    // ++   Stand....: 14.09.2016  / T.Schlosser
    // ++
    // ++   mit CCS  6.2.0.00048  /  MSP430F5529LP
    // ++
    // ++   Sensor LSM9DS1 über I2C
    // ++
    // ++
    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //
    
    
    #include <msp430.h> 
    #include <math.h>
    //
    // main.c
    //
    // +------------------------------------------------
    // +  Register LSM9DS1 Definitionen
    // +------------------------------------------------
    #define LSM9SD1                    (0xD4>>1)  // 7-bit adresse des Sensors
    #define LSM9SD1_ACC                (0xD4>>1)  // Adresse des Bescheunigungssensors und des Gyroskopes (um 1 verschoben da r/w vom MSP430 kommt)
    #define LSM9SD1_MAG                (0x38>>1)  // Adresse des Magnetsensors (um 1 verschoben da r/w vom MSP430 kommt)
    
    // Register Gyroskop Accelerometer
    #define REG_WHO_AM_I_XG           0x0F  // ACC & Gyro Who Am I Register: zur identifikation des Sensors (Registerinhalt 01101000)
    #define REG_CTRL_REG1_G           0x10  // Gyro Control Register 1: für Output Datenrate , Skalierung und Bandbreiteneinstellung des Gyro
    #define REG_CTRL_REG2_G           0x11  // Gyro Control Register 2: interrupt selektion und Wahl ob FIFO oder DataReg als Ausgang verwendet wird
    #define REG_CTRL_REG3_G           0x12  // Gyro Control Register 3: LP-Mode enable, Hochpass enable, Filter-Frequenz selection,
    #define REG_ORIENT_CFG_G          0x13  // Gyro Orientierungs Register: x,y,z-Achse Winkel Vorzeichen, Benutzer Orientierungs Vorzeichen
    #define REG_INT_GEN_SRC_G         0x14  // Gyro Interupt-quell Register: Interupt aktivieren, x,y,z-Achse Interupt Wahl ob bei High oder Low
    #define REG_OUT_TEMP_L            0x15  // Temperatur Sensor Register L: Temperatur Output Daren Lowbyte
    #define REG_OUT_TEMP_H            0x16  // Temperatur Sensor Register H: Temperatur Output Daten Highbyte
    #define REG_STATUS_REG_0          0x17  // ACC & Gyro Status Register 0: Interups Output Status, Boot running Flag,
                                            //                             Neue Temp. verfügbar, neue ACC & Gyro Daten verfügbar
    #define REG_CTRL_REG4             0x1E  // ACC & Gyro Control Register 4: Gyro x,y,z-Achse einschalten, "eingeklinkt(latched)" Interupt, 4D interupt
    #define REG_CTRL_REG5_XL          0x1F  // ACC Control Register 5: Acc z,y,x-Achsen einschalten, Updaterate einstellen
    #define REG_CTRL_REG6_XL          0x20  // ACC Control Register 6: Output Datarate, Acc Skalierung, Bandbreite, Anti-Alias. Filterbandbreite
    #define REG_CTRL_REG7_XL          0x21  // ACC Control Register 7: High-res enable, Filter selection (High-, Lowpass), Highpass enable
    #define REG_CTRL_REG8             0x22  // ACC & Gyro Control Register 8: Diverse Einstell Bits (Reboot, BD-Update, IA-Level...)
    #define REG_CTRL_REG9             0x23  // ACC & Gyro Control Register 9: Gyro-Sleep enable, Temp-FIFO, Data avail. enable, I2C disable,
                                            //                                 FIFO Memory enable
    #define REG_CTRL_REG10            0x24  // ACC & Gyro Control Register 10: Self-Test enable
    #define REG_INT_GEN_SRC_XL        0x26  // ACC Interupt-quell Register: Interupt aktivieren, x,y,z-Achse Interupt Wahl ob bei High oder Low
    #define REG_STATUS_REG_1          0x27  // Gyro & ACC Status Register 1: ACC int. output, Gyro int. output, Inact. int. output, Boot running Flag
                                            //                               Temp New Data avail., Gyro & ACC New Data avail.
    #define REG_FIFO_CTRL             0x2E  // FIFO Control Register: FIFO-Mode Sel. Bits, FIFO threshold level setting
    #define REG_FIFO_SRC              0x2F  // FIFO Status Control Register: FIFO Schwelle & Overrun Status, Anzahl der ungelesenen samples im FIFO
    #define REG_INT_GEN_CFG_G         0x30  // Gyro Int. Gen. Status Register: &| kombi interupt events, Interupt request, x,y,z L&H int. enable
    #define REG_INT_GEN_THS_XH_G      0x31  // Gyro Int. Schwellen Register X-Achse H
    #define REG_INT_GEN_THS_XL_G      0x32  // Gyro Int. Schwellen Register X-Achse L
    #define REG_INT_GEN_THS_YH_G      0x33  // Gyro Int. Schwellen Register Y-Achse H
    #define REG_INT_GEN_THS_YL_G      0x34  // Gyro Int. Schwellen Register Y-Achse L
    #define REG_INT_GEN_THS_ZH_G      0x35  // Gyro Int. Schwellen Register Z-Achse H
    #define REG_INT_GEN_THS_ZL_G      0x36  // Gyro Int. Schwellen Register Z-Achse L
    #define REG_INT_GEN_DUR_G         0x37  // Gyro Int. Gen. Dauer Register: Exit from Int. wait enable, Enter/Exit duration value
    
    //Output Register Accelerometer
    #define REG_ACCEL_OUT_X_L_A       0x28  // ACC Output Register: X-Lowbyte
    #define REG_ACCEL_OUT_X_H_A       0x29  // ACC Output Register: X-Highbyte
    #define REG_ACCEL_OUT_Y_L_A       0x2A  // ACC Output Register: Y-Lowbyte
    #define REG_ACCEL_OUT_Y_H_A       0x2B  // ACC Output Register: Y-Highbyte
    #define REG_ACCEL_OUT_Z_L_A       0x2C  // ACC Output Register: Z-Lowbyte
    #define REG_ACCEL_OUT_Z_H_A       0x2D  // ACC Output Register: Z-Highbyte
    
    //Output Register Gyroskop
    #define REG_ACCEL_OUT_X_L_G       0x18  // Gyro Output Register: X-Lowbyte
    #define REG_ACCEL_OUT_X_H_G       0x19  // Gyro Output Register: X-Highbyte
    #define REG_ACCEL_OUT_Y_L_G       0x1A  // Gyro Output Register: Y-Lowbyte
    #define REG_ACCEL_OUT_Y_H_G       0x1B  // Gyro Output Register: Y-Highbyte
    #define REG_ACCEL_OUT_Z_L_G       0x1C  // Gyro Output Register: Z-Lowbyte
    #define REG_ACCEL_OUT_Z_H_G       0x1D  // Gyro Output Register: Z-Highbyte
    
    // Register Magnetsensor
    #define REG_WHO_AM_I_M            0x0F  // Mag Who_AM_I Register: zur identifikation des Sensors (Registerinhalt 0111101)
    #define REG_CTRL_REG1_M           0x20  // MAG Control Register 1: Temp Comp. enable, x,y-Achse OP Mode Sel.
                                            //                         , ODR sel., Fast-ODR enable, Self-test enable
    #define REG_CTRL_REG2_M           0x21  // MAG Control Register 2: Full Scale config, Reboot mem. content, Config reset Bit
    #define REG_CTRL_REG3_M           0x22  // MAG Control Register 3: LP-Mode Sel., SPI W oder R/W, OP-Mode Sel.
    #define REG_CTRL_REG4_M           0x23  // MAG Control Register 4: Z-Achse OP Mode Sel., Big-/Little Endian data Sel.
    #define REG_CTRL_REG5_M           0x24  // MAG Control Register 5: Fast-read enable, Block data update BIT
    #define REG_STATUS_REG_M          0x27  // MAG Status Register: x,y,z-Achse Data overrun, x,y,z-Achse new Data available
    #define REG_INT_CFG_M             0x30  // MAG Interupt Config Register: x,y,z-Achse Interups enable,
                                            //                               Int. active, Latch Int., INT_M Int. enable
    #define REG_INT_SRC_M             0x30  // MAG Interupt-quell Register: PTH-x,y,z, NTH-x,y,z , Überlauf der Mesurement-range, Int. event
    #define REG_INT_THS_L_M           0x32  // MAG Interupt-threshold Register: LOW
    #define REG_INT_THS_H_M           0x33  // MAG Interupt-threshold Register: High
    
    //Output Register Magnetsensor
    #define REG_MAG_OUT_X_L_M         0x28  // MAG Output Register: X-Lowbyte
    #define REG_MAG_OUT_X_H_M         0x29  // MAG Output Register: X-Highbyte
    #define REG_MAG_OUT_Y_L_M         0x2A  // MAG Output Register: Y-Lowbyte
    #define REG_MAG_OUT_Y_H_M         0x2B  // MAG Output Register: Y-Highbyte
    #define REG_MAG_OUT_Z_L_M         0x2C  // MAG Output Register: Z-Lowbyte
    #define REG_MAG_OUT_Z_H_M         0x2D  // MAG Output Register: Z-Highbyte
    
    //Mode und Scalierung-(Bits 4 und 5) +-2G: 0x00, +-4G = 0x10; +-8G = 0x20; +-16G = 0x30
    #define NormalLowPowerMode_PD     0x18  // Power down mode
    #define NormalLowPowerMode_10Hz   0x38
    #define NormalLowPowerMode_50Hz   0x58
    #define NormalLowPowerMode_119Hz  0x78
    
    
    //10Hz Data output rate and Temperature sensore disabled
    #define DataOutputRate_10Hz       0x10
    
    // +------------------------------------------------
    // +  Eigene Definitionen
    // +------------------------------------------------
    
    #define NN  16
    #define xTaster   0x01	// in Merker "ARBEIT" Bit für Taster
    #define xRead     0x02	// in Merker "ARBEIT" Bit für Lesen
    #define xTimer    0x04	// in Merker "ARBEIT" Bit für Timer
    #define xAuswert  0x08  // in Merker "ARBEIT" Bit für Auswert
    
    #define T_ON    0x02
    #define T_SET   0x02
    #define LED_ON  0x01
    #define LED_X   0x80
    #define T_OnOff 0x40   // Taster auf dem Erw.Sensor-Board
    
    #define LED_LL  0x01   // LED's für Bewegungs-Richtung
    #define LED_L   0x02   //   "
    #define LED_M   0x04   //   "
    #define LED_R   0x08   //   "
    #define LED_RR  0x10   //   "
    
    #define X_Wert 0				// Arrayplatz für X Wert
    #define Y_Wert 1				// Arrayplatz für Y Wert
    #define Z_Wert 2				// Arrayplatz für Z Wert
    
    #define  I2C_START  (UCB0CTL1 & UCTXSTT)
    #define  I2C_STOP   (UCB0CTL1 & UCTXSTP)
    #define  I2C_NACK   (UCB0STAT & UCNACKIFG)
    #define  I2C_BUSY   (UCB0STAT & UCBBUSY)
    #define  I2C_SCLLOW (UCB0STAT & UCSCLLOW)
    #define  TRUE 1
    #define  FALSE 0
    
    // für die übertragung über die Serielle Schnittstelle
    extern void Sub_TX_String_N(char *y);  // '\n' wird NICHT mit übertragen
    extern void Sub_TX_String(char *y);    // '\n' wird mit übertragen
    extern void INIT_UART1(void);
    extern void TX_BYTE(unsigned char x);
    extern void SubR_DW_TX(unsigned int x);
    
    // Prototypen
    void INIT_PORTS(void);					// Subroutine zum initialisieren der Ports
    
    void init_i2c_master(void);
    void init_i2c_master(void);
    unsigned char check_ack (unsigned char addr);
    unsigned char check_ack_V2 (unsigned char addr);
    
    
    unsigned char i2c_write_byte (unsigned char addr, unsigned char data);
    
    unsigned char i2c_write_bytes (unsigned char addr, unsigned char data_write[]);
    
    unsigned char i2c_read_byte (unsigned char addr, unsigned char read);
    
    unsigned char i2c_read_bytes (unsigned char addr, unsigned char data_cnt, unsigned char data_read[]);
    
    unsigned int i2c_Register_Lesen(unsigned char addr, unsigned char subaddr);
    
    void init_LSM9DS1(void);	// Subroutine zum einstellen der Status-Registerwerte
    
    //Variablen für Messwerte
    int array_size = 3;            	// Es werden 8 Werte pro Sensor benötigt
    int DATA_A [3];				// Array für Beschleunigung X,Y,Z
    int DATA_G [3];				// Array für Gyroskop X,Y,Z
    int DATA_M [3];				// Array für Magnetometer X,Y,Z
    
    unsigned char TX_Daten[2];
    unsigned char RX_Daten[3];
    
    // Subadressen der Sensoren Daten-Register
    const unsigned int sub_addr_A[6] = {0x28,0x29,0x2A,0x2B,0x2C,0x2D};
    const unsigned int sub_addr_G[6] = {0x18,0x19,0x1A,0x1B,0x1C,0x1D};
    const unsigned int sub_addr_M[6] = {0x28,0x29,0x2A,0x2B,0x2C,0x2D};
    
    // Felder für Mag.
    unsigned int MagX[NN];
    unsigned int MagY[NN];
    unsigned int MagZ[NN];
    // Felder für G - Beschleunigung
    unsigned int GX[NN];
    unsigned int GY[NN];
    unsigned int GZ[NN];
    // Felder für Winkel
    unsigned int WX[NN];
    unsigned int WY[NN];
    unsigned int WZ[NN];
    
    
    unsigned int ptr = 0;   // Pointer / Index der Ring.Speicher
    unsigned int dmy = 0;  // Pointer / Index für ......
    
    
    // +------------------------------------------------
    // +  Hauptprogramm
    // +------------------------------------------------
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
    // ACC Daten vom Sensor holen
        INIT_PORTS();
        INIT_UART1();
        Sub_TX_String("TEST\n");
        
        init_i2c_master();          // I2C Master Initialisieren
        init_LSM9DS1();		// Statusregister des LSM9DS1 voreinstellen
      
        while(1)                    // Hauptschleife
        {
          
        
                      int Box;      // Hilfsvariable zum zusammenlegen der Low und High-Byte Daten
                      
                      DATA_A [X_Wert] = i2c_Register_Lesen(LSM9SD1_ACC, sub_addr_A [1]); // Lowbyte x-Beschleunigung lesen 
        		  Box = DATA_A [X_Wert];
        		  Box = Box << 8;  // in Box steht jetzt das Lowbyte des Wertes
                      DATA_A [X_Wert] = i2c_Register_Lesen(LSM9SD1_ACC, sub_addr_A [2]); // Highbyte x-Beschleunigung lesen   
        		  DATA_A [X_Wert]= DATA_A [X_Wert] || Box;
          
         Sub_TX_String(" \n ACC-X\n");
         SubR_DW_TX(DATA_A [X_Wert]);
         Sub_TX_String(" \n ACC-Y\n");
         SubR_DW_TX(DATA_A [Y_Wert]);
         Sub_TX_String(" \n ACC-Z\n");
         SubR_DW_TX(DATA_A [Z_Wert]);
        		     
    
    
          	int i;
            i = 100000000;			// SW Delay
            __no_operation();
    	do i--;
    	while(i != 0);
    
        }
    }
    
    // +------------------------------------------------
    // +  Funktionen Aufträge
    // +------------------------------------------------
    
    
    
    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // + Funktion: INIT_PORTS()
    // +     Stand .....: 16.09.2015  / T.Sch
    // +
    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    void INIT_PORTS(void)	// Subroutine zum initialisieren der Ports
    {
        // INIT_Port_1
        P1REN = T_ON;
        P1OUT |= T_ON;
        //...............
        P1OUT &= ~(LED_ON);
        P1DIR |= LED_ON;
        P1IES  = 0;
        P1SEL  &= ~(T_ON);
        P1IE   |= T_ON;      // Int. aktiv
        P1IFG  = 0;
    
        // Taster auf Sensor_Board
        P1SEL  &= ~(T_OnOff);
        P1DIR  &= ~(T_OnOff);
        P1IES  |= T_OnOff;      // Pos. Flanke
        P1IE   |= T_OnOff;      // Int. aktiv
        P1IFG  = 0;
    
        // INIT_Port_2
        P2REN = T_SET;
        P2OUT |= T_SET;
        //...............
        P2IES  = 0;
        P2SEL &= ~(T_SET);
        P2IE  &= ~(T_SET);    // T_SET noch nicht freigeben
        P2IFG  = 0;
    
        // INIT_Port_4
        P4OUT &= ~(LED_X);
        P4DIR |= LED_X;
        P4SEL &=  ~(LED_X);
    
    
        // INIT_Port_6     // LED's für Richtung
        P6OUT |= LED_LL + LED_L + LED_M + LED_R + LED_RR;     // Alle auf "H" -> AUS
        P6DIR |= LED_LL + LED_L + LED_M + LED_R + LED_RR;     // Alle als OUT
        P6SEL &= ~(LED_LL + LED_L + LED_M + LED_R + LED_RR) ; // Alle BIN-IO
    }
    
    // +-------------------------------------------------
    // +  SubRoutinen I2C
    // +-------------------------------------------------
    void init_i2c_master(void)
    {
      P3SEL |= BIT0+BIT1;                       // Setzen I2C Pins -> USCI_B0
      UCB0CTL1 |= UCSWRST;                      // Enable SW reset Bereit füt INIT
      UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
      UCB0BR0 = 14;                             // fSCL = SMCLK/12 = ~100kHz
      UCB0BR1 = 0;
      UCB0I2CSA = 0x48;                         // Slave Address
      UCB0CTL1 &= ~UCSWRST;                     // INIT abgeschlossen
      UCB0IE |= UCTXIE ;                        // Enable TX interrupt
    }
    
    unsigned char check_ack (unsigned char addr)
    {
      UCB0I2CSA =addr;
      //UCB0CTL1|= UCTR + UCTXSTT + UCTXSTP;
      UCB0CTL1|= UCTXSTT+UCTR  ;
      return (!I2C_NACK);
    }
    
    /*!
     * \brief Adresse auf ACK testen (IC Antwortet)
     * \param addr  I²C Slave Adresse
     * \return TRUE wenn Adresse existiert und antwortet, FALSE wenn keine Antwort von Adresse kommt
     */
    unsigned char check_ack_V2 (unsigned char addr)
    {
      UCB0I2CSA = addr;
    
      UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP;       // I2C TX, Start/Stop senden
      while (I2C_START);                          // Warten bis Start und Adresse gesendet
      while (I2C_STOP);                           // Warten bis Stop gesendet
    
      return (!I2C_NACK);                         // ACK/NACK?
    }
    
    
    unsigned char i2c_write_byte (unsigned char addr, unsigned char data)
    {
      UCB0STAT &=~UCNACKIFG;
     // if(I2C_BUSY) return 0;
      if(I2C_SCLLOW) return 0;
      UCB0I2CSA = addr;
      //UCB0CTL1 |=  UCTXSTT;
       //while ( I2C_START);
      UCB0TXBUF = data;
      while (!(UCB0IFG&UCTXIFG));
      while (I2C_START && I2C_NACK);
      if (I2C_NACK) return 0;
    //  UCB0CTL1 |=UCTXSTP;
    //  while (I2C_STOP && !I2C_NACK);
      if (I2C_NACK) return 0;
      return 1;
    }
    
    
    unsigned char i2c_write_bytes (unsigned char addr, unsigned char data_write[])
    {
      unsigned int  i = 0;
      unsigned int ll;
    
      UCB0STAT &=~UCNACKIFG;
      //if (I2C_BUSY)   return FALSE;
      if (I2C_SCLLOW) return FALSE;
    
      UCB0I2CSA = addr;                   // Slave Adresse setzen
    
      UCB0CTL1 |= UCTR + UCTXSTT;         // I2C TX, Start senden
      //UCB0TXBUF = (unsigned char *)data_to_write++;
    
     // if (I2C_NACK) return FALSE;         // Bei NACK sofort raus
    
      for(i = 0; i < 2; i++)
      {
    
       // if (I2C_NACK) return FALSE;       // Bei NACK sofort raus
    
        UCB0TXBUF = data_write[i];               // Load TX buffer
    
          ll = 100;
          while (ll>0) ll--;
        
        //while (!(UCB0IFG & UCTXIFG));    // Buffer bereit?
        i++;
      }
      
      
    return TRUE;
    }
    
    unsigned char i2c_read_byte (unsigned char addr, unsigned char read)
    {
      UCB0STAT &=~UCNACKIFG;
      if (I2C_BUSY)   return FALSE;
      if (I2C_SCLLOW) return FALSE;
    
      UCB0I2CSA = addr;                   // Slave Adresse setzen
    
      UCB0CTL1 &=~UCTR;                   // I2C RX
      UCB0CTL1 |= UCTXSTT;                // Start senden
    
      while(I2C_START && !I2C_NACK);      // Warten bis Start und Adresse gesendet
      if (I2C_NACK) return FALSE;         // Bei NACK sofort raus
    
      UCB0CTL1 |= UCTXSTP;                // Stop senden
    
      while (!(UCB0IFG & UCRXIFG));        // Buffer bereit?
      read = UCB0RXBUF;
    
      while(I2C_STOP);                    // Warten bis Stop gesendet
    
      return TRUE;
    }
    
    
    unsigned char i2c_read_bytes (unsigned char addr, unsigned char data_cnt, unsigned char data_read[])
    {
      unsigned int  i;
    
      UCB0STAT &=~UCNACKIFG;
      if (I2C_BUSY)   return FALSE;
      if (I2C_SCLLOW) return FALSE;
    
      UCB0I2CSA = addr;                   // Slave Adresse setzen
    
      UCB0CTL1 &=~UCTR;                   // I2C RX
      UCB0CTL1 |= UCTXSTT;                // Start senden
    
      while(I2C_START && !I2C_NACK);      // Warten bis Start und Adresse gesendet
      if (I2C_NACK) return FALSE;         // Bei NACK sofort raus
    
      for(i = 0; i < data_cnt; i++)
      {
        if (data_cnt == i + 1)            // Letztes Byte?
          UCB0CTL1 |= UCTXSTP;            // Stop senden
        
        while (!(UCB0IFG & UCRXIFG));      // Buffer bereit?
        data_read[i] = UCB0RXBUF;
      }
      
      while(I2C_STOP);                    // Warten bis Stop gesendet
    
      return TRUE;
    }
    
    // +-------------------------------------------------
    // +  SubRoutinen LSM9DS1
    // +-------------------------------------------------
    void init_LSM9DS1(void)					// Subroutine zum einstellen der Registerwerte
    {        
    	  //Configuration
              Sub_TX_String("init_LSM9SD1 Config OK\n");
              
    	  //Aktiviere Beschleunigungssensor (Slave: LSM9SD1_ACC, SubSlave: REG_CTRL_REG6_XL, Reg-Inhalt: NormalLowPowerMode_10Hz)
              TX_Daten[0] = REG_CTRL_REG6_XL;
    	  TX_Daten[1] = NormalLowPowerMode_10Hz;
              Sub_TX_String("ACC_1 OK\n");
              
    	  i2c_write_bytes (0x6A, TX_Daten);
              Sub_TX_String("ACC OK\n");
              
    	  //Aktiviere Gyroskop (Slave: LSM9SD1_ACC, SubSlave: REG_CTRL_REG1_G, Reg-Inhalt: 0x78)
    	  TX_Daten[0] = REG_CTRL_REG1_G;		// Registeradresse zum Einstellen des Continuous-conversion mode
    	  TX_Daten[1] = 0x78;					// Registerwertes des 14,6Hz Output Datarate (0x20)
    	  i2c_write_bytes (LSM9SD1_ACC, TX_Daten);
              Sub_TX_String("Gyro OK\n");
              
    	  //Aktiviere Magnetsensor (Slave: LSM9SD1_MAG, SubSlave: REG_CTRL_REG3_M, Reg-Inhalt: 0x00)
    	  TX_Daten[0] = REG_CTRL_REG3_M;		// Registeradresse zum Einstellen des Continuous-conversion mode
    	  TX_Daten[1] = 0x00;					// Registerwertes des Continuous-conversion mode
    	  i2c_write_bytes (LSM9SD1_MAG, TX_Daten);
              Sub_TX_String("Magnet OK\n");
    }
    
    // +-------------------------------------------------
    // +  SubRoutinen Daten Holen und vorbereiten
    // +-------------------------------------------------
    unsigned int i2c_Register_Lesen(unsigned char addr, unsigned char subaddr)
    {
            Sub_TX_String("Register_Lesen OK\n");
    	unsigned char Wert = 0;
    	i2c_write_byte(addr, subaddr);
    	i2c_read_byte(addr, Wert);
    	return (Wert);
    }
    

  • Hello Timo,

    You will need to provide a lot more information describing why you believe the function mentioned is at fault. Debugger and oscilloscope screen shots with a description of where the issues can be found would be appreciated.

    Regards,
    Ryan

**Attention** This is a public forum