This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G1106: DS1307 READ ERROR

Part Number: MSPM0G1106
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello, I am working with DS1307. I am constantly receiving meaningless times from my I2C line. I will leave the code I wrote below. Can you help me where I might have gone wrong?

#include "ti_msp_dl_config.h"
#include "LCD_Func.h"
int val=0;


#define DS1307_ADDRESS 0x68

#define Seconds 0x00
#define Minutes 0x01
#define Hours 0x02
#define Day 0x03
#define Date 0x04
#define Month 0x05
#define Year 0x06
/* I2C Target address */


/* Data received from DS1307 */
volatile uint8_t gRxPacket[7];

uint8_t seconds; // Saniyeler
uint8_t minutes ; // Dakikalar
uint8_t hours; // Saatler
uint8_t dayOfWeek ; // Haftanın günü
uint8_t dayOfMonth ; // Ayın günü
uint8_t month ; // Ay
uint8_t year ;


int bcdToDec(int val) {
return ((val / 16) * 10 + val % 16);
}


uint8_t rxData;
uint8_t readDS1307Register(uint8_t regAddr)
{



DL_I2C_fillControllerTXFIFO(I2C_INST, &regAddr, 1);


while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));


DL_I2C_startControllerTransfer(I2C_INST, DS1307_ADDRESS,
DL_I2C_CONTROLLER_DIRECTION_RX, 1);


while (DL_I2C_isControllerRXFIFOEmpty(I2C_INST))
;
rxData = DL_I2C_receiveControllerData(I2C_INST);


if (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_ERROR) {
__BKPT(0); // Hata durumunda duraklat
}


return bcdToDec(rxData);
}

int main(void)
{
SYSCFG_DL_init();

uint8_t start_address = 0x00;



while (1) {

// DS1307'den saniyeleri oku ve yazdır
// DS1307'den saniyeleri oku ve yazdır
uint8_t seconds = readDS1307Register(Seconds);
printf("second: %02d\n", seconds);

// DS1307'den dakikaları oku ve yazdır
uint8_t minutes = readDS1307Register(Minutes);
printf("minut: %02d\n", minutes);

// DS1307'den saatleri oku ve yazdır
uint8_t hours = readDS1307Register(Hours);
printf("hours: %02d\n", hours);

// DS1307'den günü oku ve yazdır
uint8_t day = readDS1307Register(Day);
printf("day: %02d\n", day);

// DS1307'den tarihi oku ve yazdır
uint8_t date = readDS1307Register(Date);
printf("date: %02d\n", date);

// DS1307'den ayı oku ve yazdır
uint8_t month = readDS1307Register(Month);
printf("monty: %02d\n", month);

// DS1307'den yılı oku ve yazdır
uint8_t year = readDS1307Register(Year);
printf("Year: %02d\n", year);


printf("/////////////////////////////////////////\n");
delay_cycles(160000000);


//toggle_gpio_pin() ;
}
}

  • Hi Burak,

    Looking at your output, it appears that you are getting some data out of your DS1307 device, it just isn't the data that you are expecting. Are there any other devices on this I2C bus currently? Is this data definitely coming from the DS1307?

    I ask this because assuming there are no other devices on the bus, and the data IS definitely coming from the DS1307, it sounds to me like the I2C communications on the MSPM0 side are working as expected. The response from the DS1307 is not though. I would recommend you check the DS1307 datasheet to verify the communication scheme that you use to see if there is some missing piece here.

    Generally if the MSPM0 is functioning as the I2C controller, and is reading a device in the incorrect format, you would get a bus error condition. We have many interrupts you can monitor to check for this, please see the I2C section of the MSPM0 G Series TRM. If you are using Sysconfig in your project it is quite convenient to enable all of the error checking interrupts, then just check to see if any of them occur while reading the DS1307. 

  • The circuit I use is a circuit I have used before. I did not connect any other slave device connected only to the ds1307 line. I will send the data sheet and my circuit as attachment.

    29185_6597768 (3).pdf

  • First, you don't handle the "CH" bit in the seconds register.

    Second, I don't see where you send the register you want to read. I think you need a

    DL_I2C_startControllerTransfer(I2C_INST, I2C_TARGET_ADDRESS,
            DL_I2C_CONTROLLER_DIRECTION_TX, I2C_TX_PACKET_SIZE);

    in there somewhere to tell the DS1307 which register you want.

  • I specified the ds1307 address as 0x68 by looking at the data sheet. regAddr helps you find where to read.

    void readAllDS1307Registers(uint8_t *buffer) {
    uint8_t regAddr = 0x01; // Başlangıç adresi (Seconds register)

    /* Başlangıç adresini belirle */
    DL_I2C_fillControllerTXFIFO(I2C_INST, &regAddr, 1);

    /* I2C hattının boşalmasını bekle */
    while (!(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));

    /* 7 byte'lık veri okuma işlemini başlat */
    DL_I2C_startControllerTransfer(I2C_INST, DS1307_ADDRESS,
    DL_I2C_CONTROLLER_DIRECTION_RX, 7);

    /* Verilerin alındığından emin ol */
    for (int i = 0; i < 7; i++) {
    while (DL_I2C_isControllerRXFIFOEmpty(I2C_INST))
    ;
    buffer[i] = DL_I2C_receiveControllerData(I2C_INST);
    }

    /* Hata kontrolü */
    if (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_ERROR) {
    __BKPT(0); // Hata durumunda duraklat
    }

    /* Tüm verileri BCD'den decimal'e çevir */
    for (int i = 0; i < 7; i++) {
    buffer[i] = bcdToDec(buffer[i]);
    }
    }

  • Hi Burak,

    After a quick skim of the DS1307 datasheet, you must write the register pointer before performing a read. If you perform a read without writing to the register pointer, the DS1307 will use the most recent value stored to the register pointer, which is unspecified in your program, so we do not know its value.

    What you need to do is set the peripheral device address as you have done, then manually send the register address you'd like to read, then send the peripheral device address again. Then with a repeated start condition, you can re-start with a read to read the data register you just indicated. So for example to read the year register you need to send [ 0x68, 0x06, 0x68 ] then use a repeated start with the direction bit set to read, and proceed to read the registers.

    To perform a repeated start, utilize the DL_I2C_startControllerTransferAdvanced() function, which you can read about in our driverlib API guide.