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.
HI,
I am using MSP430FR5969 Launchpad and Trying to configure the MSP430 as I2C master and connect to slave device . I am using the Driverlib I2C driver "eusci_b_i2c.c - Driver for the eusci_b_i2c Module" and my configuration are below
EUSCI_B_I2C_initMasterParam param;
param.selectClockSource=EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
param.i2cClk=CS_getSMCLK();
param.dataRate=EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
param.byteCounterThreshold=0x0;
param.autoSTOPGeneration=EUSCI_B_I2C_NO_AUTO_STOP;
EUSCI_B_I2C_initMaster(EUSCI_B0_BASE,¶m);
What I observe is the I2C clock line frequently has a spike of about "80ns pulse " between a 1 clock cycle . Have attached the snippet of the same below
I am not sure why this spike is seen . sometimes I write are treated as Read commands because of spike becoming a valid clock pulse
Hi Ryan,
I am not able to find the version of driverlib . But I have attached the same for reference .
I tried changing the I2C data rate ,but had the same issue [ 100khz and even lesser also ]. I can try to replicate without slave connected and confirm .
The pulse does not interrupt the communicated, but the transaction and data is misinterpreted like write command is interpreted as read command and data also .
/* --COPYRIGHT--,BSD * 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. * --/COPYRIGHT--*/ //***************************************************************************** // // eusci_b_i2c.c - Driver for the eusci_b_i2c Module. // //***************************************************************************** //***************************************************************************** // //! \addtogroup eusci_b_i2c_api eusci_b_i2c //! @{ // //***************************************************************************** #include "inc/hw_regaccess.h" #include "inc/hw_memmap.h" #ifdef __MSP430_HAS_EUSCI_Bx__ #include "eusci_b_i2c.h" #include <assert.h> void EUSCI_B_I2C_initMaster(uint16_t baseAddress, EUSCI_B_I2C_initMasterParam *param) { uint16_t preScalarValue; //Disable the USCI module and clears the other bits of control register HWREG16(baseAddress + OFS_UCBxCTLW0) = UCSWRST; //Configure Automatic STOP condition generation HWREG16(baseAddress + OFS_UCBxCTLW1) &= ~UCASTP_3; HWREG16(baseAddress + OFS_UCBxCTLW1) |= param->autoSTOPGeneration; //Byte Count Threshold HWREG16(baseAddress + OFS_UCBxTBCNT) = param->byteCounterThreshold; /* * Configure as I2C master mode. * UCMST = Master mode * UCMODE_3 = I2C mode * UCSYNC = Synchronous mode */ HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCMST + UCMODE_3 + UCSYNC; //Configure I2C clock source HWREG16(baseAddress + OFS_UCBxCTLW0) |= (param->selectClockSource + UCSWRST); /* * Compute the clock divider that achieves the fastest speed less than or * equal to the desired speed. The numerator is biased to favor a larger * clock divider so that the resulting clock is always less than or equal * to the desired clock, never greater. */ preScalarValue = (uint16_t)(param->i2cClk / param->dataRate); HWREG16(baseAddress + OFS_UCBxBRW) = preScalarValue; } void EUSCI_B_I2C_initSlave(uint16_t baseAddress, EUSCI_B_I2C_initSlaveParam *param) { //Disable the USCI module HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST; //Clear USCI master mode HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCMST; //Configure I2C as Slave and Synchronous mode HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCMODE_3 + UCSYNC; //Set up the slave address. HWREG16(baseAddress + OFS_UCBxI2COA0 + param->slaveAddressOffset) = param->slaveAddress + param->slaveOwnAddressEnable; } void EUSCI_B_I2C_enable(uint16_t baseAddress) { //Reset the UCSWRST bit to enable the USCI Module HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~(UCSWRST); } void EUSCI_B_I2C_disable(uint16_t baseAddress) { //Set the UCSWRST bit to disable the USCI Module HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST; } void EUSCI_B_I2C_setSlaveAddress(uint16_t baseAddress, uint8_t slaveAddress) { //Set the address of the slave with which the master will communicate. HWREG16(baseAddress + OFS_UCBxI2CSA) = (slaveAddress); } void EUSCI_B_I2C_setMode(uint16_t baseAddress, uint8_t mode) { HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~EUSCI_B_I2C_TRANSMIT_MODE; HWREG16(baseAddress + OFS_UCBxCTLW0) |= mode; } uint8_t EUSCI_B_I2C_getMode(uint16_t baseAddress) { //Read the I2C mode. return ((HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTR)); } void EUSCI_B_I2C_slavePutData(uint16_t baseAddress, uint8_t transmitData) { //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = transmitData; } uint8_t EUSCI_B_I2C_slaveGetData(uint16_t baseAddress) { //Read a byte. return (HWREG16(baseAddress + OFS_UCBxRXBUF)); } uint16_t EUSCI_B_I2C_isBusBusy(uint16_t baseAddress) { //Return the bus busy status. return (HWREG16(baseAddress + OFS_UCBxSTATW) & UCBBUSY); } uint16_t EUSCI_B_I2C_masterIsStopSent(uint16_t baseAddress) { return (HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTP); } uint16_t EUSCI_B_I2C_masterIsStartSent(uint16_t baseAddress) { return (HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTT); } void EUSCI_B_I2C_enableInterrupt(uint16_t baseAddress, uint16_t mask) { //Enable the interrupt masked bit HWREG16(baseAddress + OFS_UCBxIE) |= mask; } void EUSCI_B_I2C_disableInterrupt(uint16_t baseAddress, uint16_t mask) { //Disable the interrupt masked bit HWREG16(baseAddress + OFS_UCBxIE) &= ~(mask); } void EUSCI_B_I2C_clearInterrupt(uint16_t baseAddress, uint16_t mask) { //Clear the I2C interrupt source. HWREG16(baseAddress + OFS_UCBxIFG) &= ~(mask); } uint16_t EUSCI_B_I2C_getInterruptStatus(uint16_t baseAddress, uint16_t mask) { //Return the interrupt status of the request masked bit. return (HWREG16(baseAddress + OFS_UCBxIFG) & mask); } uint16_t EUSCI_B_I2C_masterSendSingleByte(uint16_t baseAddress, uint8_t txData) { uint16_t status=0; //Store current TXIE status uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG)); //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG)); //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; //Clear transmit interrupt flag before enabling interrupt again HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG); //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; return status; } uint8_t EUSCI_B_I2C_masterReceiveSingleByte(uint16_t baseAddress) { uint16_t status=0; //Set USCI in Receive mode HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCTR; //Send start HWREG16(baseAddress + OFS_UCBxCTLW0) |= (UCTXSTT + UCTXSTP); //Poll for receive interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCRXIFG)); //Send single byte data. return (HWREG16(baseAddress + OFS_UCBxRXBUF)); } uint16_t EUSCI_B_I2C_masterSendSingleByteWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout) { uint16_t status=0x0; // Creating variable for second timeout scenario uint32_t timeout2 = timeout; //Store current TXIE status uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG) && --timeout); //Check if transfer timed out if(timeout == 0) { return status; } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Poll for Transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG) && --timeout2); //Check if transfer timed out if(timeout2 == 0) { return status; } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; //Clear transmit interrupt flag before enabling interrupt again HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG); //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; return (status); } void EUSCI_B_I2C_masterSendMultiByteStart(uint16_t baseAddress, uint8_t txData) { //Store current transmit interrupt enable uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; //Poll for transmit interrupt flag. while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) { ; } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; } bool EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout) { //Store current transmit interrupt enable uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; //Poll for transmit interrupt flag. while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) { ; } //Check if transfer timed out if(timeout == 0) { return (STATUS_FAIL); } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; return(STATUS_SUCCESS); } void EUSCI_B_I2C_masterSendMultiByteNext(uint16_t baseAddress, uint8_t txData) { //If interrupts are not used, poll for flags if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)) { //Poll for transmit interrupt flag. while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) { ; } } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; } bool EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout) { //If interrupts are not used, poll for flags if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)) { //Poll for transmit interrupt flag. while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) { ; } //Check if transfer timed out if(timeout == 0) { return (STATUS_FAIL); } } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; return(STATUS_SUCCESS); } void EUSCI_B_I2C_masterSendMultiByteFinish(uint16_t baseAddress, uint8_t txData) { //If interrupts are not used, poll for flags if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)) { //Poll for transmit interrupt flag. while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) { ; } } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Poll for transmit interrupt flag. while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) { ; } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; } bool EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout) { uint32_t timeout2 = timeout; //If interrupts are not used, poll for flags if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)) { //Poll for transmit interrupt flag. while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) { ; } //Check if transfer timed out if(timeout == 0) { return (STATUS_FAIL); } } //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData; //Poll for transmit interrupt flag. while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout2) { ; } //Check if transfer timed out if(timeout2 == 0) { return (STATUS_FAIL); } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; return(STATUS_SUCCESS); } void EUSCI_B_I2C_masterSendStart(uint16_t baseAddress) { HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTT; } void EUSCI_B_I2C_masterSendMultiByteStop(uint16_t baseAddress) { //If interrupts are not used, poll for flags if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)) { //Poll for transmit interrupt flag. while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) { ; } } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; } bool EUSCI_B_I2C_masterSendMultiByteStopWithTimeout(uint16_t baseAddress, uint32_t timeout) { //If interrupts are not used, poll for flags if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)) { //Poll for transmit interrupt flag. while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) { ; } //Check if transfer timed out if(timeout == 0) { return (STATUS_FAIL); } } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; return (STATUS_SUCCESS); } void EUSCI_B_I2C_masterReceiveStart(uint16_t baseAddress) { //Set USCI in Receive mode HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCTR; //Send start HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTT; } uint8_t EUSCI_B_I2C_masterReceiveMultiByteNext(uint16_t baseAddress) { return (HWREG16(baseAddress + OFS_UCBxRXBUF)); } uint8_t EUSCI_B_I2C_masterReceiveMultiByteFinish(uint16_t baseAddress) { //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; //Wait for Stop to finish while(HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTP) { // Wait for RX buffer while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG)) { ; } } //Capture data from receive buffer after setting stop bit due to //MSP430 I2C critical timing. return (HWREG16(baseAddress + OFS_UCBxRXBUF)); } bool EUSCI_B_I2C_masterReceiveMultiByteFinishWithTimeout(uint16_t baseAddress, uint8_t *txData, uint32_t timeout) { uint32_t timeout2 = timeout; //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; //Wait for Stop to finish while((HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTP) && --timeout) { ; } //Check if transfer timed out if(timeout == 0) { return (STATUS_FAIL); } // Wait for RX buffer while((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG)) && --timeout2) { ; } //Check if transfer timed out if(timeout2 == 0) { return (STATUS_FAIL); } //Capture data from receive buffer after setting stop bit due to //MSP430 I2C critical timing. *txData = (HWREG8(baseAddress + OFS_UCBxRXBUF)); return (STATUS_SUCCESS); } void EUSCI_B_I2C_masterReceiveMultiByteStop(uint16_t baseAddress) { //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; } void EUSCI_B_I2C_enableMultiMasterMode(uint16_t baseAddress) { HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST; HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCMM; } void EUSCI_B_I2C_disableMultiMasterMode(uint16_t baseAddress) { HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST; HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCMM; } uint8_t EUSCI_B_I2C_masterReceiveSingle(uint16_t baseAddress) { //Polling RXIFG0 if RXIE is not enabled if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCRXIE0)) { while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG0)) { ; } } //Read a byte. return (HWREG16(baseAddress + OFS_UCBxRXBUF)); } uint32_t EUSCI_B_I2C_getReceiveBufferAddress(uint16_t baseAddress) { return (baseAddress + OFS_UCBxRXBUF); } uint32_t EUSCI_B_I2C_getTransmitBufferAddress(uint16_t baseAddress) { return (baseAddress + OFS_UCBxTXBUF); } uint16_t EUSCI_B_I2C_masterSendMultiByte(uint16_t baseAddress, uint8_t *txData, uint8_t num_of_bytes) { uint8_t i; uint16_t status=0; //Store current TXIE status uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG)); for (i=0;i < num_of_bytes;i++) { //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData[i]; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG)); } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; //Clear transmit interrupt flag before enabling interrupt again HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG); //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; return status; } uint16_t EUSCI_B_I2C_masterSendMultiBytetimeout(uint16_t baseAddress, uint8_t *txData, uint8_t num_of_bytes,uint8_t timeout) { uint8_t i; uint16_t status=0; uint8_t timeout2=timeout; //Store current TXIE status uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE; //Disable transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE); //Send start condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG) && --timeout); if (timeout==0) { return status; } for (i=0;i < num_of_bytes;i++) { //Send single byte data. HWREG16(baseAddress + OFS_UCBxTXBUF) = txData[i]; //Poll for transmit interrupt flag. do { status=HWREG16(baseAddress + OFS_UCBxIFG); }while(!(status & UCTXIFG) && --timeout2); if (timeout2==0) { return status; } } //Send stop condition. HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP; //Clear transmit interrupt flag before enabling interrupt again HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG); //Reinstate transmit interrupt enable HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus; return status; } #endif //***************************************************************************** // //! Close the doxygen group for eusci_b_i2c_api //! @} // //*****************************************************************************
**Attention** This is a public forum