使用I2C读取时间(Ds1307)

时间:2018-03-26 13:16:26

标签: c i2c mplab

我正在使用PIC18F45K22和XC8。 我插入了用于I2C的MCC库

我需要示例从ds1307读取秒数,然后在下一级别读取更改当前时间。

根据下面的代码,我在里面堆叠 while(status == I2C2_MESSAGE_PENDING);

    I2C2_MasterWrite(&pdata_write, 1, 0b11010000, &status);
 // at this point, your status will probably be I2C2_MESSAGE_PENDING
    while (status == I2C2_MESSAGE_PENDING); // wait for status to to change
    if (status == I2C2_MESSAGE_COMPLETE) {
    I2C2_MasterRead(&pdata_read, 1, 0b11010001, &status);
    while (status == I2C2_MESSAGE_PENDING); // again, wait for status to to change
    if (status == I2C2_MESSAGE_COMPLETE) {
        // pdata_read should now be the number of seconds (in binary-coded decimal)
    }

这是我的主管管理器自动从mcc创建

#define SCL2_TRIS               TRISDbits.TRISD0
#define SCL2_LAT                LATDbits.LATD0
#define SCL2_PORT               PORTDbits.RD0
#define SCL2_ANS                ANSELDbits.ANSD0
#define SCL2_SetHigh()            do { LATDbits.LATD0 = 1; } while(0)
#define SCL2_SetLow()             do { LATDbits.LATD0 = 0; } while(0)
#define SCL2_Toggle()             do { LATDbits.LATD0 = ~LATDbits.LATD0; } while(0)
#define SCL2_GetValue()           PORTDbits.RD0
#define SCL2_SetDigitalInput()    do { TRISDbits.TRISD0 = 1; } while(0)
#define SCL2_SetDigitalOutput()   do { TRISDbits.TRISD0 = 0; } while(0)
#define SCL2_SetAnalogMode()  do { ANSELDbits.ANSD0 = 1; } while(0)
#define SCL2_SetDigitalMode() do { ANSELDbits.ANSD0 = 0; } while(0)

// get/set SDA2 aliases
#define SDA2_TRIS               TRISDbits.TRISD1
#define SDA2_LAT                LATDbits.LATD1
#define SDA2_PORT               PORTDbits.RD1
#define SDA2_ANS                ANSELDbits.ANSD1
#define SDA2_SetHigh()            do { LATDbits.LATD1 = 1; } while(0)
#define SDA2_SetLow()             do { LATDbits.LATD1 = 0; } while(0)
#define SDA2_Toggle()             do { LATDbits.LATD1 = ~LATDbits.LATD1; } while(0)
#define SDA2_GetValue()           PORTDbits.RD1
#define SDA2_SetDigitalInput()    do { TRISDbits.TRISD1 = 1; } while(0)
#define SDA2_SetDigitalOutput()   do { TRISDbits.TRISD1 = 0; } while(0)
#define SDA2_SetAnalogMode()  do { ANSELDbits.ANSD1 = 1; } while(0)
#define SDA2_SetDigitalMode() do { ANSELDbits.ANSD1 = 0; } while(0)

Image

Image2

见下面的图片

还试图在我的lcd中显示时间

sprintf(txt,"%d",pdata_read);
     LCDPutStr(txt,1);

1 个答案:

答案 0 :(得分:0)

我没有硬件或软件,但看了https://www.studentcompanion.co.za/interfacing-the-ds1307-real-time-clock-with-pic-microcontroller-xc8/(可能让您加快速度的长篇教程)和https://datasheets.maximintegrated.com/en/ds/DS1307.pdf(数据表),以及以某种方式提及I2C_MasterWrite / I2C_MasterRead的随机页面。

非常低级的步骤是:

  1. START(为您处理)
  2. 写0b1101000(这是一个地址加上方向位)
  3. 收到ACKNOWLEDGE
  4. 写入"秒"的地址注册,正如您所说的0x00(这是数据)
  5. 收到ACKNOWLEDGE
  6. START
  7. 写0b11010001(这是一个地址加上方向位)
  8. 收到ACKNOWLEDGE
  9. 发送ACKNOWLEDGE或不确认
  10. 看起来正在为您处理非常低级的部分(START / ACKNOWLEDGE和发送地址),因此您可能只需要执行类似于以下代码的操作(您可能需要重构{{1} }更好地处理错误的逻辑):

    if
    • I2C_MESSAGE_STATUS status; uint8_t pdata_write = 0; // 0 to 'seconds' register uint8_t pdata_read; // will hold 'seconds' I2C2_MasterWrite(&pdata_write, 1, 0b1101000, &status); // at this point, your status will probably be I2C2_MESSAGE_PENDING while (status == I2C_MESSAGE_PENDING); // wait for status to to change if (status == I2C_MESSAGE_COMPLETE) { I2C2_MasterRead(&pdata_read, 1, 0b1101000, &status); while (status == I2C_MESSAGE_PENDING); // again, wait for status to to change if (status == I2C_MESSAGE_COMPLETE) { // pdata_read should now be the number of seconds (in binary-coded decimal) } } 是指向您想要读取/写入的内容的指针,它实际上是指向上面步骤4中包含*pdata的变量的指针。
    • 0x0是您想要读/写的数据的长度,我认为在上面列出的所有步骤中,该数据恰好为1
    • length是DS1307的地址address
    • 0b1101000是I2C消息的状态。

    根据https://github.com/apaivaj/WWVB/blob/master/MainProject/WWVB/mcc_generated_files/i2c1.hpstatus可以是以下任何一种:

    pstatus

    您应该检查至少typedef enum { I2C1_MESSAGE_FAIL, I2C1_MESSAGE_PENDING, I2C1_MESSAGE_COMPLETE, I2C1_STUCK_START, I2C1_MESSAGE_ADDRESS_NO_ACK, I2C1_DATA_NO_ACK, I2C1_LOST_STATE } I2C1_MESSAGE_STATUS;

    更新:要写入秒寄存器,请参见数据表第12页的图4:您需要写两个数据:首先是寄存器号,然后是您想要的数字写入该登记册。因此,代码看起来像这样:

    I2C_MESSAGE_FAIL