30、使用DS1307 RTC模块实现实时时钟功能

使用DS1307 RTC模块实现实时时钟功能

1. 背景与DS1307模块介绍

在开发实时时钟(RTC)功能时,若没有32.768kHz晶体,可以使用带有该晶体的PIC DEM开发板。为了实现RTC功能,有两种方案。一种是编写大量代码来实现24小时时钟显示、日历功能(包含年、月、日),并处理不同月份的天数和闰年问题,但这会使程序变得很长。另一种更便捷的方案是使用DS1307模块,该模块的很多功能由其固件实现,无需编写大量代码,不过需要学习如何控制和使用它。

2. I2C协议基础

DS1307通过I2C协议与微控制器通信。I2C即内部集成电路协议,通信过程中需要有主设备和从设备,主设备可以与多个从设备通信,系统中也可以存在多个主设备。在本应用中,PIC作为主设备,仅与DS1307 RTC模块这一个从设备通信。主设备在通信中既可以作为发送器(如向从设备写入数据),也可以作为接收器(如从从设备读取数据);从设备同样既可以是接收器,也可以是发送器。

3. 主设备向从设备写入数据的过程

主设备向从设备写入数据时,遵循以下步骤:
1. 发送起始位 :主设备在SCL线保持高电平时,将SDA线从高电平拉低,发送“起始”位。
2. 发送地址和控制字节 :主设备发送一个字节,其中第1 - 7位包含要写入的从设备地址,第0位是控制位。逻辑‘1’表示主设备要从从设备读取数据,逻辑‘0’表示要写入数据。对于DS1307,其地址设置为0b1101000x,若要写入数据,该字节为0b11010000(即0XD0)。
3. 接收确认位 :从设备接收到字节后,在时钟为高电平时将SDA线拉低,发送确认位给主设备。
4. 发送数据字节 :主设备先发送一个字节,包含要写入的从设备内存位置,从设备将该数据加载到内部指针中。主设备再发送要写入该地址的数据,从设备写入数据后,指针指向下一个内存地址,并再次发送确认位。主设备可继续发送更多数据。
5. 发送停止位 :主设备在SCL线为高电平时,将SDA线从低电平拉高,发送“停止”位,表示写入结束。

该过程可总结为以下表格:
| 起始位 | 从设备地址 | R/W位 | 确认位 | 内存地址 | 确认位 | 数据 | 确认位 | 最后数据 | 确认位 | 停止位 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| H to L | 0b110100x | 0 | 低 | xxxxxxxx | 低 | xxxxxxxx | 低 | xxxxxxxx | 低 | L to H |

4. 主设备从从设备读取数据的过程

主设备从从设备读取数据前,需先向从设备发送要开始读取的地址,这是一个写入操作。具体步骤如下:
1. 在SDA线上发送起始位。
2. 发送地址和控制字节(0b11010000),告知从设备主设备要写入数据。
3. 从设备响应确认位。
4. 主设备发送要开始读取的起始地址,从设备将该地址加载到指针中。
5. 从设备再次响应确认位。
6. 主设备发送停止位,结束初始写入操作。
7. 主设备告知从设备要从刚发送的起始地址读取数据,具体操作如下:
- 主设备再次发送起始位。
- 发送地址和控制字节(0b11010001),此时第0位为逻辑‘1’,表示要读取数据。
- 从设备发送确认位。
- 从设备发送请求地址的第一个字节数据,然后指针递增。
- 主设备接收数据后,在SDA线上发送确认位。
- 从设备看到确认位后,发送下一个位置的数据,指针再次递增。
- 主设备接收新数据后,再次发送确认位。
8. 发送非确认位(NACK) :当主设备获取到最后一个所需字节数据时,在SDA线上发送非确认位(NACK),即SDA线在第9个时钟信号为高电平时保持高电平。从设备看到NACK位后,停止发送数据。
9. 主设备发送停止位,完成读取操作。

读取操作可总结为以下两个表格:
初始写入操作以设置读取地址
| 起始位 | 从设备地址 | R/W位 | 确认位 | 内存地址 | 确认位 | 停止位 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| H to L | 0b110100x | 0 | 低 | xxxxxxxx | 低 | L to H |

从从设备读取数据操作
| 起始位 | 从设备地址 | R/W位 | 确认位 | 从设备数据 | 主设备确认位 | 最后数据 | 主设备非确认位 | 停止位 |
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
| H to L | 0b110100x | 1 | 低 | xxxxxxxx | 低 | Xxxxxxxx | 高 | L to H |

5. 使用DS1307的代码实现

以下是使用DS1307的代码:

/*
* File:   I2C DS1307 RTC Module
Author: Mr H. H. Ward
*DS1307 RTC program
using the PIC18f4525
Created on 25 July 2018, 13:19
*/
#include <xc.h>
#include <stdio.h>
#include <conFigInternalOscNoWDTNoLVP.h>
#include <4BitLCDPortb.h>
// declare any variables
unsigned char sec = 10, min = 0x59, hour = 0x23, day, 
date = 0x31, month = 0x12, year = 0x20;
//declare any subroutines
void ms13delay (unsigned char (t))
{
    for (n = 0; n <t; n++)
    {
        TMR0 = 0;
        while (TMR0 < 255);
    }
}
void MSSP2CInit()
{
    SSPCON1 = 0x28;
    SSPCON2 = 0x00;
    SSPSTAT = 0x00;
    SSPADD =  0x13;
    TRISCbits.RC3 = 1;
    TRISCbits.RC4 = 1;
}
void MSSP2Cidle()
{
    while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
}
void MSSP2Cwait()
{
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF=0;
}
void MSSP2CStart()
{
    MSSP2Cidle();
    SSPCON2bits.SEN = 1;
}
void MSSP2CStop()
{
    MSSP2Cidle();
    SSPCON2bits.PEN = 1;
}
void MSSP2CRestart()
{
    MSSP2Cidle();
    SSPCON2bits.RSEN = 1;
}
void MSSP2CNACK()
{
    MSSP2Cidle();
    SSPCON2bits.ACKDT = 1;
    SSPCON2bits.ACKEN = 1;
}
void MSSP2CWrite(unsigned char data)
{
    MSSP2Cidle();
    SEND: SSPBUF=data;
    MSSP2Cidle();
    while(SSPCON2bits.ACKSTAT)
    {
        SSPCON2bits.RSEN=1;
        MSSP2Cwait();
        goto SEND;
    }
}
//-------------------------------------------------
unsigned char MSSP2Cread()
{
    MSSP2Cidle();
    SSPCON2bits.RCEN=1;
    while(!BF);
    MSSP2Cidle();
    ACKDT = (1)?0:1;    //check if ack bit received
    ACKEN = 1;          //pg 85/234
    MSSP2Cidle();
    SSPCON2bits.RCEN=0;
    return SSPBUF;
}
unsigned char MSSP2CreadNAck()
{
    MSSP2Cidle();
    SSPCON2bits.RCEN=1;
    while(!BF);
    MSSP2Cidle();
    SSPCON2bits.RCEN=0;
    SSPCON2bits.ACKDT=1;
    SSPCON2bits.ACKEN=1;
    MSSP2Cwait();
    return SSPBUF;
}
void setclock ()
{
    MSSP2Cidle ();
    MSSP2CStart ();
    MSSP2CWrite (0xD0);
    MSSP2CWrite (0);
    MSSP2CWrite ((sec/10<<4)+(sec % 10));
    MSSP2CWrite (min);
    MSSP2CWrite (hour);
    MSSP2CWrite (1);
    MSSP2CWrite (date);
    MSSP2CWrite (month);
    MSSP2CWrite (year);
    MSSP2CStop();
}
void main()
{
    PORTA = 0;
    PORTB = 0;
    PORTC = 0;
    PORTD = 0;
    TRISA = 0XFF;
    TRISB = 0;
    TRISC = 0;
    TRISD = 0;
    ADCON0 = 0;
    ADCON1 = 0X0F;
    OSCCON = 0X74;
    T0CON = 0XC7;
    setUpTheLCD ();
    MSSP2CInit();
    clearTheScreen ();
    setclock ();
    MSSP2Cidle ();
    MSSP2CStart ();
    MSSP2CWrite (0xD0);
    MSSP2CWrite (0);
    MSSP2CStop();
    while (1)
    {
        writeString ("Time ");
        MSSP2Cidle ();
        MSSP2CStart ();
        MSSP2CWrite (0xD1);
        sec = MSSP2Cread();
        min = MSSP2Cread();
        hour = MSSP2Cread();
        day = MSSP2Cread();
        date = MSSP2Cread();
        month = MSSP2Cread();
        year = MSSP2CreadNAck();
        MSSP2CStop();
        MSSP2Cidle ();
        MSSP2CStart ();
        MSSP2CWrite (0xD0);
        MSSP2CWrite (0);
        MSSP2CStop();
        lcdData = ((hour>>4)+0x30);
        lcdOut ();
        lcdData = ((hour & 0x0F)+0x30);
        lcdOut ();
        lcdData = 0x3A;
        lcdOut ();
        lcdData = ((min>>4)+0x30);
        lcdOut ();
        lcdData = ((min & 0x0F)+0x30);
        lcdOut ();
        lcdData = 0x3A;
        lcdOut ();
        lcdData = ((sec>>4)+0x30);
        lcdOut ();
        lcdData = ((sec & 0x0F)+0x30);
        lcdOut ();
        line2();
        writeString ("Date ");
        lcdData = ((date >>4)+0x30);
        lcdOut ();
        lcdData = ((date  & 0X0F)+0x30);
        lcdOut ();
        lcdData = 0x3A;
        lcdOut ();
        lcdData = ((month >>4)+0x30);
        lcdOut ();
        lcdData = ((month  & 0X0F)+0x30);
        lcdOut ();
        lcdData = 0x3A;
        lcdOut ();
        lcdData = ((year >>4)+0x30);
        lcdOut ();
        lcdData = ((year  & 0X0F)+0x30);
        lcdOut ();
        sendcursorhome ();
    }
}
6. 代码分析

代码的主要功能是设置DS1307的时间和日期,并在LCD上显示。具体分析如下:
1. 变量初始化 :在第13行,定义了用于存储秒、分、时、日、日期、月和年的变量,并初始化为特定值,用于在LCD上显示初始时间和日期:

unsigned char sec = 10, min = 0x59, hour = 0x23, day, date = 0x31, month = 0x12, year = 0x20;
  1. 设置时钟 :调用 setclock() 函数设置DS1307的时间和日期,该函数内部依次执行检查I2C线路空闲、发送起始位、写入地址和控制字节、写入时间和日期数据、发送停止位等操作。
  2. 读取时间和日期 :在主循环中,先向LCD发送“Time”字样,然后通过I2C协议从DS1307读取当前时间和日期数据,存储到相应变量中。
  3. 显示时间和日期 :将读取到的时间和日期数据转换为ASCII码,通过 lcdOut() 函数发送到LCD上显示。

通过以上步骤,实现了使用DS1307模块在LCD上显示实时时间和日期的功能。

下半部分

7. 代码详细操作步骤分析

以下是对代码中关键操作步骤的详细分析:

7.1 设置时钟( setclock() 函数)
- 检查I2C线路空闲 :调用 MSSP2Cidle() 函数,确保I2C线路处于空闲状态,避免数据冲突。

MSSP2Cidle ();
  • 发送起始位 :调用 MSSP2CStart() 函数,发送起始位,开始I2C通信。
MSSP2CStart ();
  • 发送地址和控制字节 :调用 MSSP2CWrite(0xD0) 函数,发送DS1307的地址和控制字节,表明要写入数据。
MSSP2CWrite (0xD0);
  • 发送起始地址 :调用 MSSP2CWrite(0) 函数,发送要写入的起始地址(0x00),即DS1307存储秒值的地址。
MSSP2CWrite (0);
  • 写入秒值 :将秒值转换为符合DS1307要求的格式后写入。
MSSP2CWrite ((sec/10<<4)+(sec % 10));

这里将十进制的秒值转换为二进制编码的十进制(BCD)格式,分别处理十位和个位。例如,对于秒值10,先将10除以10得到1,左移4位得到0b00010000,再加上10对10取余的结果0,最终得到0b00010000,即要写入的秒值。
- 写入其他时间和日期数据 :依次写入分、时、日、日期、月和年的值。

MSSP2CWrite (min);
MSSP2CWrite (hour);
MSSP2CWrite (1);
MSSP2CWrite (date);
MSSP2CWrite (month);
MSSP2CWrite (year);
  • 发送停止位 :调用 MSSP2CStop() 函数,发送停止位,结束写入操作。
MSSP2CStop();

7.2 读取时间和日期(主循环部分)
- 发送“Time”到LCD :调用 writeString("Time ") 函数,在LCD上显示“Time”字样。

writeString ("Time ");
  • 检查I2C线路空闲并发送起始位 :确保I2C线路空闲后,发送起始位。
MSSP2Cidle ();
MSSP2CStart ();
  • 发送地址和控制字节以读取数据 :调用 MSSP2CWrite(0xD1) 函数,发送DS1307的地址和控制字节,表明要读取数据。
MSSP2CWrite (0xD1);
  • 读取时间和日期数据 :依次读取秒、分、时、日、日期、月和年的值。
sec = MSSP2Cread();
min = MSSP2Cread();
hour = MSSP2Cread();
day = MSSP2Cread();
date = MSSP2Cread();
month = MSSP2Cread();
year = MSSP2CreadNAck();

其中, MSSP2Cread() 函数用于读取数据并发送确认位, MSSP2CreadNAck() 函数用于读取最后一个字节数据并发送非确认位。
- 发送停止位 :调用 MSSP2CStop() 函数,发送停止位,结束读取操作。

MSSP2CStop();
  • 再次设置读取地址 :为了下次读取,再次向DS1307写入起始地址(0x00)。
MSSP2Cidle ();
MSSP2CStart ();
MSSP2CWrite (0xD0);
MSSP2CWrite (0);
MSSP2CStop();

7.3 显示时间和日期(主循环部分)
- 显示小时 :将小时值的十位和个位转换为ASCII码,通过 lcdOut() 函数发送到LCD上显示。

lcdData = ((hour>>4)+0x30);
lcdOut ();
lcdData = ((hour & 0x0F)+0x30);
lcdOut ();

例如,对于小时值23(二进制0b00100011),右移4位得到0b00000010(即2),加上0x30得到0X32(ASCII码的2);与0x0F进行逻辑与运算得到0b00000011(即3),加上0x30得到0X33(ASCII码的3)。
- 显示分隔符 :发送冒号( : )的ASCII码到LCD上显示。

lcdData = 0x3A;
lcdOut ();
  • 显示分钟和秒 :与显示小时类似,将分钟和秒的值转换为ASCII码并显示。
lcdData = ((min>>4)+0x30);
lcdOut ();
lcdData = ((min & 0x0F)+0x30);
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = ((sec>>4)+0x30);
lcdOut ();
lcdData = ((sec & 0x0F)+0x30);
lcdOut ();
  • 显示日期 :切换到LCD的第二行,显示“Date”字样,然后将日期、月和年的值转换为ASCII码并显示。
line2();
writeString ("Date ");
lcdData = ((date >>4)+0x30);
lcdOut ();
lcdData = ((date  & 0X0F)+0x30);
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = ((month >>4)+0x30);
lcdOut ();
lcdData = ((month  & 0X0F)+0x30);
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = ((year >>4)+0x30);
lcdOut ();
lcdData = ((year  & 0X0F)+0x30);
lcdOut ();
  • 光标回到起始位置 :调用 sendcursorhome() 函数,将LCD的光标回到第一行的起始位置。
sendcursorhome ();
8. 总结与展望

通过以上详细的代码分析,我们了解了如何使用DS1307模块通过I2C协议与微控制器通信,实现实时时间和日期的设置、读取和显示功能。DS1307模块的使用大大简化了实时时钟功能的实现,其固件完成了很多复杂的时间计算和管理任务。

在实际应用中,可以根据需求对代码进行扩展,例如添加用户输入功能,允许用户通过按键等方式设置时间和日期;或者利用DS1307的温度补偿功能,提高时钟的准确性。同时,对于I2C协议的理解和掌握,有助于我们在其他类似的通信场景中灵活应用。

希望本文能帮助你更好地理解和使用DS1307模块,实现自己的实时时钟项目。

以下是主设备与从设备通信的mermaid流程图:

graph TD
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(主设备发送起始位):::process
    B --> C(主设备发送地址和控制字节):::process
    C --> D{从设备是否发送确认位?}:::decision
    D -- 是 --> E(主设备发送数据字节):::process
    D -- 否 --> C(主设备重新发送地址和控制字节):::process
    E --> F{从设备是否发送确认位?}:::decision
    F -- 是 --> G(主设备继续发送数据或发送停止位):::process
    F -- 否 --> E(主设备重新发送数据字节):::process
    G --> H([结束]):::startend

通过这个流程图,可以更直观地理解主设备与从设备之间的通信过程。在实际应用中,根据不同的需求和场景,可以对代码和通信过程进行适当的调整和优化。

7. 代码详细操作步骤分析

以下是对代码中关键操作步骤的详细分析:

7.1 设置时钟( setclock() 函数)
- 检查I2C线路空闲 :调用 MSSP2Cidle() 函数,确保I2C线路处于空闲状态,避免数据冲突。

MSSP2Cidle ();
  • 发送起始位 :调用 MSSP2CStart() 函数,发送起始位,开始I2C通信。
MSSP2CStart ();
  • 发送地址和控制字节 :调用 MSSP2CWrite(0xD0) 函数,发送DS1307的地址和控制字节,表明要写入数据。
MSSP2CWrite (0xD0);
  • 发送起始地址 :调用 MSSP2CWrite(0) 函数,发送要写入的起始地址(0x00),即DS1307存储秒值的地址。
MSSP2CWrite (0);
  • 写入秒值 :将秒值转换为符合DS1307要求的格式后写入。
MSSP2CWrite ((sec/10<<4)+(sec % 10));

这里将十进制的秒值转换为二进制编码的十进制(BCD)格式,分别处理十位和个位。例如,对于秒值10,先将10除以10得到1,左移4位得到0b00010000,再加上10对10取余的结果0,最终得到0b00010000,即要写入的秒值。
- 写入其他时间和日期数据 :依次写入分、时、日、日期、月和年的值。

MSSP2CWrite (min);
MSSP2CWrite (hour);
MSSP2CWrite (1);
MSSP2CWrite (date);
MSSP2CWrite (month);
MSSP2CWrite (year);
  • 发送停止位 :调用 MSSP2CStop() 函数,发送停止位,结束写入操作。
MSSP2CStop();

7.2 读取时间和日期(主循环部分)
- 发送“Time”到LCD :调用 writeString("Time ") 函数,在LCD上显示“Time”字样。

writeString ("Time ");
  • 检查I2C线路空闲并发送起始位 :确保I2C线路空闲后,发送起始位。
MSSP2Cidle ();
MSSP2CStart ();
  • 发送地址和控制字节以读取数据 :调用 MSSP2CWrite(0xD1) 函数,发送DS1307的地址和控制字节,表明要读取数据。
MSSP2CWrite (0xD1);
  • 读取时间和日期数据 :依次读取秒、分、时、日、日期、月和年的值。
sec = MSSP2Cread();
min = MSSP2Cread();
hour = MSSP2Cread();
day = MSSP2Cread();
date = MSSP2Cread();
month = MSSP2Cread();
year = MSSP2CreadNAck();

其中, MSSP2Cread() 函数用于读取数据并发送确认位, MSSP2CreadNAck() 函数用于读取最后一个字节数据并发送非确认位。
- 发送停止位 :调用 MSSP2CStop() 函数,发送停止位,结束读取操作。

MSSP2CStop();
  • 再次设置读取地址 :为了下次读取,再次向DS1307写入起始地址(0x00)。
MSSP2Cidle ();
MSSP2CStart ();
MSSP2CWrite (0xD0);
MSSP2CWrite (0);
MSSP2CStop();

7.3 显示时间和日期(主循环部分)
- 显示小时 :将小时值的十位和个位转换为ASCII码,通过 lcdOut() 函数发送到LCD上显示。

lcdData = ((hour>>4)+0x30);
lcdOut ();
lcdData = ((hour & 0x0F)+0x30);
lcdOut ();

例如,对于小时值23(二进制0b00100011),右移4位得到0b00000010(即2),加上0x30得到0X32(ASCII码的2);与0x0F进行逻辑与运算得到0b00000011(即3),加上0x30得到0X33(ASCII码的3)。
- 显示分隔符 :发送冒号( : )的ASCII码到LCD上显示。

lcdData = 0x3A;
lcdOut ();
  • 显示分钟和秒 :与显示小时类似,将分钟和秒的值转换为ASCII码并显示。
lcdData = ((min>>4)+0x30);
lcdOut ();
lcdData = ((min & 0x0F)+0x30);
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = ((sec>>4)+0x30);
lcdOut ();
lcdData = ((sec & 0x0F)+0x30);
lcdOut ();
  • 显示日期 :切换到LCD的第二行,显示“Date”字样,然后将日期、月和年的值转换为ASCII码并显示。
line2();
writeString ("Date ");
lcdData = ((date >>4)+0x30);
lcdOut ();
lcdData = ((date  & 0X0F)+0x30);
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = ((month >>4)+0x30);
lcdOut ();
lcdData = ((month  & 0X0F)+0x30);
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = ((year >>4)+0x30);
lcdOut ();
lcdData = ((year  & 0X0F)+0x30);
lcdOut ();
  • 光标回到起始位置 :调用 sendcursorhome() 函数,将LCD的光标回到第一行的起始位置。
sendcursorhome ();
8. 总结与展望

通过以上详细的代码分析,我们了解了如何使用DS1307模块通过I2C协议与微控制器通信,实现实时时间和日期的设置、读取和显示功能。DS1307模块的使用大大简化了实时时钟功能的实现,其固件完成了很多复杂的时间计算和管理任务。

在实际应用中,可以根据需求对代码进行扩展,例如添加用户输入功能,允许用户通过按键等方式设置时间和日期;或者利用DS1307的温度补偿功能,提高时钟的准确性。同时,对于I2C协议的理解和掌握,有助于我们在其他类似的通信场景中灵活应用。

希望本文能帮助你更好地理解和使用DS1307模块,实现自己的实时时钟项目。

以下是主设备与从设备通信的mermaid流程图:

graph TD
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(主设备发送起始位):::process
    B --> C(主设备发送地址和控制字节):::process
    C --> D{从设备是否发送确认位?}:::decision
    D -- 是 --> E(主设备发送数据字节):::process
    D -- 否 --> C(主设备重新发送地址和控制字节):::process
    E --> F{从设备是否发送确认位?}:::decision
    F -- 是 --> G(主设备继续发送数据或发送停止位):::process
    F -- 否 --> E(主设备重新发送数据字节):::process
    G --> H([结束]):::startend

通过这个流程图,可以更直观地理解主设备与从设备之间的通信过程。下面再给出一个读取数据的步骤表格,能更清晰地梳理读取操作:
| 步骤 | 操作 | 代码示例 |
| ---- | ---- | ---- |
| 1 | 发送“Time”到LCD | writeString ("Time "); |
| 2 | 检查I2C线路空闲 | MSSP2Cidle (); |
| 3 | 发送起始位 | MSSP2CStart (); |
| 4 | 发送地址和控制字节以读取数据 | MSSP2CWrite (0xD1); |
| 5 | 读取秒值 | sec = MSSP2Cread(); |
| 6 | 读取分钟值 | min = MSSP2Cread(); |
| 7 | 读取小时值 | hour = MSSP2Cread(); |
| 8 | 读取日值 | day = MSSP2Cread(); |
| 9 | 读取日期值 | date = MSSP2Cread(); |
| 10 | 读取月值 | month = MSSP2Cread(); |
| 11 | 读取年值并发送非确认位 | year = MSSP2CreadNAck(); |
| 12 | 发送停止位 | MSSP2CStop(); |
| 13 | 再次检查I2C线路空闲 | MSSP2Cidle (); |
| 14 | 再次发送起始位 | MSSP2CStart (); |
| 15 | 发送地址和控制字节以写入起始地址 | MSSP2CWrite (0xD0); |
| 16 | 发送起始地址 | MSSP2CWrite (0); |
| 17 | 发送停止位 | MSSP2CStop(); |

在实际应用中,根据不同的需求和场景,可以对代码和通信过程进行适当的调整和优化。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值