# 2.6.10 播报时间

## 2.6.10.1 简介

当你想知道时间单又不方便看时钟时，是不是在想喊一声有人能告诉你现在是几点了。本次课程就是教你如何使用时钟模块加语音模块制作出一个可以播报时间的装置，当你想知道现在是几点了你可以对着它喊"小智小智"等待它应答然后你就可以问他"几点了"或者"现在是几点"

## 2.6.10.2 控制指令表

**命令参数表：**

| 命令码 |          命令词          |   命令回复   |
| :----: | :----------------------: | :----------: |
|   31   | “几点了” 或 “现在是几点” | 正在读取时间 |

**消息号表：**

| 消息号 |      播报语音      |
| :----: | :----------------: |
|   18   | 现在是 xx 点 xx 分 |

## 2.6.10.3 接线图

<span style="color:red;font-size:25px;">请注意本课程的语音模块接线与前面课程不一样，需要调整一下位置以及代码接口否则将无法正常工作！！！</span>

![a93](./media/a93.png)

## 2.6.10.4 代码

```c
// 引入SoftwareSerial库，用于创建软串口通信
#include <SoftwareSerial.h>
//DS3231时钟模块的库
#include <RtcDS3231.h>
#include <SoftwareWire.h>

// 创建软串口对象，使用A5作为RX引脚接收数据，A4作为TX引脚发送数据
SoftwareSerial mySerial(A3, A2);
// 定义变量用于存储从语音模块接收到的控制码
volatile int Voice_Control = 0;  // 初始化为0，确保首次判断时不触发任何指令

SoftwareWire myWire(A4, A5);  //i2c接口
RtcDS3231<SoftwareWire> Rtc(myWire);


/*
 函数功能：通过串口发送具有固定帧格式的数据包
 数据包格式：帧头(0xAA 0x55) + 消息号数据 + 数据1 + 数据2 + 帧尾(0x55 0xAA)
 
 输入参数说明：
  ---Message_Number ：消息号，用于标识命令类型   <必需填写>
  ---data1 ：第一个数据参数  <如果没有数据就输入0>
  ---data2 ：第二个数据参数  <如果没有数据就输入0>
 */
void Uart_SendCmd(int Message_Number, int data1, int data2) {
  // 发送帧头：固定字节0xAA和0x55，用于标识数据包的开始
  mySerial.write(0XAA);
  mySerial.write(0X55);

  // 发送消息号，标识具体的命令类型
  mySerial.write(Message_Number);

  // 发送两个数据参数
  mySerial.write(data1);
  mySerial.write(data2);

  // 发送帧尾：固定字节0x55和0xAA，用于标识数据包的结束
  mySerial.write(0X55);
  mySerial.write(0XAA);
}

void setup() {
  // 初始化硬件串口，用于调试和监控，波特率9600
  Serial.begin(9600);

  // 初始化软串口，用于与语音模块通信，波特率9600
  mySerial.begin(9600);
  //初始化时钟模块函数
  Rtc.Begin();
  Rtc.SetIsRunning(true);
  Rtc.SetDateTime(RtcDateTime(__DATE__, __TIME__));
}

void loop() {
  //获取时间数据
  int hour = Rtc.GetDateTime().Hour();
  int min = Rtc.GetDateTime().Minute();

  // 持续检查软串口是否有来自语音模块的数据
  while (mySerial.available()) {
    // 读取一个字节的数据
    Voice_Control = mySerial.read();

    // 将接收到的数据通过硬件串口输出，便于调试和监控
    Serial.println(Voice_Control);
  }

  //判断是否是播报时间的指令码
  if (Voice_Control == 31) {
    Uart_SendCmd(18, hour, min);
  }
  Voice_Control = 0;
}
```



## 2.6.10.5 代码说明

① 添加库文件，设置串口以及模拟串口的波特率为`9600`，设置模拟串口引脚为RX：A3，TX：A2（<span style="color:red;">注意，语音模块模拟串口接口引脚变化！！</span>）

② 发送消息号`Uart_SendCmd`函数；初始化时钟代码。

③ 定义局部变了`hour`、`min` 并降时钟模块的时与分的数据复制给对应变量。

⑤ 当接收语音控制模块的命令码时判断变量`Voice_Control`中的命令码是否等于`31`，如果是则发生消息号`18`以及data1（时钟），data2（分钟）数据给语音模块

```c
//  Uart_SendCmd(播报消息号, 时数据, 分数据);
Uart_SendCmd(18, hour, min);
```



## 2.6.10.6 代码结果

上传代码成功后，使用唤醒词“小智小智”唤醒小智语音模块，他会回答你“我在”然后你就可以使用命令词进行控制它了，如当前教程，我们就可以这样

**示例：** 你：“小智小智” ，小智：“我在”，你：“几点了” 或 “现在是几点” ，小智：“现在是 xx 点 xx 分”

