I try to use an example program i2c_master_rw_repeated_start-master_code.c, ti/mspware/MSPWare_2_30_00_49/driverlib/examples/MSP432P4xx/i2c/ in my app, but found it is not easy. Below is the code, into which I have inserted my questions in their places.
Please help, any answer will be appreciate greatly.
/******************************************************************************
* MSP432 I2C - EUSCI_B0_MODULE I2C Master TX bytes to MSP432 Slave - Repeated Start
*
* Description: This demo connects two MSP432 's via the I2C bus. The master
* transmits to the slave. This is the MASTER CODE. It continuously
* transmits an array of data and demonstrates how to implement an I2C
* master transmitter sending multiple bytes followed by a repeated start,
* followed by a read of multiple bytes. This is a common operation for
* reading register values from I2C slave devices such as sensors. The
* transaction for the I2C that is written looks as follows:
*
* ________________________________________________________________
* | Start | | | Start | | |
* | 0x48Addr | 0x04 | 0x00 | 0x48Addr | <10 Byte Read> | Stop |
* | W | | | R | | |
* |__________|______|______|__________|___________________|_______|
*
* ACLK = n/a, MCLK = HSMCLK = SMCLK = BRCLK = default DCO = ~3.0MHz
*
* /|\ /|\
* MSP432P401 10k 10k MSP432P401
* slave | | master
* ----------------- | | -----------------
* | P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA |
* | | | | |
* | | | | |
* | P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL |
* | | | |
*
* Author: Timothy Logan
*****************************************************************************/
/* DriverLib Defines */
#include "driverlib.h"
/* Standard Defines */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
/* Slave Address for I2C Slave */
#define SLAVE_ADDRESS 0x48
#define NUM_OF_REC_BYTES 10
/* Variables */
const uint8_t TXData[2] = {0x04, 0x00};
static uint8_t RXData[NUM_OF_REC_BYTES];
static volatile uint32_t xferIndex;
static volatile bool stopSent;
/* I2C Master Configuration Parameter */
const eUSCI_I2C_MasterConfig i2cConfig =
{
EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
3000000, // SMCLK = 3MHz
EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 100khz
0, // No byte counter threshold
EUSCI_B_I2C_NO_AUTO_STOP // No Autostop
};
int main(void)
{
volatile uint32_t ii;
/* Disabling the Watchdog */
MAP_WDT_A_holdTimer();
/* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,
* (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).
*/
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
stopSent = false;
memset(RXData, 0x00, NUM_OF_REC_BYTES);
/* Initializing I2C Master to SMCLK at 400kbs with no autostop */
MAP_I2C_initMaster(EUSCI_B0_MODULE, &i2cConfig);
/* Specify slave address */
MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS);
/* Set Master in transmit mode */
MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);
/* Enable I2C Module to start operations */
MAP_I2C_enableModule(EUSCI_B0_MODULE);
/* Enable and clear the interrupt flag */
MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE,
EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
Q. 1: it should be Transmit interrupt
//Enable master Receive interrupt
MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
MAP_Interrupt_enableSleepOnIsrExit();
MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
while (1)
{
/* Making sure the last transaction has been completely sent out */
while (MAP_I2C_masterIsStopSent(EUSCI_B0_MODULE) == EUSCI_B_I2C_SENDING_STOP);
/* Send start and the first byte of the transmit buffer. We have to send
* two bytes to clean out whatever is in the buffer from a previous
* send */
Q. 2: Is this so called repeated start?
MAP_I2C_masterSendMultiByteStart(EUSCI_B0_MODULE, TXData[0]);
MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[0]);
Q. 3: done just a few lines early, why do it again? A waste or a must?
/* Enabling transfer interrupt after stop has been sent */
MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
/* While the stop condition hasn't been sent out... */
while(!stopSent)
{
MAP_PCM_gotoLPM0InterruptSafe();
}
stopSent = false;
}
}
/*******************************************************************************
* eUSCIB0 ISR. The repeated start and transmit/receive operations happen
* within this ISR.
*******************************************************************************/
void euscib0_isr(void)
{
uint_fast16_t status;
status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_MODULE);
MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE, status);
Q. 4: It says it will change the mode, but didn’t do it.
/* If we reached the transmit interrupt, it means we are at index 1 of
* the transmit buffer. When doing a repeated start, before we reach the
* last byte we will need to change the mode to receive mode, set the start
* condition send bit, and then load the final byte into the TXBUF.
*/
if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
{
MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[1]);
MAP_I2C_disableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_MODE);
xferIndex = 0;
MAP_I2C_masterReceiveStart(EUSCI_B0_MODULE);
MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
}
/* Receives bytes into the receive buffer. If we have received all bytes,
* send a STOP condition */
if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
{
if(xferIndex == NUM_OF_REC_BYTES - 2) xferIndex = 8
{
Q. 5: There is a byte still not received, why stop it?
MAP_I2C_masterReceiveMultiByteStop(EUSCI_B0_MODULE);
Q. 6: It stoped already, why this line can be executed?
RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_MODULE);
}
else if(xferIndex == NUM_OF_REC_BYTES - 1)
{
RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_MODULE);
MAP_I2C_disableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
Q. 7: will stop condition send in this mode set function?
MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);
xferIndex = 0;
stopSent = true;
Q. 8: why disableSleepOnIsrExit() here
MAP_Interrupt_disableSleepOnIsrExit();
}
else
{
RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_MODULE);
}
}
}