打印
[PIC®/AVR®/dsPIC®产品]

【Curiosity Nano测评报告】I2C通讯实验

[复制链接]
1078|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hu9jj|  楼主 | 2024-9-27 17:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hu9jj 于 2024-9-27 17:37 编辑

#申请原创#
    I2C是常见的通讯协议之一,用于本次实验的I2C器件是DS1307日历模块,下图就是从某宝购入的日历模块:

    这个模块背面是一颗CR2032电池,正面是一颗DS1307日历芯片及一颗AT24C32EEPROM,以及相应的外围电路。板上还留有DS18B20温湿度传感器的焊盘,但没有安装元件。
    本次先后实验了硬件I2C和软件模拟I2C。

一、硬件I2C实验
    首先进入MCC进行配置,PIC16F13146的I2C外设有主从之分,我手上的I2C设备都是从设备,因此单片机选择为I2C主设备,传输率为最常见的100k:

    生成代码后,根据mssp1.h文件,我们需要使用的主要有三个函数:
    使用I2C1_Write()函数对DS1307进行写入操作:
/****************************************************************************************** 
* 函数名称:        DS1307_write_date()
* 功能说明: 读取DS1307日期时间数据
* 输    入: 无
* 输    出: 无
******************************************************************************************/
void DS1307_WriteDate(void)
{
    uint8_t i, dat[9];
    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_Write(DS1307_Addr_7,dat,9);       //写入1字节地址及8个字节的数据
}

   经测试能够正常写入到DS1307芯片中,但读DS1307却不成功。我最初的读取代码如下:
/****************************************************************************************** 
* 函数名称:        DS1307_read_date()
* 功能说明: 读取DS1307日期时间数据
* 输    入: 无
* 输    出: 无
******************************************************************************************/
void DS1307_ReadDate(void)
{
    uint8_t d=0;
    bool i;
   
    i = I2C1_Write(DS1307_Addr_7,d,1);                     //写入地址0
//    printf("写地址返回值=%d\n",i);
    i = I2C1_Read(DS1307_Addr_7,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);  //年
}
   也就是先写入要读取数据的首地址,再连续读出7个字节的数据,即写地址与读数据是分开操作的。可按照DS1307芯片数据手册,写入地址后没有stop,直接start开始读数据的操作,其时序图如下:

    由于时序不符合要求,因此读出的日期数据不正确。
    之后我改用了I2C1_WriteRead()函数,也就是先写入数据接着再读出数据,按说可以符合DS1307的时序要求,可测试结果却读不出数据。用逻辑分析仪抓取的SCL和SDA时序却是连续不断的固定规律的波形(见下图),折腾了多日仍没有头绪。
    至此,硬件I2C的实验只好告一段落。

二、软件模拟I2C实验
    在MCC中删除I2C的外设,然后RB4引脚为输入模式,RB6引脚为输出模式。其中RB4引脚作为SDA使用,使用过程中根据需要动态设置成输入或输出。RB6引脚则作为SCL使用。

    分析I2C的时序,不外是下列6种时序:

    1、在空闲时,SCL和SDA同时为高,当SDA先拉低,然后SCL紧接着也拉低,此时在总线上产生一个START,即开始信号,这是由主设备发出的;
    2、在SCL由低拉高后,SDA的电平为低,则表示为数据'0',SDA的电平为高,则表示为数据'1';
    3、在传输完8byte数据后,接收方在SCL为低电平时拉低SDA,一直保持到SCL变高后再变低,这就是给发送方的ACK应答信号,表示可以继续进行下一个字节的传递。如果在这个周期中SDA的电平一直为高,则是给发送方的NOACK非应答信号,表示结束字节的传递;
    4、在SCL和SDA同时为低电平时,先拉高SCL的电平,紧接着再拉高SDA的电平,则产生一个STOP停止信号。
    实际上数据‘0’的时序与ACK的时序完全一样,数据‘1’的时序与NOACK的时序完全一样,只不过ACK和NOACK是在一个字节传输结束后,由接收方发出的。
    弄清楚了I2C所必须的时序,就可以编写软件模拟I2C的代码了:
/****************************************************************************************************************************************** 
* 函数名称: SI2C_Start()
* 功能说明: 产生I2C传输的Start信号
* 输    入: 无
* 输    出: 无
******************************************************************************************************************************************/
void SI2C_Start(void)
{
    SDA_OUT();           //SDA输出
    SDA_1();
    SCL_1();             //scl = 1;
    DELAY_microseconds(1);
        SDA_0();             //sda = 0;        scl为高时sda的下降沿表示“起始”
    DELAY_microseconds(1);
        SCL_0();             //scl = 0;钳住I2C总线,准备发送或接收数据 START:when CLK is high,DATA change form high to low
}


/******************************************************************************************************************************************
* 函数名称: SI2C_Stop()
* 功能说明: 产生I2C传输的Stop信号
* 输    入: 无
* 输    出: 无
******************************************************************************************************************************************/
void SI2C_Stop(void)
{
    SDA_OUT();
    SCL_0();             // scl = 0;
    SDA_0();             // STOP:when CLK is high DATA change form low to high
    DELAY_microseconds(1);
    SCL_1();             // scl = 1;
    DELAY_microseconds(1);
    SDA_1();             // sda = 1;        sclk为高时sdat的上升沿表示“停止”
//    DELAY_microseconds(2);
}


/******************************************************************************************************************************************
* 函数名称: SI2C_Send()
* 功能说明: 向IIC总线发送一个字节的数据
* 输    入: byte dat         要发送的数据
* 输    出: 无
******************************************************************************************************************************************/
void SI2C_Send(uint8_t dat)
{
    uint8_t i;
    SDA_OUT();
    SCL_0();             //拉低时钟开始数据传输
    for(i=0;i<8;i++)
    {
        if(dat&0x80)
            SDA_1();     //准备好SDA数据
        else
            SDA_0();
        dat<<=1;
        DELAY_microseconds(1);
        SCL_1();                //拉高时钟等待从设备读取数据
        DELAY_microseconds(2);
        SCL_0();               //拉低时钟准备下一位数据
//  
    }
}


/******************************************************************************************************************************************
* 函数名称: SI2C_Receive()
* 功能说明: 从IIC总线接收一个字节的数据
* 输    入: 无
* 输    出: byte   从IIC总线上接收到得数据
* 注意事项: 无
******************************************************************************************************************************************/
uint8_t SI2C_Receive(void)
{
    uint8_t i,dat = 0;
    SDA_IN();        //设置为输入       
    for(i=0;i<8;i++)
    {
        SCL_0();
        DELAY_microseconds(2);
        SCL_1();
        dat<<=1;
        if(SDA_X() > 0)
            dat|=0x01;
        DELAY_microseconds(2);
    }
    SCL_0();
    return dat;
}


/******************************************************************************************************************************************
* 函数名称: SI2CDoAck()
* 功能说明: 在应答位位置产生应答,从而继续连续传输
* 输    入: 无
* 输    出: 无
******************************************************************************************************************************************/
void SI2CDoAck(void)
{
    SCL_0();
    SDA_OUT();
    SDA_0();              //sda = 0;        /拉低数据线,即给于应答
    DELAY_microseconds(1);
    SCL_1();              //scl = 1;
    DELAY_microseconds(2);
    SCL_0();                  //scl = 0;
}


/******************************************************************************************************************************************
* 函数名称: SI2CNoAck()
* 功能说明: 在应答位位置不产生应答,从而终止连续传输
* 输    入: 无
* 输    出: 无
******************************************************************************************************************************************/
void SI2CNoAck(void)
{
    SCL_0();
    SDA_OUT();
    SDA_1();              // sda = 1;        不拉低数据线,即不给于应答
    DELAY_microseconds(1);
    SCL_1();              // scl = 1;
    DELAY_microseconds(2);
    SCL_0();              // scl = 0;
}


/******************************************************************************************************************************************
* 函数名称: SI2CIsAck()
* 功能说明: 检测从机应答位
* 输    入: 无
* 输    出: uint8_t        0=ACK_OK 从机产生了应答;1=ACK_NO 从机没有产生应答
******************************************************************************************************************************************/
uint8_t SI2CIsAck(void)
{
    uint8_t i;
    SDA_OUT();
    SDA_1();              // sda = 1; 释放数据线
    DELAY_microseconds(1);
    SDA_IN();
    SCL_1();              // scl = 1;
    DELAY_microseconds(1);
    while(SDA_X() > 0){
        i++;
        if(i > 250){
            SI2C_Stop();//数据线未被拉低,即未收到应答
            SDA_OUT();
            return 1;
        }
    }
    SCL_0();
    DELAY_microseconds(1);
    SDA_OUT();
    return 0;
}
   以上是模拟I2C的基础代码,由此可以写出8位寄存器地址的单个字节读写或多个字节读写的函数:
/********************************************************************************************** 
* 函数名称: I2C_8bitByteWrite()
* 功能说明: 向I2C器件的地址addr开始写入一个字节的数据
* 输    入: uint8_t addr     器件地址
*           uint8_t reg      寄存器地址
*           uint8_t data     要写入的数据
* 输    出: uint8_t        0=成功向器件写入数据  大于1=向器件写入数据过程中出现错误
**********************************************************************************************/
uint8_t SI2C_8bitByteWrite(uint8_t addr,uint8_t reg,uint8_t data)
{
    SI2C_Start();         //产生起始信号
    SI2C_Send(addr|0);    //发送器件地址及读写位,0表示写
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 1;
    }

    SI2C_Send(reg);       //发送数据要写入的地址
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 2;
    }

    SI2C_Send(data);      //写入数据
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 3;
    }

    SI2C_Stop();          //产生停止信号
    return 0;
}

/**********************************************************************************************
* 函数名称: I2C_8bitByteRead()
* 功能说明: 从I2C器件的地址addr读取1字节数据
* 输    入: uint8_t addr     器件地址
*           uint8_t reg      读取数据的地址
* 输    出: 读取的数据
**********************************************************************************************/
uint8_t SI2C_8bitByteRead(uint8_t addr,uint8_t reg)
{
    uint8_t data;

    SI2C_Start();         //产生起始信号
    SI2C_Send(addr);      //发送器件地址及读写位,0表示写
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 2;
    }
    SI2C_Send(reg);       //发送读取数据的起始地址
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();          //产生停止信号
        return 3;
    }

    SI2C_Start();         //产生Repeated Start
    SI2C_Send(addr|1);    //发送器件地址及读写位,1表示读
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 4;
    }

    data = SI2C_Receive();//从addr处读取1个字节的数据
      
    SI2CNoAck();          //器件要求必须使用NOAck来结束数据读取
    SI2C_Stop();          //产生停止信号

    return data;
}

/**********************************************************************************************
* 函数名称: I2C_8bitBuffWrite()
* 功能说明: 向I2C器件的地址addr开始写入size个字节的数据,将要写入的数据存储在全局变量I2C_Buff中
* 输    入: uint8_t addr     器件地址
*           uint8_t reg      写入数据的寄存器地址
*           uint8_t size     要设置的数据个数(1~16),数据在buf[]中
* 输    出: uint8_t        0=成功向器件写入数据  大于1=向器件写入数据过程中出现错误
**********************************************************************************************/
uint8_t SI2C_8bitBuffWrite(uint8_t addr,uint8_t reg,uint8_t size,uint8_t *buf)
{
    uint8_t i = 0;

    SI2C_Start();         //产生起始信号
    SI2C_Send(addr|0);    //发送器件地址及读写位,0表示写
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 1;
    }

    SI2C_Send(reg);       //发送数据要写入的地址
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 2;
    }

    for(i=0; i<size; i++)
    {
        SI2C_Send(buf[i]);
        if(SI2CIsAck())   //检测器件是否有响应
        {
            SI2C_Stop();  //产生停止信号
            return 3;
        }
    }

    SI2C_Stop();          //产生停止信号
       
    return 0;
}


/******************************************************************************************
* 函数名称: I2C_8bitBuffRead()
* 功能说明: 从指定的I2C器件地址addr开始获取size个字节的数据,获取的数据存储在全局变量I2C_Buff中
* 输    入: uint8_t addr     I2C器件地址
*           uint8_t reg      获取数据从addr开始
*           uint8_t size     要获取的数据个数(1~16)
* 输    出: 从器件获取数据(在全局变量数组DS_Buff中)
******************************************************************************************/
uint8_t SI2C_8bitBuffRead(uint8_t addr,uint8_t reg,uint8_t size)
{
    uint8_t i = 0;

    SI2C_Start();         //产生起始信号
    SI2C_Send(addr);      //发送器件地址及读写位,0表示写
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 2;
    }

    SI2C_Send(reg);       //发送读取数据的起始地址
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 3;
    }

    SI2C_Start();         //产生Repeated Start
    SI2C_Send(addr|1);    //发送器件地址及读写位,1表示读
    if(SI2CIsAck())       //检测器件是否有响应
    {
        SI2C_Stop();      //产生停止信号
        return 4;
    }

    for(i=0;i<size;i++)    //从addr处开始读取size个字节的数据
    {
        DS_Buff[i] = SI2C_Receive();
        if(i+1==size)
            SI2CNoAck();   //器件要求必须使用NOAck来结束数据读取
        else
            SI2CDoAck();
    }

    SI2C_Stop();          //产生停止信号

    return 0;
}
   有了以上函数,就可以进一步写出DS1307的读写函数了:
/****************************************************************************************** 
* 函数名称:        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)
{
    uint8_t d=0;
    bool i;

    d = SI2C_8bitByteRead(DS1307_Addr,0);
        if(d > 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)
{
    uint8_t d=0;
    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)
{
    uint8_t i, dat[8];
    week = GetWeek(year,month,day);
    dat[0] = 0;                                //秒
    dat[1] = ((minute/10)<<4|(minute%10));     //分
    dat[2] = ((hour/10)<<4|(hour%10));         //时
    dat[3] = week;                             //星期
    dat[4] = ((day/10)<<4|(day%10));           //日
    dat[5] = ((month/10)<<4|(month%10));       //月
    dat[6] = ((year%100)/10<<4|(year%10));     //年
    dat[7] = 16;                               //0001 0000 = 允许按1Hz输出方波,低电平触发
    i = SI2C_8bitBuffWrite(DS1307_Addr,0,8,dat);
}
   至此,成功地完成了对DS1307的读写操作实验。
    软件模拟I2C比较灵活直观,不象使用硬件I2C那样有“隔靴搔痒”的感觉,而且还能够适应某些特殊的I2C设备,因此深受大家的喜爱。在上述的读写函数中扩充寄存器地址的长度,还可以适应16位甚至更高位寄存器的地址器件。




I2C_5.png (303.87 KB )

I2C_5.png

I2C_4.png (252.64 KB )

I2C_4.png

I2C_3.png (292.59 KB )

I2C_3.png

I2C_2.png (316.72 KB )

I2C_2.png

使用特权

评论回复
沙发
小灵通2018| | 2024-9-29 19:42 | 只看该作者
看着不错。比较好用。

使用特权

评论回复
板凳
21mengnan| | 2024-9-30 11:59 | 只看该作者
看着很好用。

使用特权

评论回复
地板
单片小菜| | 2024-9-30 13:52 | 只看该作者
void DS1307_WriteDate(void)这个函数进不去

使用特权

评论回复
5
自己造声卡| | 2024-9-30 14:14 | 只看该作者
直接上函数,代码看的太累了。

使用特权

评论回复
6
hu9jj|  楼主 | 2024-9-30 17:28 | 只看该作者
  今天继续测试硬件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);
}






使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:Microchip
简介:让我们来为您提供帮助。我们可提供各种资源来帮助您解决一切问题。是否需要与我们的客户支持团队联系?您可以通过电话、在线聊天功能或电子邮件与他们联系。

151

主题

1059

帖子

11

粉丝