Quantcast
Channel: MSP low-power microcontroller forum - Recent Threads
Viewing all articles
Browse latest Browse all 21936

CCS/MSP430F5529: I2C Master Read - First byte read is garbage (Rest of data is read properly)

$
0
0

Part Number:MSP430F5529

Tool/software: Code Composer Studio

I am writing a generic, polling-based I2C master RX/TX driver on the MSP430F5529LP evaluation board (Default Clock Rate). I have an Adafruit metro-mini (Arduino based) board functioning as a slave transmitter sending "Hello" when I request a read.

My write function works properly, but when I attempt to read, I experience strange behavior. The first byte read from RXBUF is garbage, however the the entire message is received in consecutive reads. If I step through the code, the first byte is no longer garbage, and I receive the entire message properly. This makes me think I am not checking for some IFG/CTL flag to be set properly after the start condition, and as a result have a timing issue. The baffling thing is if I read the RXBUF prior to issuing the start condition, all bytes are read correctly.  I didn't see anything obvious in the User guide to make me think this is correct (Seems more like a Hack) so I am hoping you guys see my issue. 

i2c::i2c(I2C_Type port, uint8_t clkDiv)
{
	switch((int16_t)port)
	{
		case USCIB0:

			UCxxCTL1 =	&UCB0CTL1;
			UCxxCTL0 = &UCB0CTL0;
			UCxxBR0  = &UCB0BR0;
			UCxxBR1  = &UCB0BR1;
			UCxxI2CSA = &UCB0I2CSA;
			UCxxIFG   = &UCB0IFG;
			UCxxRXBUF = &UCB0RXBUF;
			UCxxTXBUF = &UCB0TXBUF;

			break;
		case USCIB1:

			UCxxCTL1  = &UCB1CTL1;
			UCxxCTL0  = &UCB1CTL0;
			UCxxBR0   = &UCB1BR0;
			UCxxBR1   = &UCB1BR1;
			UCxxI2CSA = &UCB1I2CSA;
			UCxxIFG   = &UCB1IFG;
			UCxxRXBUF = &UCB1RXBUF;
			UCxxTXBUF = &UCB1TXBUF;

			break;

		default:
			return;
	}

	pinSetup();

	*UCxxCTL1 |= UCSWRST;                      // Enable SW reset
	*UCxxCTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
	*UCxxCTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
//	*UCxxI2CSA = 0x04;
	*UCxxBR0  = clkDiv;                        // Apply Clock divider to SMCLK
	*UCxxBR1  = 0;
	*UCxxCTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

	*UCxxIE   = 0;
	*UCxxIFG  = 0;                             // Clear interrupt flags

}

bool i2c::start(bool isRead)
{
	// Set the I2C r/w bit, Send start condition
	if(isRead == false)
	{
		*UCxxCTL1 |= UCTR|UCTXSTT;
	}
	else
	{
		*UCxxCTL1 |= UCTXSTT;
		*UCxxCTL1 &= ~UCTR;
	}

	return !((*UCxxIFG & UCNACKIFG) == UCNACKIFG);
}

bool i2c::stop(void)
{
	// Wait for the Stop condition to be accepted
	uint16_t count = 5000;

	*UCxxCTL1 |= UCTXSTP;

	while ((*UCxxCTL1 & UCTXSTP)==UCTXSTP)
	{
		count--;
		if(count <= 0)
			return false;
	}

	return true;
}

uint8_t i2c::read(uint8_t address, uint8_t* data, uint8_t length, bool repeated)
{
	// Holds number of bytes read
	uint8_t br = 0;

	 // Assign the Slave Address
	*UCxxI2CSA = address;

	{
		// A junk byte is read if I don't clear the RXBUF
		uint8_t junk = *UCxxRXBUF;
	}

	// Issue Start Request
	if(start(true) == false)
	{
		// Regardless of repeated status, issue stop and terminate
		stop();
		return br;
	}

	for(uint8_t idx = 0; idx < length; idx++)
	{
		int16_t counts=10;

		// Wait for previous rx to complete.
		while (!(*UCxxIFG & UCRXIFG))
		{
			_delay_cycles(100);
			counts--;
			if(counts <= 0)
			{
				// Regardless of repeated status, issue stop and terminate
				stop();
				return 0;
			}
		}

		data[br++] = *UCxxRXBUF;
	}

	// Calling function will issue a repeated start, don't issue a STOP
	if(repeated == false)
		stop();

	return br;
}


Viewing all articles
Browse latest Browse all 21936

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>