I'm new to this so I may have done something stupid. When I run my code, the msp430 (master) does an extra byte read instead of sending the stop code. I'm attaching the logic analyzer. Thanks!
code (I bolded the parts I thought relevant):
#include <msp430.h>
#include "gy-80_config.h"
int RXByteCtr, RPT_Flag = 0; // enables repeated start when 1
volatile unsigned char RxBuffer[128]; // Allocate 128 byte of RAM
unsigned char TxData; // TX data
unsigned char *PRxData; // Pointer to RX data
unsigned char TXByteCtr, RX = 0;
void Setup_TX(unsigned char );
void Setup_RX(unsigned char );
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
while(1){
//Transmit process
Setup_TX(ACCE_ADDR);
TXByteCtr = 1;
TxData = ACCE_DEVID;
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
//Receive process
Setup_RX(ACCE_ADDR);
PRxData = (unsigned char *)RxBuffer; // Start of RX buffer
RXByteCtr = 1; // Load RX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTXSTT; // I2C start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
}
//-------------------------------------------------------------------------------
// The USCI_B0 data ISR is used to move received data from the I2C slave
// to the MSP430 memory. It is structured such that it can be used to receive
// any 2+ number of bytes by pre-loading RXByteCtr with the byte count.
//-------------------------------------------------------------------------------
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if(RX == 1){ // Master Receive?
RXByteCtr--; // Decrement RX byte counter
if (RXByteCtr)
{
*PRxData++ = UCB0RXBUF; // Move RX data to address PRxData
}
else
{
if(RPT_Flag == 0)
UCB0CTL1 |= UCTXSTP; // No Repeated Start: stop condition
if(RPT_Flag == 1){ // if Repeated Start: do nothing
RPT_Flag = 0;
}
*PRxData = UCB0RXBUF; // Move final RX data to PRxData
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
else{ // Master Transmit
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = TxData; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
}
void Setup_TX(unsigned char slAddress){
_DINT();
RX = 0;
IE2 &= ~UCB0RXIE;
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent// Disable RX interrupt
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
UCB0BR1 = 0;
UCB0I2CSA = slAddress; // Slave Address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0TXIE; // Enable TX interrupt
}
void Setup_RX(unsigned char slAddress){
_DINT();
RX = 1;
IE2 &= ~UCB0TXIE;
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
UCB0BR1 = 0;
UCB0I2CSA = slAddress; // Slave Address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0RXIE; // Enable RX interrupt
}
