昨天开始尝试驱动DS1302模块,这是非标准的I2C通讯接口,因为其不需要指定器件的地址,直接进行I2C操作,我配置了2 个空闲引脚,再加上LED3引脚作RST,测试了半天并动用了逻辑分析仪,最后发现模块的SDA口有问题,写数据时一直无法拉低电平,怀疑模块故障。今天改用DS1307日历模块,这是标准的I2C通讯,器件的地址为0xD0。起初将1.3版本的I2C_POLL_RW_EEPROM中的代码复制到测试程序中,但编译总是出错,最后才知道是与1.2的版本不兼容,只好将整个文件夹复制过来,重新修改为测试项目。
厂家的例程虽然能编译通过,但整个EEPROM测试代码全在main.c文件中,连宏定义都没有独立到头文件中,似乎有点太粗糙,不规范。
我可能有点强迫症,花了不少时间将这些代码分解成i2c.c和i2c.h文件,并逐个函数分析,加上中文注释:
通过整理代码和注释,参照例程中提供的EEPROM测试代码,移植好DS1307日历模块的驱动代码。
在分析代码的过程中,我对I2C的初始化代码还有点迷惑,例程中对引脚先后进行了两次配置,首先配置成普通输出模式,在设置好I2C参数后再配置成I2C模式,不知道为何要如此配置?
从测试的过程看,灵动的HAL库I2C的使用比STM方便的多,设置好器件地址后只要给出要操作的起始地址,数组、长度三个参数就能完成读写操作。下面是相应的代码:
/******************************************************************************************
* 函数名称: DS1307_I2C_Read()
* 功能说明: 读DS1307的日历数据,并转换为各自的变量值
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_I2C_Read(void)
{
//Set the DS1307 address
I2C_SetDeviceAddr(I2C1, 0x00D0);
I2CRead(0x00, DS_Buff, 0x08);
DS1307_BuffToData();
}
/******************************************************************************************
* 函数名称: DS1307_I2C_Write()
* 功能说明: 将当前的日历数据写入DS1307
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_I2C_Write(void)
{
DS1307_DataToBuff(); //时间日期数据转换存入Buff数组中
I2C_SetDeviceAddr(I2C1, 0x00D0);
I2CWrite(0x00, DS_Buff, 0x08);
}
/******************************************************************************************
* 函数名称: DS1307_Init()
* 功能说明: 检查DS1307是否已经初始化,若未初始化则用特写日期进行初始化
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_Init(void)
{
I2C_SetDeviceAddr(I2C1, 0x00D0);
I2CRead(0x00, DS_Buff, 0x08);
if(DS_Buff[0]> 127){
year = 2020;
month = 5;
day = 27;
week = 3;
hour = 16;
minute = 21;
DS1307_DataToBuff();
I2CWrite(0x00, DS_Buff, 0x08);
}
}
/******************************************************************************************
* 函数名称: DS1307_DataToBuff()
* 功能说明: 将时间日期变量数据转换到数组Buff中
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_DataToBuff(void)
{
uint8_t temp;
DS_Buff[0] = 0; //秒
temp = ((minute/10)<<4|(minute%10));
DS_Buff[1] = temp; //分
temp = ((hour/10)<<4|(hour%10));
DS_Buff[2] = temp; //时
DS_Buff[3] = week; //星期
temp = ((day/10)<<4|(day%10));
DS_Buff[4] = temp; //日
temp = ((month/10)<<4|(month%10));
DS_Buff[5] = temp; //月
temp = ((year%100)/10<<4|(year%10));
DS_Buff[6] = temp; //年
DS_Buff[7] = 32; //0010 0000 = 允许按1Hz输出方波
}
/******************************************************************************************
* 函数名称: DS1307_BuffToData()
* 功能说明: 将数组Buff数据转换到时间日期变量中
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_BuffToData(void)
{
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); //时(取低5位)
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显示的效果,因位置有限年份和日月交替显示:
这是通过串口发送到电脑上的数据:
最后是测试项目的打包文件:
test3.rar
(4.04 MB)
|