Ic2 programming interfacing DS895450 with an MMA8452Q accelerometer HELP!

Thread Starter

dekage

Joined Apr 5, 2012
2
Hi,
Basically i did a program to read datas from this 3 axis accelerometer.
however the results is 0xff for all 3 axis. May i know what might be the possible cause?

Here is the code:

Rich (BB code):
#include <DS89C4XX.h>    //DS89C450 Microcontroller          
#include <intrins.h>    //_nop_() function
#include <stdio.h>        //sprintf() function
#define  _Nop()  _nop_() 

/*#define  OUT_X_MSB 0x01
#define  OUT_X_LSB 0x02
#define  OUT_Y_MSB 0x03
#define  OUT_Y_LSB 0x04
#define  OUT_Z_MSB 0x05
#define  OUT_Z_LSB 0x06 */
#define  WHO_AM_I  0x0D
//#define  SLA       0x1C       //slave address

sbit SDA=P1^0;            
sbit SCL=P1^1;

//i2c buffer
void I2CBitDly()
 // wait approximately 4.7uS
{ // tune to xtal. This works at 11.0592MHz
unsigned int time_end = 10;
unsigned int index;
for (index = 0; index < time_end; index++);
return;
}

//i2c START
//-------------------------------------------
void I2CSendStart()
{
  SDA = 1;             // i2c start bit sequence
  I2CBitDly();
  SCL = 1;
  I2CBitDly();
  SDA = 0;
  I2CBitDly();
  SCL = 0;
  I2CBitDly();
}
//-------------------------------------------

//i2c Stop
//-------------------------------------------
void I2CSendStop()
{
  SDA = 0;             // i2c stop bit sequence
  I2CBitDly();
  SCL = 1;
  I2CBitDly();
  SDA = 1;
  I2CBitDly();
}
//--------------------------------------------

// Set SCL high, and wait for it to go high
//--------------------------------------------
void I2CSCLHigh(void) 
{
register int err;
SCL = 1;
while (! SCL)
{
err++;
if (!err)
{
return;
}
}
}
//---------------------------------------------

//Send function
//---------------------------------------------
void I2CSendByte(unsigned char bt)
{
register unsigned char i;
for (i=0; i<8; i++)
{
if (bt & 0x80) SDA = 1; // Send each bit, MSB first changed 0x80 to 0x01
else SDA = 0;
I2CSCLHigh();
I2CBitDly();
SCL = 0;
I2CBitDly();
bt = bt << 1;
}
SDA = 1; // Check for ACK
I2CBitDly();
I2CSCLHigh();
I2CBitDly();
if (SDA)
SCL = 0;
I2CBitDly();
SDA = 1; // end transmission
SCL = 1;
}
//-----------------------------------------------

// Transmit to SDA
//---------------------------------------------
void I2CSendAddr(unsigned char addr, unsigned char rd)
{
I2CSendStart();
I2CSendByte(addr+rd); // send address byte
}
//---------------------------------------------

// Receive from SDA
//--------------------------------------------------
unsigned char I2CGetByte(unsigned char lastone) // last one == 1 for last byte; 0 for any other byte
{
register unsigned char i, res;
res = 0;
for (i=0;i<8;i++) // Each bit at a time, MSB first
{
I2CSCLHigh();
I2CBitDly();
res *= 2;
if (SDA) res++;
SCL = 0;
I2CBitDly();
}
SDA = lastone; // Send ACK according to 'lastone'
I2CSCLHigh();
I2CBitDly();
SCL = 0;
SDA = 1; // end transmission
SCL=1;
I2CBitDly();
return(res);
}
//----------------------------------------------------------

//delay
//--------------------------------------------------
void delay(int count)
{
    int i,j;

    for (i=0;i<count;i++){
    for (j=0;j<1200;j++); }
}
//--------------------------------------------------
///////////////////////////////////////////SERIAL PORT/////////////////////////////////////////////////
void Tx(unsigned char c)
{
    while (TI_0==0);
    TI_0=0;
    SBUF0=c;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////Digital Transfer//////////////////////////////////////////////
void Tx_char(unsigned char c)
{
    unsigned char s[4];
    int i;

    c=c&0xff;
    sprintf(s,"%#x",(int)c);         // write into string.
    for (i=0;i<4;i++) Tx(s);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////String port////////////////////////////////////////////////////
void Uart_Tx2(unsigned char x)
{
    while (TI_0==0);
    TI_0=0;
    SBUF0=x;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////Send String//////////////////////////////////////////
void sendstring (char *String)
{
    int i=0;    //set counter to 0
    while(String)
    {
        Uart_Tx2(String[i++]);
    }

}
////////////////////////////////////////////////////////////////////////////////////////////////

void main ()
{
     unsigned char value;
     
     
     SCON1 = 0x52;  
     SCON0 = 0x52;  
     TMOD  = 0x20;    
     TCON  = 0x69;      
     TH1   = 0xFD;
     delay(500);
    
     sendstring("System boot...");
     while(1)
         
     {
         //READ X_MSB
        //sendstring(" ");
        sendstring(" XMSB: ");
        delay(500);
        I2CSendAddr(0x1C,0x38);
        I2CSendByte(0x01);
        I2CSendAddr(0x1C,0x39);
        value = I2CGetByte(1);
        Tx_char(value);
        I2CSendStop();
        delay(1000);

        sendstring(" XLSB: ");
        delay(500);
        I2CSendAddr(0x1C,0x38);
        I2CSendByte(0x02);
        I2CSendAddr(0x1C,0x39);
        value = I2CGetByte(1);
        Tx_char(value);
        I2CSendStop();
        delay(1000);

        sendstring(" YMSB: ");
        delay(500);
        I2CSendAddr(0x1C,0x38);
        I2CSendByte(0x03);
        I2CSendAddr(0x1C,0x39);
        value = I2CGetByte(1);
        Tx_char(value);
        I2CSendStop();
        delay(1000);

        sendstring(" YLSB: ");
        delay(500);
        I2CSendAddr(0x1C,0x38);
        I2CSendByte(0x04);
        I2CSendAddr(0x1C,0x39);
        value = I2CGetByte(1);
        Tx_char(value);
        I2CSendStop();
        delay(1000);

        sendstring(" ZMSB: ");
        delay(500);
        I2CSendAddr(0x1C,0x38);
        I2CSendByte(0x05);
        I2CSendAddr(0x1C,0x39);
        value = I2CGetByte(1);
        Tx_char(value);
        I2CSendStop();
        delay(1000);

        sendstring(" ZLSB: ");
        delay(500);
        I2CSendAddr(0x1C,0x38);
        I2CSendByte(0x06);
        I2CSendAddr(0x1C,0x39);
        value = I2CGetByte(1);
        Tx_char(value);
        I2CSendStop();
        delay(1000);
  }
          
}

 
Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
0xFF is what an I2C interface appears to read if you assume the addressing was good and don't check the ACK/NAK bit and assume you were ACKed.

So the slave wasn't responding, the Data line stayed at it's default pull up value of one, and your master clocked those in.

Do you have a scope to watch the transaction? If not, I2C works at DC speed so you can literally watch it on a voltmeter.
 

Thread Starter

dekage

Joined Apr 5, 2012
2
Hi, i have tried to re-program this chip just to read for acknowledgement by sending the start up code for I2C followed by a simple sending of data to the chip. However, i could not receive any acknowledgement from the accelerometer. Im interfacing it with a DS89C450 chip XTAL 11.0592hz . using only 2 ports 1.0 and 1.1.

May i ask what might be the problem?
(* The program is stuck at sending "nack" which i believe SDA is not pulled low )

here is the current edited program changed:

Rich (BB code):
#include <DS89C4XX.h>    //DS89C450 Microcontroller  


sbit SDA=P1^0;            
sbit SCL=P1^1; 
//--------------------------Transmit----------------------------------
void Uart_Tx2(unsigned char c)
{
    while (TI_0==0);
    TI_0=0;
    SBUF0=c;
}

// ----------------------Transmit string ------------------------------------------------------
void sendstring (char *String)
{
    int i=0;    //set counter to 0
    while(String)
    {
        Uart_Tx2(String[i++]);
    }

}   


//-------------------------------Delay -----------------------------------------
void I2CBitDly()   // wait approximately 4.7uS
{ // tune to xtal. This works at 11.0592MHz
unsigned int time_end = 10;
unsigned int index;
for (index = 0; index < time_end; index++);
return;
}


//-------------------------------------------Start--------------------------
void I2CSendStart(void)
{
SDA = 1;
I2CBitDly();
SCL = 1;
I2CBitDly();
SDA = 0;
I2CBitDly();
SCL = 0;
I2CBitDly();
}

//-------------------------------------------STOP-----------------------------
void I2CSendStop(void)
{
SDA = 0;
I2CBitDly();
SCL = 1;
I2CBitDly();
SDA = 1;
I2CBitDly();
}

//-----------------------------------------SEND data---------------------------
void I2CSendByte(unsigned char bt)
{
register unsigned char i;
for (i=0; i<8; i++)
{
if ((bt<<i)&0x80) SDA = 1; // Send each bit
else SDA = 0;

SCL = 1;
I2CBitDly();
SCL = 0;
I2CBitDly();

}
SDA = 1; // Check for ACK  by forcing SDA high
I2CBitDly();
SCL = 1;    // 9th clock high.
I2CBitDly();


while (SDA == 1) //waits until SDA is pulled low
{
    sendstring("nack");          // SDA is not pulled low. nack is sent.
    
}
   SCL = 0;

  
I2CBitDly();
SDA = 1; // end transmission
SCL = 1;
}




//---------------MAIN---------------------------------
void main ()
{
//     unsigned char value;    

        SCON1  = 0x52;   
     SCON0 = 0x52; 
     TMOD  = 0x20;    
     TCON  = 0x69;      
     TH1   = 0xFD;    //Buad Rate: 9600 bps 
      

     
     I2CSendStart();
     I2CSendByte(0x38);
   
   while(1)
   {
           

   };
}
 
Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
I don't see anything wrong in your start signal nor the byte send. What metering do you have? Scope? DVM? Scope is faster but you can use a DVM (or even 2 LEDs) to see what is happening on the I2C lines as it works at DC speeds.


It may be necessary to add a delay here in I2CSendByte():
Rich (BB code):
if ((bt<<i)&0x80) SDA = 1; // Send each bit
else SDA = 0;
I2CBitDly();        // add delay here
 
Top