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.

Reading multiple bytes over I2C on the MSP432

Generally, the problem is with reading multiple bytes at a time from an I2C slave device, using the MSP432 as a master device. Specifically, I am trying to read data from the Honeywell 6131 Humidity/Temperature sensor connected to the MSP432 on P1.6 and P1.7, as SDA and SCL respectively. The code I’m using is a slightly modified code from an example on TI Resource Explorer. I commented out the lines I added. Basically, I set a clock frequency for the CPU, and also initialized a UART module transmitting through P1.3 as TX line. The code is basically reading 4 bytes a time from a certain register on the Honeywell sensor, and sending these reading over UART.
The problem is I’m getting the same values for the four different bytes all the time. With Arduino, these values fluctuate slightly with time, and they change significantly when I blow up on the sensor (change humidity/temperature). The .C file code I am running on the MSP432 is below. The only issue I could think of is timing for I2C with reading from specific devices, which there is not any information on in the datasheets of the sensors I have. You also mentioned using interrupts in the solution, and I have no problem with this.

/* --COPYRIGHT--,BSD_EX
* Copyright (c) 2014, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************
*
* MSP432 CODE EXAMPLE DISCLAIMER
*
* MSP432 code examples are self-contained low-level programs that typically
* demonstrate a single peripheral function or device feature in a highly
* concise manner. For this the code may rely on the device's power-on default
* register values and settings such as the clock configuration and care must
* be taken when combining code from several examples to avoid potential side
* effects. Also see www.ti.com/.../mspdriverlib for an API functional
* library & https://dev.ti.com/pinmux/ for a GUI approach to peripheral configuration.
*
* --/COPYRIGHT--*/
//******************************************************************************
// MSP432P401 Demo - eUSCI_B0 I2C Master RX multiple bytes from MSP432 Slave
//
// Description: This demo connects two MSP432's via the I2C bus. The master
// reads 5 bytes from the slave. This is the MASTER CODE. The data from the slave
// transmitter begins at 0 and increments with each transfer.
// The USCI_B0 RX interrupt is used to know when new data has been received.
//
// *****used with "MSP432P401_euscib0_i2c_11.c"****
//
// /|\ /|\
// MSP432P401 10k 10k MSP432P401
// slave | | master
// ----------------- | | -----------------
// | P1.6/UCB0SDA|<-|----|->|P1.6/UCB0SDA |
// | | | | |
// | | | | |
// | P1.7/UCB0SCL|<-|------>|P1.7/UCB0SCL |
// | | | P1.0|--> LED
//
// Wei Zhao
// Texas Instruments Inc.
// June 2014
// Built with Code Composer Studio V6.0
//******************************************************************************
#include "msp.h"
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
#include <stddef.h>
#include <driverlib.h>

uint8_t RXData = 0;


// For the UART module config.
const eUSCI_UART_Config uartConfig= {
EUSCI_A_UART_CLOCKSOURCE_SMCLK,
156,
4,
0,
EUSCI_A_UART_NO_PARITY,
EUSCI_A_UART_LSB_FIRST,
EUSCI_A_UART_ONE_STOP_BIT,
EUSCI_A_UART_MODE,
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION
};


int main(void)
{
volatile uint32_t i;
WDTCTL = WDTPW | WDTHOLD;

// Clock Initialization was added by me to this example
MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_24);

MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);

// UART Module initialization
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
UART_initModule(EUSCI_A0_MODULE, &uartConfig);
UART_enableModule(EUSCI_A0_MODULE);


// Configure GPIO
P1SEL0 |= BIT6 | BIT7; // I2C pins

__enable_interrupt();
NVIC_ISER0 = 1 << ((INT_EUSCIB0 - 16) & 31); // Enable eUSCIB0 interrupt in NVIC module
// Configure USCI_B0 for I2C mode
UCB0CTLW0 |= UCSWRST; // Software reset enabled
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync
UCB0CTLW1 |= UCASTP_2; // Automatic stop generated
// after UCB0TBCNT is reached
UCB0BRW = 0x0018; // baudrate = SMCLK / 8
UCB0TBCNT = 0x0004; // number of bytes to be received
UCB0I2CSA = 0x0027; // Slave address
UCB0CTLW0 &= ~UCSWRST;
UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;

while (1)
{

for (i = 20000; i > 0; i--);
while (UCB0CTLW0 & UCTXSTP); // Ensure stop condition got sent
UCB0CTLW0 |= UCTXSTT; // I2C start condition

__sleep(); // Go to LPM0
}
}

// I2C interrupt service routine
void eUSCIB0IsrHandler(void)
{
if (UCB0IFG & UCNACKIFG)
{
UCB0IFG &= ~ UCNACKIFG;
SCB_SCR |= SCB_SCR_SLEEPONEXIT; // Don't wake up on exit from ISR
UCB0CTLW0 |= UCTXSTT; // I2C start condition
}
if (UCB0IFG & UCRXIFG0)
{
UCB0IFG &= ~ UCRXIFG0;
SCB_SCR &= ~SCB_SCR_SLEEPONEXIT; // Wake up on exit from ISR
RXData = UCB0RXBUF; // Get RX data
UART_transmitData(EUSCI_A0_MODULE, RXData); // Added line to send bytes recieved from I2C over UART
}
if (UCB0IFG & UCBCNTIFG)
{
UCB0IFG &= ~ UCBCNTIFG;
SCB_SCR |= SCB_SCR_SLEEPONEXIT; // Don't wake up on exit from ISR
P1OUT ^= BIT0; // Toggle LED on P1.0
}

}

  •  Mohammed,

    After seeing the screen capture of SDA Line, the shark fin pattern indicates that your pull up resistors are too large. Try 3.5 kOhm and let me know what that does. you may need to go even lower.

  • I tried going lower. I tried 4K7, 3K3, and 1K and got the same bytes all the byte. On the Oscope, The SDA signal looked like the clock one when I used the 3K5 and 1K resistors.
  • Mohammed,

    Unfortunately, I don't have one of these sensors, so bear with me.

    I think you're right it's a timing issue. But getting those sharkfins out of the picture was a step in the right direction.

    Can you get a screen capture of both your data and your clock on the same screen in the same time domain, and at an amplitude that will match the wave heights?

    We are looking for a signal that looks like this:

    I noticed you have some spikes in your clock signal (I'm assuming these are not the signal themselves) that could be contributing to the issue. Do you know what is causing these? It's likely another communication line crossing your i2c line, this could be from the UART which we could test with a delay. If these spikes are your SCL signal, then this is a big problem, since i2c SCL should be a 50% duty cycle. Maybe send me a picture of your setup?

    This duty cycle also need to conform to the sensors T_low and T_high in fig 6 of sensing.honeywell.com/index.php

    If I'm following your code modifications correctly. You're SCL frequency at a nominal 375 kHz, but could be as much as 500 kHz, which violates the sensor's max SCL frequency. Try setting  DIVS in the CSCTL1 register to 001 or even 010. This should drop you down to 185 kHz nom, 250 kHz max.

    Finally, you may want to comment out the UART send and print statements in the ISR, add a break point and see watch the RxData variable, this could also be the problem.

    Let me know what you find.

    Best regards,

    Cameron

  • Cameron,

    For some reason I can't zoom into the clock signal on the oscilloscope. It always looks like spikes. I even tried commanding the sensor with Arduino. I was able to read from the sensor over I2C and send the data back over UART without any problem. However, I still get the spikes for the clock line on the oscilloscope although the system was working fine. It seems that the oscilloscope/probe circuit is interfering somehow with my circuit. I also tried on the MSP432 launchpad without using UART.

    I also reset the value in the CSCTL1 register, and tried different values, but I had the same issue. Please let me know how a logic analyzer could help in this case. I will send you a picture of my setup shortly.

    Thanks,

  • Have you made any progress on this issue? If so I'd like to close it out. Otherwise, let me know how I can help!!


    Best ,
    Cameron
  • Closing this due to inactivity.
  • Hi Cameron,

    Sorry for the delay, and thank you for the help. I actually found this: e2e.ti.com/.../448013
    helpful, and it solved my problem.

**Attention** This is a public forum