LPC1768 interfacing with DS3231 problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1768 interfacing with DS3231 problem

1,917 Views
mostafanfs
Contributor III

I'm using the I2C driver from this link https://community.nxp.com/servlet/JiveServlet/download/11497-431883-820007-391187/mcb1700.code_.bund...  to get the time data from a RTC chip (DS3231). But I keep getting I2C_NACK_ON_ADDRESS after sending the first byte which is the slave address (0x68) and I can't go forward after this.

All things seems to be ok. I used I2C0 and configured it correctly and using a famous DS3231 module with battery and everything and with 4.7K pull-up resistors.

What could be the problem?

Labels (1)
0 Kudos
8 Replies

1,512 Views
rolfmeeser
NXP Employee
NXP Employee

Try slave address 0xD0 instead of 0x68.

0 Kudos

1,512 Views
mostafanfs
Contributor III

Well Thank you. That solved my first problem. Now I'm using 0xD0 for write operations and 0xD1 for read operations.

Now I don't get NACK on anything but I just keep getting zeros when I attempt to read time and date registers.

I've been told that I need to set the timekeeping register values first. I tried to set some values before any attempt to read those registers. But I still keep reading zeros or nothing.

I don't know what is wrong. Do you guys have some ideas about it?

Do I need to set any control bit or something or just reading and writing to address registers 0x00 ~ 0x07 is enough?

0 Kudos

1,512 Views
rolfmeeser
NXP Employee
NXP Employee

You're not telling what exactly you are sending to the RTC, so I'm unable to comment.

If you are sure that you have followed the DS3231 data sheet instructions precisely, it might be better to ask the Maxim guys for assistance.

0 Kudos

1,512 Views
mostafanfs
Contributor III

According to datasheet there is not much to send. I have sent some values to register address 0x00 and read back from this address.

#define PORT_USED      0

void open_ds3231(void){

  I2C0Init();

}

uint32_t rtc_set_time(uint8_t hour,uint8_t min,uint8_t sec)

{

  uint32_t state;

    /* Write SLA(W), address and one data byte */

  I2CWriteLength[PORT_USED] = 5;

  I2CReadLength[PORT_USED] = 0;

  I2CMasterBuffer[PORT_USED][0] = DS3231_ADDR_WRITE;  // 0xD0

  I2CMasterBuffer[PORT_USED][1] = 0x00;  // Second register address

  I2CMasterBuffer[PORT_USED][2] = bin2bcd(sec);

  I2CMasterBuffer[PORT_USED][3] = bin2bcd(min);

  I2CMasterBuffer[PORT_USED][4] = bin2bcd(hour);

  state = I2CEngine( PORT_USED );

  return state;

}

uint32_t rtc_get_time(uint8_t *hour,uint8_t *min,uint8_t *sec)

{

  uint32_t state;

    /* Write SLA(W), address and one data byte */

  I2CWriteLength[PORT_USED] = 2;

  I2CReadLength[PORT_USED] = 3;

  I2CMasterBuffer[PORT_USED][0] = DS3231_ADDR_READ; // 0xD1

  I2CMasterBuffer[PORT_USED][1] = 0x00;

  state = I2CEngine( PORT_USED );

  *sec=bcd2bin(I2CSlaveBuffer[PORT_USED][0]);

  *min=bcd2bin(I2CSlaveBuffer[PORT_USED][1]);

  *hour=bcd2bin(I2CSlaveBuffer[PORT_USED][2]);

  return state;

}

There is one thing that I noticed. By setting some breakpoints in i2c.c file in I2C0_IRQHandler() routine I found out it goes to this case after sending the first byte :

     case 0x38:          /* Arbitration lost, in this example, we don't deal with multiple master situation */

     default:

     I2CMasterState[0] = I2C_ARBITRATION_LOST;

     LPC_I2C0->CONCLR = I2CONCLR_SIC;    

     break;

0 Kudos

1,512 Views
rolfmeeser
NXP Employee
NXP Employee

If I understand the state machine implementation in the code bundle driver correctly, then a small modification to your get_time() function is necessary.

The first address byte must be a write address, and the read address must be added as a third byte in the MasterBuffer. The driver appears to use that third byte when it reaches state 0x10 (after the repeated start).

  1. I2CWriteLength[PORT_USED]=2;
  2. I2CReadLength[PORT_USED]=3;
  3. I2CMasterBuffer[PORT_USED][0]=DS3231_ADDR_WRITE;//0xD0
  4. I2CMasterBuffer[PORT_USED][1]=0x00;
  5. I2CMasterBuffer[PORT_USED][2]=DS3231_ADDR_READ;//0xD1
  6. state=I2CEngine(PORT_USED);
0 Kudos

1,512 Views
mostafanfs
Contributor III

Well it didn't solve the problem.

What about the rtc_set_time() ? Is it in a correct form?

Cause when I first call rtc_set_time() the state reaches to I2C_OK in 0x28 and I think it's fine :

pastedImage_18.png

But after this when I call rtc_get_time() it keeps going to the I2C_ARBITRATION_LOST state in case 0x38 or default case except the first time after writing the first byte into I2CDAT register (case 0x08) : Why this keeps happening?

pastedImage_19.png

Why do you think about these lines that has been written in the i2c.c driver file ?

pastedImage_2.png

0 Kudos

1,512 Views
rolfmeeser
NXP Employee
NXP Employee

We need to see what's going on on the bus (trace). Can you provide scope pictures or logic analyzer trace?

0 Kudos

1,512 Views
mostafanfs
Contributor III

Not right now !  Actually I was kind if hoping it wouldn't get to there !

I'll see what can I do tomorrow about the scope.

I don't get it why would a simple RTC give me such a hard time.

0 Kudos