hu9jj 发表于 2020-5-27 18:24

【MM32 eMiniBoard测评报告】+启用I2C驱动DS1307日历模块

    昨天开始尝试驱动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> 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;                  //秒
    temp = ((minute/10)<<4|(minute%10));
    DS_Buff = temp;               //分
    temp = ((hour/10)<<4|(hour%10));
    DS_Buff = temp;               //时

    DS_Buff = week;               //星期

    temp = ((day/10)<<4|(day%10));
    DS_Buff = temp;               //日
    temp = ((month/10)<<4|(month%10));
    DS_Buff = temp;               //月
    temp = ((year%100)/10<<4|(year%10));
    DS_Buff = temp;               //年
    DS_Buff = 32;               //0010 0000 = 允许按1Hz输出方波
}


/******************************************************************************************
* 函数名称: DS1307_BuffToData()
* 功能说明: 将数组Buff数据转换到时间日期变量中
* 输    入: 无
* 输    出: 无
******************************************************************************************/
void DS1307_BuffToData(void)
{
    second = ((DS_Buff&0x70)>>4)*10 + (DS_Buff&0x0F);//秒,屏蔽秒的第7位的标志
    minute = ((DS_Buff&0x70)>>4)*10 + (DS_Buff&0x0F);//分(取低7位)
    hour = ((DS_Buff&0x30)>>4)*10 + (DS_Buff&0x0F);//时(取低5位)
    week = (DS_Buff&0x07);                              //周(取低3位)
    day = ((DS_Buff&0x30)>>4)*10 + (DS_Buff&0x0F);   //日(取低6位)
    month = ((DS_Buff&0x10)>>4)*10 + (DS_Buff&0x0F); //月(取低5位)
    year = 2000 + (DS_Buff>>4)*10 + (DS_Buff&0x0F);//年
}




    这是测试过程:




    这是LCD显示的效果,因位置有限年份和日月交替显示:



    这是通过串口发送到电脑上的数据:



    最后是测试项目的打包文件:


页: [1]
查看完整版本: 【MM32 eMiniBoard测评报告】+启用I2C驱动DS1307日历模块