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.

Interfacing RTC BQ32000 with MSP430g2553, using interrupts fails on read

Other Parts Discussed in Thread: BQ32000, MSP430G2553

#include <msp430.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

void I2CInit(unsigned char RTC_i2c_address);
void I2CWriteInit(void);
void I2CReadInit(void);

static unsigned char *PRxData;                     // Pointer to RX data
static unsigned char *PTxData;                     // Pointer to RX data
static unsigned char TxByteCtr;
static unsigned char RxByteCtr;
volatile unsigned char TxBuffer[]= {
		  0x00
		};
volatile unsigned char RxBuffer[7];
static volatile unsigned char read_notwrite;

int main(void)
{
		unsigned char Time[7];


		WDTCTL = WDTPW + WDTHOLD;               // Stop WDT
		P1DIR |= 0x01;                          // set P1.0 to output direction
		P1OUT &= ~0x01;                    		// reset P1.0
		I2CInit( 0x68 );						// init RTC


	while (1)
	{
		while(UCB0STAT & UCBBUSY); 				// wait for bus to be free

		read_notwrite=1;
		PTxData = (unsigned char *)TxBuffer;      // TX array start address
		TxByteCtr = sizeof TxBuffer;              // Load TX byte counter
		RxByteCtr = 1;
		while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
		UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
		__bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
											  // Remain in LPM0 until all data
											  // is RX'd

	}
}


void I2CInit(unsigned char rtc_i2c_address)
{

	  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
	  P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
	  P1SEL2|= BIT6 + BIT7;                     // 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 = 20;                             // fSCL = SMCLK/12 = ~100kHz
	  UCB0BR1 = 0;
	  UCB0I2CSA = rtc_i2c_address;                         // Slave Address is 048h
	  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
	  IE2 |= UCB0TXIE;                          // Enable TX interrupt
	  IE2 |= UCB0RXIE;                          // Enable RX interrupt
}

void I2CWriteInit(void)
{

}

void I2CReadInit(void)
{

}



#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
	if( read_notwrite == 1 )							// if read
	{
		  if ( TxByteCtr )                              // Check TX byte counter
		  {
				UCB0TXBUF = *PTxData++;                 // Load TX buffer
				TxByteCtr--;                            // Decrement TX byte counter
		  }
		  else
		  {
				UCB0CTL1 &= ~UCTR;						// set read mode
				UCB0CTL1 |= UCTXSTT;                    // I2C stop condition
			  	IE2 &= ~UCB0TXIE;                       // Disable TX interrupt
				IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
		  }
	}
}


#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
	if( read_notwrite == 1 )						// if read
	{
		if( RxByteCtr )								// Check RX byte counter
		{
			P1OUT |= 0x01;                    		// set P1.0 (for testing)
			RxBuffer[RxByteCtr] = UCB0RXBUF;
			RxByteCtr--;
		}
		else
		{
			UCB0CTL1 |= UCTXSTP;				    // stop condition
			IFG2 &= ~UCB0RXIFG;                     // Clear USCI_B0 RX int flag
			__bic_SR_register_on_exit(CPUOFF);      // Exit LPM0 if data was
													// received
		}
	}

}

Hey guys.

It´s the first time working with a microcontroller outside of university lessons. 

I want to interface the RTC BQ32000 with the MSP430g2553.

I have an oscilloscope running on my SDA and CLK. What i want to do is read out the seconds register 0x00 of the RTC.

Its working fine until it comes to the point where it should read the RXBUFFER. The RTC sends much more data than expected because the Stop from RX-INTERRUPT is not going to happen. 

Whats working:

-send start

-Startbit, RTC adress, subadress of register is send

-restart for read

-RTC adress with read is send, ACK, Data from RTC

Whats not working:

-read buffer from RX-INTERRUPT and stop communication

Pushing STOP-DEBUG holds the programm within the TX-INTERRUPT, it seems the programm is stuck within this interrupt and runs it all time again, even if the TX-FLAG and TX-INTERRUPT-ENABLE are 0. 

  • Check the User's Guide and the datasheet for the interrupt vectors; in I²C mode, the vectors are not what you think. Furthermore, the interrupt handler needs to check for the state change flags.
  • Hey, thanks for your answer. I had another look into the Manual and Datasheet, but only thing i get out of it is:
    -Only the NACK statechange flag is important if in Mastermode (yeah i should use, but should not solve the Problem, because i get ACKs)
    -RX and TX for I2C have their own interrupt vector as i used them in my code
    -RX-Vector is called if something is written to the RXBuffer
    -TX-Vector is called if TXBuffer is empty.
    -RX/TX flags get reset if buffer is read (RX) or written to buffer (TX)

    In the Manuel I found this sentence:
    "The I2C transmit and receive interrupt flags UCBxTXIFG and UCBxRXIFG
    from USCI_Bx and UCAxTXIFG from USCI_Ax share another interrupt vector."
    Does this mean RX and TX share the same vector? But would misfit with an TI example I build this code on.

    What else I found:
    "Setting the UCTXSTP bit will generate a STOP condition. After setting UCTXSTP, a NACK followed by a
    STOP condition is generated after reception of the data from the slave, or immediately if the USCI module
    is currently waiting for UCBxRXBUF to be read.
    If a master wants to receive a single byte only, the UCTXSTP bit must be set while the byte is being
    received. For this case, the UCTXSTT may be polled to determine when it is cleared:"
    But this should not break my code. As my code is written, the STOP bit should be set after the second byte sent by the slave is received. And because the buffer is not read, the STOP condition should be executed after the second byte received.

    Would be thankfull for any futher help. Working 5 weeks now on that bit of code *sight*
  • The names of the two interrupt vectors make sense only for UART and SPI modes.

    The full quote is:

    In I²C mode the state change interrupt flags UCSTTIFG, UCSTPIFG, UCNACKIFG, UCALIFG from USCI_Bx and UCAxRXIFG from USCI_Ax are routed to one interrupt vector. The I²C transmit and receive interrupt flags UCBxTXIFG and UCBxRXIFG from USCI_Bx and UCAxTXIFG from USCI_Ax share another interrupt vector.

    The datasheet shows that the interrupt named "RX" is actually used for USCI_B0 I²C status, and that the interrupt named "TX" is actually used for USCI_B0 I²C receive/transmit.

  • omg, thank you very much. This was driving me crazy. Bad declaration of vector useage ...

    Must have missunderstood the example I used to build the code on.

    Forever in your debt

    regards

**Attention** This is a public forum