更新时间:2024-04-08 08:18:04下载pdf
智能设备在很多场景下存在时间显示或使用系统时间做功能逻辑等需求,并需要保证时间准确。MCU 标准协议接入支持 MCU 通过 Wi-Fi 模组和 Wi-Fi & 蓝牙双模模组获取格林时间和本地时间,设备在连接网络后,MCU 通过指令获取当前的系统时间。
模组在网期间每次 HTTP 交互时会与云端校时,无交互时设备会间隔 6 小时定期到云端校时一次。模组自身带有软件 RTC,MCU 获取到的时间是模组自身软件 RTC 的时间,在模组离线期间 MCU 也可以获取到时间。同时,模组支持时间服务通知说明功能。Wi-Fi 模组和 Wi-Fi & 蓝牙双模模组上电重新入网后,时间与云端校准后主动通知 MCU。
时间服务涉及以下协议指令:
命令字 | 命令说明 |
---|---|
0x0c | 获取格林时间 |
0x1c | 获取本地时间 |
0x34(子命令 0x01) | 打开时间服务通知 |
0x34(子命令 0x02) | 模组时间服务通知 |
格林时间是一个国际标准的时间基准,不带有时区和夏令时。当模组连接上网络后,本地的时间戳校准完成才会返回成功,并携带有效的时间数据。
0x03
后,也可以实现时间戳校准功能。设备与 App 连接建立时,App 需要连接外网。0x04
后,模组会执行时间戳校准功能。MCU 发送
字段 | 字节数 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x03 |
命令字 | 1 | 0x0c |
数据长度 | 2 | 0x0000 |
数据 | 0 | 无 |
校验和 | 1 | 从帧头开始,按字节求和,得出的结果对 256 求余 |
示例:55 aa 03 0c 00 00 0e
模组返回
字段 | 字节数 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x00 |
命令字 | 1 | 0x0c |
数据长度 | 2 | 0x0007 |
数据 | 7 | 数据长度为 7 字节:
|
校验和 | 1 | 从帧头开始,按字节求和,得出的结果对 256 求余 |
示例:格林时间 2016 年 4 月 19 日 5 时 6 分 7 秒
55 aa 00 0c 00 07 01 10 04 13 05 06 07 4c
本地时间是在格林时间的基础上加上当地(设备激活所在地)时区和夏令时的时间。当模组连接上网络后,本地的时间戳校准完成才会返回成功,并带有有效的时间数据。
当地时间是指配网时手机的系统时区。
0x03
后,也可以实现时间戳校准功能。设备与 App 连接建立时,App 需要连接外网。0x04
后,模组会执行时间戳校准功能。MCU 发送
字段 | 字节数 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x03 |
命令字 | 1 | 0x1c |
数据长度 | 2 | 0x0000 |
数据 | 0 | 无 |
校验和 | 1 | 从帧头开始,按字节求和,得出的结果对 256 求余 |
示例:55 aa 03 1c 00 00 1e
模组返回
字段 | 字节数 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x00 |
命令字 | 1 | 0x1c |
数据长度 | 2 | 0x0008 |
数据 | 8 | 数据长度为 8 字节:
|
校验和 | 1 | 从帧头开始,按字节求和,得出的结果对 256 求余 |
模组上电并连接上云之后时间戳并不会马上校准,需要大约 10 秒才能正确校准时间,模组上电后该功能默认关闭,此时间周期内 MCU 不断地重试获取时间。开启时间服务通知功能后,Wi-Fi 和 Wi-Fi & 蓝牙模组上电、连接云,并与云端校准时间后主动通知 MCU。
上电后 MCU 发送打开时间服务通知指令,并选择格林时间或本地时间,模组收到后将开启 时间服务通知,并返回开启结果至 MCU。
MCU 发送
字段 | 长度 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x03 |
命令字 | 1 | 0x34 |
数据长度 | 2 | 0x0002 |
数据 | 1 | 0x01(子命令) |
1 |
|
|
校验和 | 1 | 从帧头开始按字节求和得出的结果对 256 求余 |
示例:55 aa 03 34 00 02 01 01 3a
模组返回
字段 | 字节数 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x00 |
命令字 | 1 | 0x34 |
数据长度 | 2 | 0x0002 |
数据 | 1 | 0x01(子命令) |
1 |
|
|
校验和 | 1 | 从帧头开始按字节求和得出的结果对 256 求余 |
示例:55 aa 00 34 00 02 01 00 36
指令使用:模组时间与云端校准后,当前模组 时间服务通知 已打开,模组发送相对应的时间数据给至 MCU。
模组重新上电后,时间服务通知默认为关闭,需要 MCU 发送 打开时间服务通知(0x34 子命令 0x01) 指令。
模组发送
字段 | 长度 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x00 |
命令字 | 1 | 0x34 |
数据长度 | 2 | 0x0009 |
数据 | 1 | 0x02(子命令) |
1 |
|
|
7 | 数据长度为 6 字节。
|
|
校验和 | 1 | 从帧头开始按字节求和得出的结果对 256 求余 |
示例:Type:1(本地时间),Time:2021/08/23 18:35:28 星期一
55 aa 00 34 00 09 02 01 15 08 17 12 23 1c 01 c5
MCU 返回
字段 | 字节数 | 说明 |
---|---|---|
帧头 | 2 | 0x55aa |
版本 | 1 | 0x03 |
命令字 | 1 | 0x34 |
数据长度 | 2 | 0x0001 |
数据 | 1 | 0x02(子命令) |
校验和 | 1 | 从帧头开始按字节求和得出的结果对 256 求余 |
示例:55 aa 03 34 00 01 02 39
打开 SUPPORT_GREEN_TIME
宏定义,开启格林时间功能。
#define SUPPORT_GREEN_TIME //开启格林时间功能
获取格林时间函数 mcu_get_green_time()
定义在 mcu_api.c
文件中,MCU 主动调用 mcu_get_green_time()
函数,发送格林时间获取指令。
/**
* @brief MCU 获取格林时间
* @param Null
* @return Null
* @note MCU 需要自行调用该功能
*/
void mcu_get_green_time(void)
{
wifi_uart_write_frame(GET_ONLINE_TIME_CMD, MCU_TX_VER, 0);
}
在串口接收数据处理函数 data_handle()
中,收到模组发来的获取结果后,将调用 mcu_get_greentime()
函数接收判断,并做下一步处理。
void data_handle(unsigned short offset)
{
......
#ifdef SUPPORT_GREEN_TIME
case GET_ONLINE_TIME_CMD: //获取格林时间
mcu_get_greentime((unsigned char *)(wifi_data_process_buf + offset + DATA_START));
break;
#endif
......
}
获取到的格林时间,您需实现该函数。
/**
* @brief 获取到的格林时间
* @param[in] {time} 获取到的格林时间数据
* @return Null
* @note MCU 需要自行实现该功能
*/
void mcu_get_greentime(unsigned char time[])
{
#error "请自行完成相关代码,并删除该行"
/*
time[0] 为是否获取时间成功标志,0 表示失败,1 表示成功
time[1] 为年份,0x00 表示 2000 年
time[2] 为月份,从 1 开始到 12 结束
time[3] 为日期,从 1 开始到 31 结束
time[4] 为时钟,从 0 开始到 23 结束
time[5] 为分钟,从 0 开始到 59 结束
time[6] 为秒钟,从 0 开始到 59 结束
*/
if(time[0] == 1) {
//正确接收到 Wi-Fi 模组返回的格林数据
}else {
//获取格林时间出错,有可能是当前 Wi-Fi 模组未联网
}
}
调试助手示意图如下:
打开 SUPPORT_MCU_RTC_CHECK
宏定义,开启本地时间功能。
#define SUPPORT_MCU_RTC_CHECK //开启校时功能
获取本地时间函数 mcu_get_system_time()
定义在 mcu_api.c
文件中,MCU 主动调用 mcu_get_system_time()
函数,发送本地时间获取指令。
/**
* @brief MCU 获取系统时间,用于校对本地时钟
* @param Null
* @return Null
* @note MCU 主动调用完成后在 mcu_write_rtctime 函数内校对 rtc 时钟
*/
void mcu_get_system_time(void)
{
wifi_uart_write_frame(GET_LOCAL_TIME_CMD, MCU_TX_VER, 0);
}
在串口接收数据处理函数 data_handle()
中,收到模组发来的获取结果后,调用 mcu_write_rtctime()
函数接收判断,并做下一步处理。
void data_handle(unsigned short offset)
{
......
#ifdef SUPPORT_MCU_RTC_CHECK
case GET_LOCAL_TIME_CMD: //获取本地时间
mcu_write_rtctime((unsigned char *)(wifi_data_process_buf + offset + DATA_START));
break;
#endif
......
}
获取到的本地时间,可校对本地 RTC 时钟,您需实现该函数。
/**
* @brief MCU 校对本地 RTC 时钟
* @param[in] {time} 获取到的格林时间数据
* @return Null
* @note MCU 需要自行实现该功能
*/
void mcu_write_rtctime(unsigned char time[])
{
#error "请自行完成 RTC 时钟写入代码,并删除该行"
/*
Time[0] 为是否获取时间成功标志,0 表示失败,1 表示成功
Time[1] 为年份,0x00 表示 2000 年
Time[2] 为月份,从 1 开始到 12 结束
Time[3] 为日期,从 1 开始到 31 结束
Time[4] 为时钟,从 0 开始到 23 结束
Time[5] 为分钟,从 0 开始到 59 结束
Time[6] 为秒钟,从 0 开始到 59 结束
Time[7] 为星期,从 1 开始到 7 结束,1 代表星期一
*/
if(time[0] == 1) {
//正确接收到 Wi-Fi 模组返回的本地时钟数据
}else {
//获取本地时钟数据出错,有可能是当前 Wi-Fi 模组未联网
}
}
调试助手示意图如下:
打开 MODULE_EXPANDING_SERVICE_ENABLE
宏定义,开启模组拓展服务功能。
#define MODULE_EXPANDING_SERVICE_ENABLE //开启模组拓展服务功能
打开时间服务通知函数 open_module_time_serve()
定义在 mcu_api.c
文件中,MCU 主动调用 open_module_time_serve()
函数,发送打开模组时间服务通知指令,并选择服务时间类型。
/**
* @brief 打开模组时间服务通知
* @param[in] {time_type} 时间类型
* @ref 0x00: 格林时间
* @ref 0x01: 本地时间
* @return Null
* @note MCU 需要自行调用该功能
*/
void open_module_time_serve(unsigned char time_type)
{
unsigned short send_len = 0;
send_len = set_wifi_uart_byte(send_len, 0x01);
send_len = set_wifi_uart_byte(send_len, time_type);
wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
}
在串口接收数据处理函数 data_handle()
中,收到模组发来的获取结果后,调用模组拓展功能函数 open_module_time_serve_result()
接收判断,并做下一步处理。
```c
void data_handle(unsigned short offset)
{
......
#ifdef MODULE_EXPANDING_SERVICE_ENABLE
case MODULE_EXTEND_FUN_CMD: //模组拓展服务
total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
break;
#endif
......
}
```
打开模组时间服务通知结果,您需实现该函数。
/**
* @brief 打开模组时间服务通知结果
* @param[in] {value} 数据缓冲区
* @param[in] {length} 数据长度
* @return Null
* @note MCU 需要自行实现该功能
*/
void open_module_time_serve_result(const unsigned char value[], unsigned short length)
{
......
case 0x01: { //子命令 打开模组时间服务通知
if(0x02 != length) {
//数据长度错误
return;
}
if(value[1] == 0) {
//服务开启成功
} else {
//服务开启失败
}
}
break;
......
}
调试助手示意图如下:
打开 MODULE_EXPANDING_SERVICE_ENABLE
宏定义,开启模组拓展服务功能。
#define MODULE_EXPANDING_SERVICE_ENABLE //开启模组拓展服务功能
在串口接收数据处理函数 data_handle()
中,收到模组发来的获取结果后,调用模组拓展功能函数 open_module_time_serve_result()
接收判断,并做下一步处理。
void data_handle(unsigned short offset)
{
......
#ifdef MODULE_EXPANDING_SERVICE_ENABLE
case MODULE_EXTEND_FUN_CMD: //模组拓展服务
total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW];
open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len);
break;
#endif
......
}
模组时间服务通知结果,您需实现该函数。
/**
* @brief 模组时间服务通知结果
* @param[in] {value} 数据缓冲区
* @param[in] {length} 数据长度
* @return Null
* @note MCU 需要自行实现该功能
*/
void open_module_time_serve_result(const unsigned char value[], unsigned short length)
{
......
case 0x02: { //子命令 模组时间服务通知
if(0x09 != length) {
//数据长度错误
return;
}
unsigned char time_type = value[1]; //0x00:格林时间 0x01:本地时间
unsigned char time_data[7];
my_memcpy(time_data, value + 2, length - 2);
/*
Data[0]为年份, 0x00 表示 2000 年
Data[1]为月份,从 1 开始到 12 结束
Data[2]为日期,从 1 开始到 31 结束
Data[3]为时钟,从 0 开始到 23 结束
Data[4]为分钟,从 0 开始到 59 结束
Data[5]为秒钟,从 0 开始到 15 结束
Data[6]为星期,从 1 开始到 7 结束,1 代表星期一
*/
//在此处添加时间数据处理代码,time_type 为时间类型
unsigned short send_len = 0;
send_len = set_wifi_uart_byte(send_len,sub_cmd);
wifi_uart_write_frame(MODULE_EXTEND_FUN_CMD, MCU_TX_VER, send_len);
}
break;
......
}
调试助手示意图如下:
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈