#申请原创#
之前多次测试PIC及AVR的核心板都是使用模拟I2C来对DS1307日历模块进行读写操作,感觉硬件I2C操控起来不知从何处下手,没有模拟I2C那么得心应手。为了熟悉和掌握硬件I2C的使用,本次就没有使用模拟I2C,直接进行硬件I2C的测试。
在用MCC进行配置的时候,可以添加一个I2C使用的范例文件:
在这个范例文件中为我们提供了几个I2C读写操作的函数:
在以前的评测中我也曾经尝试过使用硬件I2C,但从来设有成功过。经过多次测试和分析,后来明白了在使用这些函数时,I2C器件的地址要用7位而不是我习惯的8位,因为在读写操作时,函数会将7位地址左移1位然后再加上读写操作码。
关于DS1307日历模块网上有很多的资料,这里只是简单介绍一下数据的储存方式和读写操作:
开机时一般先读入地址0的数据,若CH(位7)为1,则表明日历模块尚未启动,应该对其设置日期及时间,因此我们要用上读指定地址一个字节数据的函数;
设置日期及时间需要连续写入7~8个字节的数据,因此我们需要使用写多个字节数据的函数;
同样,在读取日历模块的日期及时间需要使用读多个字节的函数:
在测试过程中,读取一个字节数据的函数没有问题,一次调试即成功:
/******************************************************************************************
* 函数名称: DS1307_Init()
* 功能说明: 用当前日期(yesr,month,day,hour,minute,second)初始化DS1307
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_Init(void)
{
uint8_t i;
i = I2C1_Read1ByteRegister(DS1307_Addr_7,0);
// LCD_write_value(0,3,3,0,0,i);//监测读取值
if(i > 127){
year = 2021;
month = 5;
day = 31;
week = 1;
hour = 14;
minute = 30;
second = 0;
DS1307_write_date();
// I2C1_WriteNBytes(DS1307_Addr_7,DS_Buff,8);
}
else
DS1307_read_date();
}
开始测试时,初始化日期写操作使用的是I2C1_WriterNBytes()函数(也就是上面代码中注释行),但读取时日期数据不正确,通过使用逻辑分析仪抓取时序,发现基本操作是符合要求的,但实际写入的数据却大相径庭,完全不是数组中的值:
我将要写入的数据与实际写入的数据进行了对比,两者之间没有规律,不知道是什么原因造成的,也许是数据传递过程中出了问题吧:
之后我测试了单个数据的写入函数,写入正确,于是是只好通过循环,依次将数组中的数据写入,下面是最后通过的写操作函数:
/******************************************************************************************
* 函数名称: DS1307_write_date()
* 功能说明: 读取DS1307日期时间数据
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_write_date(void)
{
uint8_t i;
DS_Buff[0] = 0; //秒
DS_Buff[1] = ((minute/10)<<4|(minute%10)); //分
DS_Buff[2] = ((hour/10)<<4|(hour%10)); //时
DS_Buff[3] = week; //星期
DS_Buff[4] = ((day/10)<<4|(day%10)); //日
DS_Buff[5] = ((month/10)<<4|(month%10)); //月
DS_Buff[6] = ((year%100)/10<<4|(year%10)); //年
DS_Buff[7] = 16; //0001 0000 = 允许按1Hz输出方波,低电平触发
for(i=0; i<8; i++ ){
I2C1_Write1ByteRegister(DS1307_Addr_7,i,DS_Buff[i]); //写入8个字节数据
}
}
读操作的函数测试很顺利,没有什么时周折:
/******************************************************************************************
* 函数名称: DS1307_read_date()
* 功能说明: 读取DS1307日期时间数据
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_read_date(void)
{
I2C1_ReadDataBlock(DS1307_Addr_7,0,DS_Buff,7); //读取前7个字节数据
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); //年
}
这是测试过程的照片:
这是LCD日历显示的效果:
这是测试项目的压缩包:
MyTest.X.rar
(1.23 MB)
|