RTU/mimo/工程/DCU_HOST/README.md

206 lines
8.1 KiB
Markdown
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.

# DCU_HOST 项目 lib60870 CBB 库调用参考
> **用途**: RTU 项目开发 IEC 101/104 时的参考工程
> **源项目**: [DCU_HOST](../../../../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_260202API 完全一致。
---
## 2. 核心架构:实体池 + 线程驱动
### 2.1 实体封装 `stLIB60870ENTITY`
DCU_HOST 将 `CS10x` 封装了一层:
```c
#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()`
```c
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 发送回调
```c
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 从站初始化
```c
// 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` + `iLinkAddr`
- `CS10x_ResendGap` / `CS10x_ResendCnt`: 重发参数
- `CS10x_SetHeartTimeGap`: 心跳间隔
- `CS10x_SetFileAckType`: 文件确认
- `CS10x_SetInitType`: 简单初始化
---
## 4. 回调注册全景 (SetProtocolItfc)
```c
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-总召与遥测遥信](01-总召与遥测遥信.md) | GetYcCountByGroup / GetYcValueByGroup / GetYxCountByGroup / GetYxStatusByGroup 详细实现 | `CS10x_S_GetYcByGroupHandler` / `CS10x_S_GetYxByGroupHandler` |
| [02-SOE与扰动数据](02-SOE与扰动数据.md) | GetSOE / GetSOESendNum / UpdateSoePtrOut + 扰动遥测回调 | `CS10x_S_SOEHandler` / `CS10x_S_DiturbYcHandler` |
| [03-遥控与对时](03-遥控与对时.md) | SetYkInfor / YkResultNofify / Cs10xYkVerifyItfs / GetTimeItfs / SetTimeItfs | `CS10x_S_YkVerifyHandler` / `CS10x_TimeRWHandler` |
| [04-参数定值与文件服务](04-参数定值与文件服务.md) | GbParamGetParamArea / GbParamAddElement / 文件读写 | `CS10x_S_ParamAreaHandler` / `CS10x_S_IECParamHandler` / 文件回调 |
| [05-故障事件与电度](05-故障事件与电度.md) | GetFaultEvent / GetDdValueByGroup | `CS10x_S_FaultEventHandler` / `CS10x_S_GetDdByGroupHandler` |