Trying to read data from accelerometer (MMA7660) with an LPC1343

Thread Starter

Biestly

Joined May 29, 2014
1
Hello community,

I'm working on my school project and therefor as the title says I'm trying to read data from the MMA7660 accelerometer with an LPC1343 over I2C connection.

The project is about reading out the data of accelerometer and show the values with LEDs so that the uC-Board works as a level.

I have everything configured as said in the data sheet and I also make the process for reading data over I2C (STA-Bit -> address... and so on).

When I want to try it out the program is always stocked in the second while after sending the slave address of the accelerometer.
Don't wonder, I use some of the LEDs for debugging :p
I recognized that the status-byte after sending the slave address is 0... but thats not good...

Can anyone of you help me out her?
Thanks a lot!

Here is the code:

Rich (BB code):
/*
 * file Wasserwaage_LPC_1343
 * author Patrick Gröller
 * brief program the accelerator to show tha g-status with LEDs
 * date 19-05-2014
 */

//Accelerator slave adress = 0x4C

#include <LPC13xx.h>
#include <type.h>

#define LATCH_EN (1<<2)
#define LED1	 (1<<4)  /* PIO1_4  */
#define LED2	 (1<<5)  /* PIO1_5  */
#define LED3	 (1<<6)  /* PIO1_6  */
#define LED4	 (1<<7)  /* PIO1_7  */
#define LED5	 (1<<8)  /* PIO1_8  */
#define LED6	 (1<<9)  /* PIO1_9  */
#define LED7	 (1<<10) /* PIO1_10 */
#define LED8     (1<<11) /* PIO1_11 */

#define LED_GREEN_ENB (1<<0)
#define LED_RED_EN	  (1<<2)

#define MMA7660_DevAdr  0x4C
#define MMA7660_XValue  0x00

volatile uint8_t I2CMasterBuffer[7];

void blinkDebug(int blinkanz, unsigned char LEDMask)
{
    int i, cnt;
    
    for (i=0; i<blinkanz; i++)
    {
        LPC_GPIO1->DATA |= LEDMask;
        for(cnt=0;cnt<=3000000;cnt++);
        LPC_GPIO1->DATA &= ~LEDMask;
        for(cnt=0;cnt<=3000000;cnt++);
    }
    
}

void LED_Config(void)
{
    SystemInit();                               /* Initialize clocks          */
	LPC_IOCON->JTAG_nTRST_PIO1_2 |= (1<<0);     /* configure LED_RED_EN as IO pin */
    
	/* configure the direction of several IO pins */
	LPC_GPIO3->DIR = LATCH_EN;
	LPC_GPIO1->DIR = (LED_RED_EN | LED1 | LED2 | LED3 | LED4 | LED5 | LED6 | LED7 | LED8);
	LPC_GPIO2->DIR = LED_GREEN_ENB;
    
	LPC_GPIO3->DATA = LATCH_EN;					/* enable the Latch                   */
	//LPC_GPIO2->DATA &= ~(LED_GREEN_ENB);		/* disable the Green LEDs - low active */
	LPC_GPIO1->DATA |= (LED_RED_EN);			/* enable the Red LEDs - high active  */
    
    /* all other LEDs -> off */
    LPC_GPIO1->DATA &= ~(LED1 | LED2 | LED3 | LED4 | LED5 | LED6 | LED7 | LED8);
    
    blinkDebug(3, 0x010);   //DEBUG
}

void I2C_Init(void)
{
    LPC_IOCON->PIO0_4 |= 0x00000001;
    LPC_IOCON->PIO0_5 |= 0x00000001;
    
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);    //Clock enable for I2C
    LPC_SYSCON->PRESETCTRL |= (1<<1);       //de-asserts reset signal to I2C

	LPC_I2C->CONCLR = (1<<2);	/* Assert acknowledge Clear bit */
	LPC_I2C->CONCLR = (1<<3);	/* I2C interrupt Clear bit */
	LPC_I2C->CONCLR = (1<<5);	/* START flag clear */
	LPC_I2C->CONSET = (1<<6);	/* I2C enable */
    
    blinkDebug(3, 0x020);   //DEBUG
}

unsigned char readData_I2C(unsigned char addr, unsigned reg, unsigned data)
{
    int cnt;
    
    //MASTER transmitter mode
	LPC_I2C->CONSET |= (1<<5);				/*  START condition */
    
    LPC_GPIO1->DATA |= LED8;   //DEBUG
    for(cnt=0;cnt<=5000000;cnt++);  //DEBUG
    while(!(LPC_I2C->CONSET & (1<<3)));		/* wait for SI Bit, till bus is free */
    if (LPC_I2C->STAT != 0x08)				/* Status 0x08 bedeutet START condiction empfangen*/
        return 11;	/* FALSE */
    LPC_GPIO1->DATA &= ~LED8;    //DEBUG
    
    LPC_I2C->CONCLR = (1<<3); 		/* Set SIC Bit for clearing SI in CONSET */
    
    LPC_I2C->DAT = (addr<<1);				/* slave address + 8. bit = 0 (8. Bit ist für R=1/W=0)*/
    
    LPC_GPIO1->DATA |= LED7;   //DEBUG
    for(cnt=0;cnt<=5000000;cnt++);  //DEBUG
    while(!(LPC_I2C->CONSET & (1<<3)));	/* wait for interrupt (ACK Adresse + Write) */
	if (LPC_I2C->STAT != 0x01)		/* Status 0x18 bedeutet Slave-Address + W empfangen!*/
        LPC_GPIO1->DATA &= ~(LED1 | LED2 | LED3 | LED4 | LED5 | LED6 | LED7 | LED8);
        LPC_GPIO1->DATA |= ((LPC_I2C->STAT)<<1);    //DEBUG
        return 22;/* FALSE */
    LPC_GPIO1->DATA &= ~LED7;    //DEBUG
    
    LPC_I2C->CONCLR = (1<<3); 		/* Set SIC Bit for clearing SI in CONSET */
    
    LPC_I2C->DAT = reg ;		/* register address*/
    
    LPC_GPIO1->DATA |= LED6;   //DEBUG
    for(cnt=0;cnt<=5000000;cnt++);  //DEBUG
    while(!(LPC_I2C->CONSET & (1<<3)));	/* wait for SI Bit */
	if (LPC_I2C->STAT != 0x28)			/* möglicher Status code:*/
        return 33;/* FALSE */				/* 0x28 Data + ACK recieved*/
    /* 0x30 Data NOT ACK recieved*/
    LPC_GPIO1->DATA &= ~LED6;    //DEBUG
    
    LPC_I2C->CONSET |= (1<<5);				/*  Repeated START condition */
    
    LPC_GPIO1->DATA |= LED5;    //DEBUG
    for(cnt=0;cnt<=5000000;cnt++);  //DEBUG
	while(!(LPC_I2C->CONSET & (1<<3)));		/* wait for SI Bit, till bus is free */
	if (LPC_I2C->STAT != 0x10)				/* Status 0x08 bedeutet START condiction empfangen*/
        return 44;	/* FALSE */
    LPC_GPIO1->DATA &= ~LED5;    //DEBUG
    
    LPC_I2C->DAT = (addr<<1)+1 ;		/* slave address + 8. bit = 1 (8. Bit ist für R=1/W=0)*/
    
	LPC_I2C->CONCLR = (1<<3); 			/* Set SIC Bit for clearing SI in CONSET */
    
    LPC_GPIO1->DATA |= LED4;    //DEBUG
    for(cnt=0;cnt<=5000000;cnt++);  //DEBUG
	while(!(LPC_I2C->CONSET & (1<<3)));	/* wait for SI Bit (ACK Adresse + Write) */
	if (LPC_I2C->STAT != 0x18)			/* möglicher Status code:*/
        return 55;/* FALSE */				/* 0x40 SLA+R and ACK recieved*/
    /* 0x48 SLA+R and no ACK recieved*/
    LPC_GPIO1->DATA &= ~LED4;    //DEBUG
    
    data = LPC_I2C->DAT;
    
    LPC_I2C->CONCLR = (1<<3); 			/* Set SIC Bit for clearing SI in CONSET */
    
    LPC_I2C->CONSET |= (1<<4);      /* STOP ausgeben */
    
	return 0;
}

void I2C_IRQHandler(void){
	int i = 0;
	i++;
    
	uint8_t I2C_state;
    
	I2C_state = LPC_I2C->STAT; /* recent state */
    
	switch (I2C_state) {
            
        case 0x08:		/* a start condition is issued */
            LPC_I2C->DAT = I2CMasterBuffer[0];
            LPC_I2C->CONCLR = (1<<3) | (1<<5);   //interrupt clear bit & START flag clear bit
            break;
            
        default:
            LPC_I2C->CONCLR = (1<<3);    //Interrupt clear bit
            break;
	}
}

int main (void)
{
    LED_Config();
    I2C_Init();
    unsigned char sensorValue = 0;
    unsigned char I2C_Stat;
    
    while(1)
    {
        I2C_Stat = readData_I2C(MMA7660_DevAdr, MMA7660_XValue, sensorValue);
        
        if(I2C_Stat == 0 && sensorValue > 0)
            LPC_GPIO1->DATA |= (LED1 | LED2);
        //else
          //  LPC_GPIO1->DATA |= (LED7 | LED8 | LED5);
    }

}
 
Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
I recognized that the status-byte after sending the slave address is 0... but thats not good...
Well THAT is a problem. If the slave doesn't ACK then it is not part of the transaction, and you can stop right there.

I tried to check your readData_I2C() function but there is too much for me to understand there as I'm not familiar with the processor you are running.

Sending the first slave address is crutial, what typically goes wrong is it gets shifted over a bit as the first byte is a 7 bit address and 1 read/write bit. Some manufacturers give the address as 7 bits, some as 8. Same with I2C library authors: some use 7 bits, some use 8.

One good thing is I2C has no minimum speed, meaning you can send out a bit per hour and read the full bus transaction with a voltmeter or even a LED ;-).

First off, keep working at that first ACK, nothing will work till that is there.
 
Top