Other Parts Discussed in Thread: TMP102, MSP430G2553
Hello,
I'm trying to get the msp430g2553 to acknowledge poll a
24lc256 flash rom and a tmp102 temperature sensor. I've modified the ti
sample code somewhat and it is currently working, but not quite how it
should. I would ideally like to send only the control byte, but I have
tried various methods and I cannot seem to manage it. I have tried
setting TxByteCtr to zero both directly and via my i2cTransmit function
with no avail. I have also tried a very basic send a setupTX then send a start condition and
then a stop more or less directly after which seems to be what is
suggested in the data sheet. All of these generally end up with my
program in one of the while(UCB0CTL1 & UCTXSTP); 's which suggests
the chip cannot send the stop condition for some reason or the while 1
of the USCIAB0RX_ISR, which shouldn't happen.
I do know that my
current method should cause no problems since both devices first bytes
are for register addressing but I would like to try and make it as
universal as possible. I also know that I could use a delay but I
personally think that is a bit messy.
Any help would be appreciated.
#include "project2553i2c.h"
void Setup_TX(char address)
{
_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 = address;
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE |= UCNACKIE;
IE2 |= UCB0TXIE; // Enable TX interrupt
}
void Setup_RX(char address)
{
_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 = address;
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE |= UCNACKIE;
IE2 |= UCB0RXIE; // Enable RX interrupt
}
void i2cTransmit(char * data, int numberOfBytes)
{
PTxData = data; // TX array start address
TXByteCtr = numberOfBytes; // Load TX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
}
void i2cReceive(volatile char * data, int numberOfBytes)
{
PRxData = (char *)data; // Start of RX buffer
RXByteCtr = numberOfBytes; // Load RX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTXSTT; // I2C start condition
while (UCB0CTL1 & UCTXSTT);
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
}
void i2cFlashWrite(char * data, char i2cAddress, unsigned int internalAddress, int numberOfBytes)
{
while(numberOfBytes > 0)
{
TxData[0] = (char)((internalAddress >> 8) & 0xff); //Placing internal address into transmit data
TxData[1] = (char)(internalAddress & 0xff);
Setup_TX(i2cAddress);
if(numberOfBytes > 64) //Sends 64 bytes of data
{
memcpy(&TxData[2], data, 64);
i2cTransmit(TxData,66);
numberOfBytes -= 64;
data+=64;
internalAddress += 64;
i2cPoll(i2cAddress);
}
else
{
memcpy(&TxData[2], data, numberOfBytes);
i2cTransmit(TxData, numberOfBytes + 2);
i2cPoll(i2cAddress);
break;
}
}
}
void i2cRandomRead(volatile char * data, char i2cAddress, unsigned int internalAddress, int numberOfBytes)
{
char internalAddressArray[2];
internalAddressArray[0] = (char)((internalAddress >> 8) & 0xFF);
internalAddressArray[1] = (char)(internalAddress & 0xFF);
Setup_TX(i2cAddress);
i2cTransmit(&internalAddressArray[0], 2);
i2cPoll(FLASH);
while (UCB0CTL1 & UCTXSTP);
Setup_RX(i2cAddress);
i2cReceive(data, numberOfBytes);
while (UCB0CTL1 & UCTXSTP);
}
void i2cPoll(char address)
{
do //polling for write complete
{
polling = 1;
Setup_TX(address);
i2cTransmit(0,1); //DEBUG
}
while(polling == 2);
polling = 0;
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
if ((UCB0STAT & UCNACKIFG) == UCNACKIFG && polling == 1)
{
nacks++;
UCB0STAT &= ~UCNACKIFG;
UCB0CTL1 |= UCTXSTP;
while(UCB0CTL1 & UCTXSTP);
polling = 2;
__bic_SR_register_on_exit(CPUOFF);
}
else
{
UCB0CTL1 |= UCTXSTP;
while(UCB0CTL1 & UCTXSTP);
while(1);
}
}
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if(RX == 1) // Master Recieve?
{
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
IFG2 &= ~UCB0RXIFG;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
else
{ // Master Transmit
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = *PTxData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
if(RPT_Flag == 1)
{
RPT_Flag = 0;
PTxData = &TxData[0]; // TX array start address
__bic_SR_register_on_exit(CPUOFF);
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
}
}