EmbeddedRelated.com
Forums

MSP430 I2C communication(2)

Started by Songsongsong August 29, 2012
Hi everyone, I should transmit and receive data from master(MSP430f5338) to slave sensor(LSM303DLM) by I2C communication.
I want to read data of x, y and z, so I can't receive multiple bytes because I have to change register continuously.
I made some codes using example codes from this group and TI example code. But there are two problems in my code.

First, the slave address register UCB0I2CSA is never changed from 0x48.
I assign the slave address 0x30 or the other hex numbers, but it was never changed from 0x48.

Second, in datasheet of this sensor, to write data, operation protocol is like below.
Master....Start.....SAD+W.....SUB.....DATA.....Stop
Slave.....................SAK.....SAK......SAK

And to read data, operation protocol is below.
Master....Start.....SAD+W.....SUB.....SR.....SAD+R...........Stop
Slave.....................SAK.....SAK..............SAK..DATA

So I programmed interrupt service routine like below, but RX interrupt service routine is never called.
Case 10: RXIFG routine in
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR (void)
is totally ignored and passed. I don't know why these problem is occured...
Here is my code. please help my problem.. I think the main problem part is function [DataRead] and interrupt service routine.
Thank you.

//////////////////////////////////////////////////////////////////
#include

unsigned char *PTxData;
unsigned char RXData;
unsigned char TXByteCtr = 1;

unsigned char ACC_Data[6], MAG_Data[6];
int ACC_X, ACC_Y, ACC_Z, MAG_X, MAG_Y, MAG_Z;

void SetAccMagPort (void)
{
P2SEL = 0; P2DIR = 0; P2OUT = 0; P2IES = 0; P2IE = 0;

P2SEL |= BIT1 | BIT2;

PMAPPWD = 0x2D52; // enable write access to any of the
// port mapping controller registers
if (!(PMAPCTL & PMAPLOCKED)) // if write access is granted
{
PMAPCTL |= PMAPRECFG;
P2MAP1 = PM_UCB0SDA; // P2.3 : UCB0CLK
P2MAP2 = PM_UCB0SCL; // P2.4 : UCB0SIMO
PMAPPWD = 0; // prevent further write accesses
}
else ;
}

void SetI2C (void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
UCB0CTL1 |= UCSWRST; // **Put state machine in reset**
UCB0CTL0 |= UCMST | UCSYNC | UCMODE_3;
UCB0CTL1 |= UCSSEL_2; // SMCLK
UCB0BR0 = 0x04; // /4 --- 2.304 MHz
UCB0BR1 = 0;
UCB0I2CSA = 0x30;
UCB0CTL1 &= ~UCSWRST;
UCB0IE = UCTXIE;
//UCB0IE = UCRXIE;
}

void SetAccREG (void)
{
DataWrite(ACC_ADDRESS_W, CTRL_REG1_A, 0x27);
DataWrite(ACC_ADDRESS_W, CTRL_REG3_A, 0x40);
}
void DataWrite (unsigned char sadw, unsigned char sub, unsigned char data)
{
unsigned char temp[] = {sub, data};
PTxData = (unsigned char *)temp;
TXByteCtr = sizeof temp;

while(TXByteCtr)
{
UCB0I2CSA = sadw;
UCB0CTL1 |= UCTR | UCTXSTT;
__bis_SR_register(GIE);
__no_operation();
while(UCB0CTL1 & UCTXSTP);
}
}
unsigned char DataRead (unsigned char sadr, unsigned char sub)
{
UCB0IE &= ~UCRXIE;
UCB0IE |= UCTXIE;
UCB0I2CSA = ACC_ADDRESS_W;
PTxData = (unsigned char *)sub;
TXByteCtr = 1;
UCB0CTL1 |= UCTR | UCTXSTT;
__bis_SR_register(GIE);
while(UCB0CTL1 & UCTXSTP);

// UCB0CTL1 |= UCSWRST;
// UCB0CTL1 &= ~UCSWRST;
UCB0IE &= ~UCTXIE;
UCB0IE |= UCRXIE;
UCB0I2CSA = sadr;
//UCB0CTL1 &= ~UCTR;
UCB0CTL1 |= UCTXSTT;
__bis_SR_register(GIE);

return RXData;
}

void main (void)
{
SetAccMagPort();
SetI2C();
SetAccREG();

while(1)
{
ACC_Data[0] = DataRead(ACC_ADDRESS_R, OUT_X_L_A);
ACC_Data[1] = DataRead(ACC_ADDRESS_R, OUT_X_H_A);
ACC_Data[2] = DataRead(ACC_ADDRESS_R, OUT_Y_L_A);
ACC_Data[3] = DataRead(ACC_ADDRESS_R, OUT_Y_H_A);
ACC_Data[4] = DataRead(ACC_ADDRESS_R, OUT_Z_L_A);
ACC_Data[5] = DataRead(ACC_ADDRESS_R, OUT_Z_H_A);
ACC_X = (int)(ACC_Data[0] << 8) + ACC_Data[1];
ACC_Y = (int)(ACC_Data[2] << 8) + ACC_Data[3];
ACC_Z = (int)(ACC_Data[4] << 8) + ACC_Data[5];
}
}

#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR (void)
{
switch(__even_in_range(UCB0IV,12))
{
case 0: break; // Vector 0: No interrupts
case 2: break; // Vector 2: ALIFG
case 4: break; // Vector 4: NACKIFG
case 6: break; // Vector 6: STTIFG
case 8: break; // Vector 8: STPIFG

case 10: // Vector 10: RXIFG

RXData = UCB0RXBUF; // Get RX data
UCB0CTL1 |= UCTXSTP;
break;

case 12: // Vector 12: TXIFG

if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = *PTxData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
//__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
}
break;

default: break;
}
}

Beginning Microcontrollers with the MSP430

Hi,

> Hi everyone, I should transmit and receive data from master(MSP430f5338)
> to slave sensor(LSM303DLM) by I2C communication.
> I want to read data of x, y and z, so I can't receive multiple bytes
> because I have to change register continuously.

The 303DLM's accelerometer is intended to be read as a burst-mode
transaction with a repeated start, i.e. START+WRITE START+READ
NAK. The LSM303DLH device is the combination of a LIS331DL
and a Honeywell HMC5883L in a single integrated circuit and supports address
auto-increment through the accelerometer output registers. Read the
datasheet!

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore Development Platform http://www.soldercore.com