我正在使用PIC18F45K22和XC8。
我已经为I2C插入了MCC库
我需要从ds1307读取秒数的示例,并在下一级中更改当前时间。
根据下面的代码,我在里面
while(状态== 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
见下面的图片
也试图在我的液晶显示器中显示时间
sprintf(txt,"%d",pdata_read);
LCDPutStr(txt,1);
最佳答案
我没有硬件或软件,但查看了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
以某种方式。
非常低级的步骤是:
START(为您处理)
写入0b1101000(这是地址加方向位)
收到确认
如您正确指出的那样,“秒”寄存器的写地址为I2C_MasterRead
(这是数据)
收到确认
开始
写入0b11010001(这是地址加方向位)
收到确认
读
发送确认或不确认
看起来很底层的部分(START / ACKNOWLEDGE和发送地址)正在为您处理,因此您可能只需要执行与以下代码类似的操作(您可能希望重组0x00
逻辑以处理错误)更好):
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)
}
}
if
是指向您要读取/写入的内容的指针,它实际上是指向上述步骤4中包含*pdata
的变量的指针。0x0
是您要读取/写入的数据的长度,我认为在上面列出的所有步骤中,该长度恰好为1length
是DS1307的地址,address
0b1101000
是I2C消息的状态。根据https://github.com/apaivaj/WWVB/blob/master/MainProject/WWVB/mcc_generated_files/i2c1.h,
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;
您可能应该至少检查
pstatus
。更新:要写入秒寄存器,请参见数据表第12页的图4:您需要写入两段数据:首先是寄存器编号,然后是您想要写入该寄存器的编号。因此,代码如下所示:
I2C_MESSAGE_STATUS status;
uint8_t pdata_write[2] = { 0, 0x10 }; // 0x10 into 'seconds' register
I2C2_MasterWrite(pdata_write, 1, 0b1101000, &status);
while (status == I2C_MESSAGE_PENDING); // wait for status to to change
if (status == I2C_MESSAGE_COMPLETE) {
// done!
} else {
// error
}
关于c - 使用I2C的读取时间(Ds1307),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49492415/