Files
STM32F4-Base/IEC60870-Slave/common/IEC60870_Clock.h
T
STF 4c55544f05
CI / L0 静态门禁 (pre-commit) (push) Failing after 45s
CI / L0.5 主机侧单测 (MSVC) (push) Failing after 42s
通信协议代码
2026-10-26 08:31:48 -04:00

107 lines
5.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* IEC 60870-5-101/104 共用时间源接口:读取当前日历、设置实际时钟。
* 读写日历统一采用固定UTC+8标准时间,年份1970..2099;CP56编码另限2000..2099。
* 此处的本地时间指固定UTC+8,不随Windows本地时区设置或夏令时变化。
* 时间源仅考虑Windows系统时钟和RTC,构建时二选一,业务直接调用Clock_Read/Clock_Set。
* Windows实现已提供;RTC目前只保留接入接口,具体芯片驱动暂不实现。
* 与IEC60870_Time的日期转换、CP56编解码分工;不自动接入ASDU或链路单调计时。
*/
#ifndef IEC60870_CLOCK_H
#define IEC60870_CLOCK_H
#include "IEC60870_Time.h"
/*
* 时间源编译选项:0=Windows系统时钟(默认,须在Windows构建),1=RTC预留接口。
* 这是编译时选择,不在运行期间切换;RTC模式不编译Windows读写代码。
* 选项须作用于IEC60870_Clock.c的编译,不能只在业务源文件中定义。
* RTC模式须由板级驱动实现下方的Clock_RTC_Read/Set;本模块不提供芯片驱动。
* 此选项与IEC60870_TIME_USE_PLATFORM的日期转换算法选择相互独立:
* 前者决定从哪里读取/设置当前时间,后者决定如何将UTC秒数转换为日历。
* RTC已提供约定的日历时,Clock读写入口不需要时间戳与日历之间的往返转换。
*/
#ifndef IEC60870_CLOCK_USE_RTC
#define IEC60870_CLOCK_USE_RTC 0
#endif
#if IEC60870_CLOCK_USE_RTC != 0 && IEC60870_CLOCK_USE_RTC != 1
#error "IEC60870_CLOCK_USE_RTC must be 0 (Windows) or 1 (RTC)"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* 时间源的读取结果。日历数值合法与时间质量分开表示。
* is_invalid=1仍须提供合法日历;没有可用日历时,平台读时函数应返回0。
* is_invalid=0仅表示未标记无效,不证明时钟已经校准或与外部时间源同步。
*/
typedef struct {
IEC60870_WallTime_t time; /* 固定UTC+8标准时间,ms为0..999,星期由公共入口重算 */
uint8_t is_invalid; /* 0=未标记无效,1=时间无效;可按业务约定传递给CP56的IV */
} IEC60870_ClockValue_t;
/*
* 构建:IEC60870_Clock.c + IEC60870_Time.c;Windows读写实现在Clock.c内部。
* 以后接RTC时,定义IEC60870_CLOCK_USE_RTC=1并加入实现下方RTC接口的板级驱动。
* 时间源由构建选择,公共接口不需要时钟对象、函数指针绑定或初始化。
* RTC等硬件仍须由应用按驱动要求初始化;同一时钟的读写由调用方串行执行。
* 本模块不提供设备锁,不进行动态内存分配。
*/
/**
* 功能:从构建时选定的时间源读取固定UTC+8标准时间,并校验日历和质量标志。
* 输入:value——接收结果的指针,不得为空。
* 输出:value——合法日历、星期(0=周日..6=周六)及源提供的is_invalid。
* 返回:1 取得格式合法的结果,is_invalid可能为1;0 参数非法、底层失败或结果非法。
* 说明:先读取局部变量,检查完成后才提交输出,失败不修改value。
* 局部结果的is_invalid初始为1,驱动应按实际状态明确填写0或1。
* 调用方须同时检查返回值和is_invalid,读取成功不等于时钟准确或已同步。
*/
int IEC60870_Clock_Read(IEC60870_ClockValue_t *value);
/**
* 功能:将固定UTC+8标准时间交给构建时选定的时间源设置实际时钟。
* 输入:local_time——非空,1970..2099的合法UTC+8标准时间;输入的weekday可忽略。
* 返回:1 底层报告设置成功;0 参数非法、平台不支持设时或底层未报告成功。
* 说明:先检查日历并重算星期,再将副本交给时间源实现,原始输入保持不变。
* Windows分支转换为UTC后调用系统设时接口;RTC分支直接将日历交给驱动。
* 本接口不接收IV/SU;校时报文须先通过CP56转换及业务校时条件检查。
* 不提供硬件写入回滚;失败时设备是否已有部分修改由具体驱动决定。
*/
int IEC60870_Clock_Set(const IEC60870_WallTime_t *local_time);
/*
* RTC预留接入接口:仅RTC模式需要由板级驱动实现,Windows模式不引用这两个符号。
* 业务调用上方公共入口,下面的函数由公共层同步调用,无需注册回调或绑定时钟对象。
* 不得保留输入/输出指针供返回后使用,也不能反向调用公共读写入口。
* 本模块仅声明,不提供空实现或默认成功结果;RTC硬件由应用按驱动要求初始化。
*/
/**
* 功能:由板级驱动读取RTC日历,供IEC60870_Clock_Read调用。
* 输入:value——公共层提供的非空局部结果,其is_invalid初始为1。
* 输出:value——一组一致的固定UTC+8日历和is_invalid=0/1;weekday由公共层重算。
* 返回:1 取得可供检查的日历;0 读取失败或没有可用日历。
* 说明:驱动负责寄存器格式转换及读取一致性,避免读到跨秒、跨日拼接的字段。
* RTC日历的时间基准由设备约定,驱动须保证输出为UTC+8;无毫秒能力时可填写ms=0。
* 即使日历数值合法,停振、掉电等状态仍可能使时间无效,须按实际状态填写质量。
*/
int IEC60870_Clock_RTC_Read(IEC60870_ClockValue_t *value);
/**
* 功能:由板级驱动设置RTC实际时钟,供IEC60870_Clock_Set调用。
* 输入:local_time——非空,公共层已校验并重算星期的UTC+8日历副本,只在调用期间有效。
* 返回:1 驱动报告设置成功;0 设置失败或设备不支持设置。
* 说明:驱动负责将日历转换为芯片要求的寄存器格式,按芯片能力处理毫秒。
* 只读驱动直接返回0;写入失败时可能已有部分寄存器改变,公共层不提供回滚。
*/
int IEC60870_Clock_RTC_Set(const IEC60870_WallTime_t *local_time);
#ifdef __cplusplus
}
#endif
#endif /* IEC60870_CLOCK_H */