- bool I2C1_WriteRead(uint16_t address, uint8_t *writeData, size_t writeLength, uint8_t *readData, size_t readLength);
第一个参数是器件地址,第二个参数是写入的数组,第三个参数是写入的长度,第四个参数是读出的数组,第五个参数是读出的长度。我因为只需要写入一个字节,所以开始就用一个变量来代替写入的数组:
- d = 0;
- i = I2C1_Host_WriteRead(DS1307_Addr_7,&d,1,&DS_Buff,7);
就是这里出了问题,变量不能代替数组。实际执行的结果写入的不是0地址,而是一个不确定的值,每次操作其值都不相同,所以最终读出的数据是错误的日期。下面就是逻辑分析仪抓取的数据:
找出原因之后,我尝试修改代码,定义了两个数组,一个存放读出的数据,另一个存放要写入的数据:
- dat[0] = 0;
- i = I2C1_Host_WriteRead(DS1307_Addr_7,&dat,1,&DS_Buff,7);
这次测试得到了正确的结果,从逻辑分析仪抓取的时序数据是正确的:
通过串口获得的也是正确的日期:
下面是DS1307的完整驱动代码:
- //#include "My_i2c.h"
- #include "ds1307.h"
- extern uint16_t year; //年
- extern uint8_t week,month,day,hour,minute,second,DS_Buff[16]; //月日时分秒
- uint8_t dat[9]={0,0,0,0,0,0,0,0,0,};
- /******************************************************************************************
- * 函数名称: GetWeek(Y,M,D)
- * 功能说明: 通过日期(yesr,month,day)计算星期
- * 输 入: Y,M,D
- * 输 出: W(周日=7)
- ******************************************************************************************/
- uint8_t GetWeek(uint16_t Y,uint8_t M,uint8_t D)
- {
- uint8_t W;
- if(M<3){
- M += 12;
- Y--;
- }
- W = (D+1+2*M+3*(M+1)/5+Y+Y/4-Y/100+Y/400)%7;
- if(0==W)
- W = 7;
- return W;
- // W = (Y-1) * 365.2425 + 0.5 + (M-1) * 30 +D;
-
- }
- /******************************************************************************************
- * 函数名称: DS1307_Init()
- * 功能说明: 用当前日期(yesr,month,day,hour,minute)初始化DS1307
- * 输 入: 无
- * 输 出: uint8_t 0=RET_OK 初始化成功 1=RET_ERR 初始化出错
- ******************************************************************************************/
- void DS1307_Init(void)
- {
- bool i;
- dat[0] = 0;
- i = I2C1_Host_WriteRead(DS1307_Addr_7,&dat,1,&DS_Buff,7);
- // d = SI2C_8bitByteRead(DS1307_Addr,0);
- if(DS_Buff[0] > 127){
- year = 2024;
- month = 9;
- day = 23;
- week = 1;
- hour = 12;
- minute = 30;
- second = 0;
- DS1307_WriteDate();
- }
- }
- /******************************************************************************************
- * 函数名称: DS1307_read_DS_Buffe()
- * 功能说明: 读取DS1307日期时间数据
- * 输 入: 无
- * 输 出: 无
- ******************************************************************************************/
- void DS1307_ReadDate(void)
- {
- bool i;
- dat[0] = 0;
- i = I2C1_Host_WriteRead(DS1307_Addr_7,&dat,1,&DS_Buff,7);
- // d = SI2C_8bitBuffRead(DS1307_Addr,0,8);
-
- second = ((DS_Buff[0]&0x70)>>4)*10 + (DS_Buff[0]&0x0F);//秒,屏蔽秒的第7位的标志
- minute = ((DS_Buff[1]&0x70)>>4)*10 + (DS_Buff[1]&0x0F);//分(取低7位)
- hour = ((DS_Buff[2]&0x30)>>4)*10 + (DS_Buff[2]&0x0F); //时(取低6位)
- week = (DS_Buff[3]&0x07); //周(取低3位)
- day = ((DS_Buff[4]&0x30)>>4)*10 + (DS_Buff[4]&0x0F); //日(取低6位)
- month = ((DS_Buff[5]&0x10)>>4)*10 + (DS_Buff[5]&0x0F); //月(取低5位)
- year = 2000 + (DS_Buff[6]>>4)*10 + (DS_Buff[6]&0x0F); //年
- }
- /******************************************************************************************
- * 函数名称: DS1307_write_DS_Buffe()
- * 功能说明: 读取DS1307日期时间数据
- * 输 入: 无
- * 输 出: 无
- ******************************************************************************************/
- void DS1307_WriteDate(void)
- {
- bool i;
- week = GetWeek(year,month,day);
- dat[0] = 0; //寄存器地址
- dat[1] = 0; //秒
- dat[2] = ((minute/10)<<4|(minute%10)); //分
- dat[3] = ((hour/10)<<4|(hour%10)); //时
- dat[4] = week; //星期
- dat[5] = ((day/10)<<4|(day%10)); //日
- dat[6] = ((month/10)<<4|(month%10)); //月
- dat[7] = ((year%100)/10<<4|(year%10)); //年
- dat[8] = 16; //0001 0000 = 允许按1Hz输出方波,低电平触发
- i = I2C1_Host_Write(DS1307_Addr_7,&dat,9);
- // i = SI2C_8bitBuffWrite(DS1307_Addr,0,8,dat);
- }