8.1 KiB
8.1 KiB
DCU_HOST 项目 lib60870 CBB 库调用参考
用途: RTU 项目开发 IEC 101/104 时的参考工程 源项目: DCU_HOST (科大智能 DCU 通信板) 原理由: DCU_HOST 已成熟使用 lib60870 CBB 库实现 101/104 从站,调用模式可直接参考
1. DCU_HOST 项目背景
DCU_HOST 是基于 RT-Thread 实时操作系统的嵌入式通信板项目,运行在 STM32H743 平台。其 applications/iec_prtcl/ 模块是对 lib60870 CBB 规约库的完整封装。
1.1 模块文件结构
DCU_HOST/applications/
├── iec_prtcl/ # ★ IEC 规约应用层
│ ├── Iec_Use.h # CS10x 实体封装 + 外部接口声明
│ ├── Iec_Use.c # ★ 主循环驱动 (IecEntry) + 收/发/调度
│ ├── Protocol_Config.h # 参数配置接口声明
│ └── Protocol_Config.c # ★ 参数配置 + 回调注册 (SetProtocolItfc)
├── data/iec_itfc/ # ★ 数据回调层 (规约 ↔ 业务数据)
│ ├── YcItfc.c/h # 遥测回调 (GetYcCountByGroup / GetYcValueByGroup)
│ ├── YxItfc.c/h # 遥信回调 + SOE 回调
│ ├── YkItfc.c/h # 遥控回调 (SetYkInfor / YkResultNofify)
│ ├── GbParamItfs.c/h # ★ 参数/定值读写回调 (882行)
│ ├── DdItfc.c/h # 电度回调
│ ├── FaultItfc.c/h # 故障事件回调
│ └── FileParamItfs.c/h # 文件服务回调
└── cbblibs/lib60870/ # lib60870 CBB 库 (git submodule)
1.2 lib60870 CBB 库版本
与 RTU 项目使用同一套 CBB 库(同为科大智能 IECVer2.01.059_260202),API 完全一致。
2. 核心架构:实体池 + 线程驱动
2.1 实体封装 stLIB60870ENTITY
DCU_HOST 将 CS10x 封装了一层:
#define MAX_CS10X_NUM 2 // 最大支持 2 个 CS10x 实例 (如一路104 + 一路101)
typedef struct {
u8 ucBusy; // 是否使用中
u8 ucType; // PRTCL_104_S / PRTCL_101_S
u32 uiItfs; // 绑定的通信接口编号 (如 ETH0=0x0A000001)
u32 uiTime; // 链路空闲超时累计 (ms)
stLIB60870BUFF stBuf; // 内部收发缓冲区
CS10x stCs10x; // ★ CBB 库的 CS10x 结构体 (值语义)
} stLIB60870ENTITY;
// 全局实体池
stLIB60870ENTITY g_astLib60870Entity[MAX_CS10X_NUM];
2.2 线程入口 IecEntry()
void IecEntry(void *pvArg) {
// 1. 创建 10ms 周期定时器
rt_timer_create("IEC_tm1", TmExpire, ..., 10, RT_TIMER_FLAG_PERIODIC);
// 2. 初始化环形缓冲区 (用于跨线程数据传递)
IecRingblkInit();
// 3. 主循环
while(1) {
rt_event_recv(..., &uiEvent); // 等待事件
if(uiEvent & EV_TIMER1_IEC) {
Schedule60870(10); // ★ 10ms 驱动一次
}
if(uiEvent & EV_PARA_UPDATE) {
UpdateParamLib60870(...); // 参数热更新
}
rb_channel_process(&g_stIecChannel); // 处理收到的数据
}
}
2.3 数据接收链路
串口/网口收数据
→ CommChannel_SendData / 加密解密
→ IecRingblkInput(pucData, usLen, uiItfs) // 写入环形缓冲
→ rb_channel_process() // 主循环中消费
→ RecvDateProtocolItfs()
→ DataProc60870()
├── GetEntity60870(ucType, uiItfs) // 获取/创建实体
│ ├── pstEntity->ucBusy = 1
│ ├── memset(&stCs10x, 0, sizeof(CS10x))
│ ├── 绑定缓冲区指针
│ ├── ProtocolEntityConfig() → CS10x_104Init / CS10x_101Init
│ └── Cs10xConfig() → 参数配置 + 回调注册
└── CS10x_DoRecv(&pstEntity->stCs10x, pucData, usLen) // ★ 喂给规约栈
2.4 发送回调
s32 DataSend60870(u8 *pucBuf, u16 usLen, void* pvArg) {
u32 uiItfs = *(u32*)pvArg; // pvArg = &pstEntity->uiItfs
return CommChannel_SendData(pucBuf, usLen, uiItfs);
}
3. 初始化流程
3.1 104 从站初始化
// 1. 选择协议类型
enType = CS104_TYPE_S; // 或 CS101_TYPE_S
// 2. 初始化规约栈
CS10x_104Init(pCs10x, DataSend60870, &pstEntity->uiItfs, enType);
// 3. 配置参数 (通过参数映射表)
Cs10xConfig(pstEntity, &g_stParamMappingTable);
// → SetProtocol104Param()
// ├── CS10x_SetAppParameters(&stAppParam)
// ├── CS10x_SetAPCIParameters(&stApciParam)
// ├── CS10x_SetYcType(浮点/整形)
// ├── CS10x_SetYxType(单点/双点)
// ├── CS10x_SetDdType / CS10x_FrameGap / CS10x_SetMultFrameEn
// ├── CS10x_FaultEventEn / CS10x_SetSendSoe / CS10x_SetSendCos
// ├── CS10x_SetYKEendFrame / CS10x_SetReadFileVSQ
// └── CS10x_SetPresetContType
// → SetProtocolItfc() ← ★ 所有回调在此注册
3.2 101 从站初始化 (差异项)
101 额外配置:
CS10x_SetAppParameters: 需要iSzOfLinkAddr+iLinkAddrCS10x_ResendGap/CS10x_ResendCnt: 重发参数CS10x_SetHeartTimeGap: 心跳间隔CS10x_SetFileAckType: 文件确认CS10x_SetInitType: 简单初始化
4. 回调注册全景 (SetProtocolItfc)
void SetProtocolItfc(stLIB60870ENTITY *pstEntity, u8 ucType) {
CS10x *pstCs10x = &pstEntity->stCs10x;
// ── 对所有类型 (主站/从站) ──
CS10x_TimeRWHandler(pstCs10x, GetTimeItfs, SetTimeItfs);
CS10x_WR_ResetHandler(pstCs10x, Cs10xReadFileResetCOI, Cs10xWriteFileResetCOI);
CS10x_SetYkInforHandler(pstCs10x, SetYkInfor);
// ── 仅从站 ──
if (PRTCL_104_S == ucType || PRTCL_101_S == ucType) {
// 遥测
CS10x_S_GetYcByGroupHandler(pstCs10x, GetYcCountByGroup, GetYcValueByGroup);
// 扰动遥测
CS10x_S_DiturbYcHandler(pstCs10x, GetDiturbYc, GetDiturbYcSendNum, UpdateDiturbYcPtrOut);
// 遥信
CS10x_S_GetYxByGroupHandler(pstCs10x, GetYxCountByGroup, GetYxStatusByGroup);
// SOE
CS10x_S_SOEHandler(pstCs10x, GetSOE, GetSOESendNum, UpdateSoePtrOut);
// 电度
CS10x_S_GetDdByGroupHandler(pstCs10x, GetDdCountByGroup, GetDdValueByGroup);
// 时标电度
CS10x_S_DiturbDduHandler(pstCs10x, GetTimeDdu, GetTimeDduSendNum, UpdateTimeDduPtrOut);
// 故障事件
CS10x_S_FaultEventHandler(pstCs10x, GetEventSendNum, GetFaultEvent, UpdateFaultEventPtrOut);
// 遥控校验
CS10x_S_YkVerifyHandler(pstCs10x, Cs10xYkVerifyItfs);
// 定值区
CS10x_S_ParamAreaHandler(pstCs10x, GbParamGetParamArea, GbParamSetParamArea);
// 参数读写
CS10x_S_IECParamHandler(pstCs10x, GbParamAddElement, GbParamRunRding, GbParamRunWting);
// 参数信息
CS10x_S_GetParamInfoHandler(pstCs10x, GbParamGetTotalNum, GbParamGetIecParam);
// 文件服务
CS10x_S_FileReadOprtHandler(pstCs10x, Fm_GetDirFile, Fm_SearchDirFileNum, Fm_ReadFile, ...);
CS10x_S_FileWriteOprtHandler(pstCs10x, Cs10xWriteItfs, Cs10xWriteFileCheckItfs, Cs10xWriteFinishItfs, ...);
// 升级
CS10x_S_UpdateProcHandler(pstCs10x, NULL);
}
}
5. 子文档索引
| 子文档 | 内容 | 对应回调 |
|---|---|---|
| 01-总召与遥测遥信 | GetYcCountByGroup / GetYcValueByGroup / GetYxCountByGroup / GetYxStatusByGroup 详细实现 | CS10x_S_GetYcByGroupHandler / CS10x_S_GetYxByGroupHandler |
| 02-SOE与扰动数据 | GetSOE / GetSOESendNum / UpdateSoePtrOut + 扰动遥测回调 | CS10x_S_SOEHandler / CS10x_S_DiturbYcHandler |
| 03-遥控与对时 | SetYkInfor / YkResultNofify / Cs10xYkVerifyItfs / GetTimeItfs / SetTimeItfs | CS10x_S_YkVerifyHandler / CS10x_TimeRWHandler |
| 04-参数定值与文件服务 | GbParamGetParamArea / GbParamAddElement / 文件读写 | CS10x_S_ParamAreaHandler / CS10x_S_IECParamHandler / 文件回调 |
| 05-故障事件与电度 | GetFaultEvent / GetDdValueByGroup | CS10x_S_FaultEventHandler / CS10x_S_GetDdByGroupHandler |