This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Ic2 programming interfacing DS895450

Hi,
This programing is to Start I2c Communication with the basic start up code followed by sending a 8 bit address together with a write bit. Next, it will send a string a serial port to show a string "nack" only if the SDA is not pulled low, which means not acknowledged.

Chip used: Dallas DS89C450 11.0592Mhz
Accelerometer: SEN 10955 2.25 Mhz

Problem faced: SDA could not be pulled low. Nack received.

Question: May i know is there any faults in this program?

#include <DS89C4XX.h>     //DS89C450 Microcontroller
#include <intrins.h>      //_nop_() function

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[i])
        {
                Uart_Tx2(String[i++]);
        }

}


//-------------------------------Delay -----------------------------------------
void I2CBitDly()   // wait approximately 4.7uS
{ // tune to xtal. This works at 11.0592MHz
unsigned int time_end = 9;
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; // make P1.0 an input.
I2CBitDly();
SCL = 1;        // 9th clock high.
I2CBitDly();


if (SDA == 1) //
{
        sendstring("nack");             // SDA is not pulled low. nack is sent.

}
   SCL = 0;


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



//---------------MAIN---------------------------------
void main ()
{

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



         I2CSendStart();
         I2CSendByte(0x38);

   while(1)
   {

   };
}

Parents
  • You are testing SDA after you set SCL high. This can't work. If the SDA would change while SCL is high 'other' I2C devices would see a 'start' or 'stop' condition on the bus. After you set SCL high then set SCL low again and then test the SDA state. Please read the I2C specification carefully. Read what happens on rising and falling edge of the SCL signal.

Reply
  • You are testing SDA after you set SCL high. This can't work. If the SDA would change while SCL is high 'other' I2C devices would see a 'start' or 'stop' condition on the bus. After you set SCL high then set SCL low again and then test the SDA state. Please read the I2C specification carefully. Read what happens on rising and falling edge of the SCL signal.

Children
  • Hi!
    I finally manage to receive an acknowledge, the problem was the wrong slave address used.
    However, Now, i could not Read from the I2C bus. I keep receiving 0x01 as the final result.

    Question: Is my Transmitting to serial port or receiving from I2C function at fault?

    #include <DS89C4XX.h>     //DS89C450 Microcontroller
    #include <intrins.h>      //_nop_() function
    #include <stdio.h>                //sprintf() function
    
    sbit SDA=P1^0;
    sbit SCL=P1^1;
    
    
    //--------------------------Transmit----------------------------------
    void Uart_Tx1(unsigned char c)
    {
            while (TI_0==0);
            TI_0=0;
            SBUF0=c;
    }
    
    //--------------------------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[i])
            {
                    Uart_Tx2(String[i++]);
            }
    
    }
    
    //-----------------------------Delay--------------------------------------------
    void Delay(int count)
    {
            int i,j;
    
            for (i=0;i<count;i++){
            for (j=0;j<1200;j++); }
    }
    
    //-------------------------------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; // make P1.0 an input.
    I2CBitDly();
    SCL = 1;        // 9th clock high.
    I2CBitDly();
    
    
    if (SDA == 0) //
    {
            //sendstring(" ack ");                  // SDA is not pulled low. nack is sent.
    
    }
       SCL = 0;
    
    
    I2CBitDly();
    SDA = 1; // end transmission
    SCL = 1;
    }
    
    //----------------READ DATA --------------------------------------------------------------------------------
    unsigned char I2CGetByte()
    {
      unsigned char retc;
      unsigned char BitCnt;
    
      retc=0;
       I2CBitDly();
      SCL=0;
       I2CBitDly();
      SDA=1;        // set as input pin.
    
      for(BitCnt=0;BitCnt<8;BitCnt++)
          {
    
    
    
            I2CBitDly();
            SCL=1;
            retc=retc<<1;              // shift by 1 for each bit.
                    I2CBitDly();
            if(SDA==1)retc=retc+1;
           I2CBitDly();
               SCL=0;
          }
    
    
        I2CBitDly();
    
    
    
    
      return(retc);
    }
    //-------------------Standby---------------------------
    void standby_mode ()
    {
                    I2CSendStart();
                    I2CSendByte(0x3A);
                    I2CSendByte(0x0B);                      //address
                    I2CSendByte(0x00);                      // standby mode
                    I2CSendStop();
    }
    
    //-------------------Active mode-----------------------
    void active_mode ()
    {
                    I2CSendStart();
                    I2CSendByte(0x3A);
                    I2CSendByte(0x0B);
                    I2CSendByte(0x01);                      // active mode
                    I2CSendStop();
    }
    
    //---------------------8g mode -----------------------
    void g_mode ()
    {
                    I2CSendStart();
                    I2CSendByte(0x3A);
                    I2CSendByte(0x0E);
                    I2CSendByte(0x02);                        // set to 8g.
                    I2CSendStop();
    }
    
    //-------------------Register Active mode ----------------
    void AReg1 ()
    {
                    I2CSendStart();
                    I2CSendByte(0x3A);
                    I2CSendByte(0x2A);
                    I2CSendByte(0x01);                      // active mode
                    I2CSendStop();
    }
    
    //----------------------------------Transmit CHAR----------------------
    void Char_Int(unsigned char c)
    {
            unsigned char s[4];
            int i;
    
            c=c&0xff;
            sprintf(s,"%03d ",(int)c);
            for (i=0;i<4;i++) Uart_Tx1(s[i]);
    }
    
    //---------------MAIN---------------------------------
    void main ()
    {
             unsigned char value;
    
    
             SCON1  = 0x52;
             SCON0 = 0x52;
             TMOD  = 0x20;
             TCON  = 0x69;
             TH1   = 0xFD;  //Buad Rate: 9600 bps
             Delay(200);
              SDA = 0;         //set to output pin
             SCL = 0;         //set to output  pin
             Delay(200);
    
    
             standby_mode (); // set to standby to do config
    
    
             g_mode ();     // set to 8g range
    
    
    
             AReg1 (); // set REG 1 active for reading
    
    
             active_mode (); // set back to active mode
    
    
    
    
    while (1)
            {
                    I2CSendStart();
                    I2CSendByte(0x3A);
                    I2CSendByte(0x01);
                    I2CSendStart();
                    I2CSendByte(0x3B);
                    value = I2CGetByte();
                    Char_Int(value);
                    I2CSendStop();
                    Delay(1000);
              }
    
    
    }