今天继续测试硬件I2C的写读函数。通过逻辑分析仪抓取的时序,发现问题出在开始的写寄存器地址上,其函数结构如下: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);
}
|