253 lines
7.3 KiB
Markdown
253 lines
7.3 KiB
Markdown
# 04 - 参数定值与文件服务回调详解
|
|
|
|
> 源码: [DCU_HOST/applications/data/iec_itfc/GbParamItfs.c](../../../../../../DCU_HOST/applications/data/iec_itfc/GbParamItfs.c) (882行)
|
|
|
|
---
|
|
|
|
## 1. 回调注册
|
|
|
|
```c
|
|
// 定值区管理
|
|
CS10x_S_ParamAreaHandler(pstCs10x, GbParamGetParamArea, GbParamSetParamArea);
|
|
// 参数读写
|
|
CS10x_S_IECParamHandler(pstCs10x, GbParamAddElement, GbParamRunRding, GbParamRunWting);
|
|
// 参数信息查询
|
|
CS10x_S_GetParamInfoHandler(pstCs10x, GbParamGetTotalNum, GbParamGetIecParam);
|
|
```
|
|
|
|
---
|
|
|
|
## 2. 定值区管理
|
|
|
|
### 2.1 GbParamGetParamArea — 获取当前定值区号
|
|
|
|
```c
|
|
u16 GbParamGetParamArea(void *pParam) {
|
|
return g_stParamMappingTable.stComCommunitParam.pucCurRunParamArea;
|
|
// 返回当前运行区号 (0-255)
|
|
}
|
|
```
|
|
|
|
### 2.2 GbParamSetParamArea — 切换定值区
|
|
|
|
```c
|
|
s32 GbParamSetParamArea(u16 usAreaNum, void *pParam) {
|
|
g_stParamMappingTable.stComCommunitParam.pucCurRunParamArea = (u8)usAreaNum;
|
|
// 执行定值区切换逻辑...
|
|
return 1; // 成功
|
|
}
|
|
```
|
|
|
|
**定值区概念**:
|
|
- 电力装置通常有多个定值区 (0-3 或更多)
|
|
- 0 区通常是当前运行区
|
|
- 主站通过 C_SR_NA (TypeID=200) 切换定值区
|
|
- 通过 C_RR_NA (TypeID=201) 读取当前区号
|
|
|
|
---
|
|
|
|
## 3. 参数读写 (核心)
|
|
|
|
### 3.1 GbParamAddElement — 添加参数项到规约参数表
|
|
|
|
```c
|
|
s32 GbParamAddElement(IECPARAM_T *pstIecParam, void *pParam) {
|
|
// 1. 从参数映射表中查找对应参数
|
|
u16 usIdx = GbParamSearchIndex(pstIecParam->uiInfoAddr);
|
|
|
|
// 2. 填充 IECPARAM_T 的类型和长度
|
|
pstIecParam->ucType = g_stParamMap[usIdx].ucTagType; // TAG_TPYE_FLOAT 等
|
|
pstIecParam->ucLen = g_stParamMap[usIdx].ucDataLen; // 数据长度
|
|
|
|
// 3. 根据类型填充值
|
|
switch(pstIecParam->ucType) {
|
|
case TAG_TPYE_FLOAT:
|
|
pstIecParam->unVal.fVal = GetParamFloatValue(usIdx);
|
|
break;
|
|
case TAG_TPYE_INT:
|
|
pstIecParam->unVal.lVal = GetParamIntValue(usIdx);
|
|
break;
|
|
// ...
|
|
}
|
|
return 1;
|
|
}
|
|
```
|
|
|
|
**IECPARAM_T 结构体**:
|
|
```c
|
|
typedef struct {
|
|
unsigned char ucType; // 类型 (TAG_TPYE_FLOAT/INT/STR...)
|
|
unsigned char ucLen; // 数据长度
|
|
union {
|
|
unsigned char ucVal;
|
|
char cVal;
|
|
unsigned short usVal;
|
|
short sVal;
|
|
unsigned int ulVal;
|
|
int lVal;
|
|
float fVal;
|
|
unsigned long long ullVal;
|
|
long long llVal;
|
|
double dVal;
|
|
char caBuf[64]; // 字符串
|
|
} unVal;
|
|
unsigned int uiInfoAddr; // 信息体地址
|
|
} IECPARAM_T;
|
|
```
|
|
|
|
### 3.2 GbParamRunRding — 执行参数读取
|
|
|
|
```c
|
|
s32 GbParamRunRding(u16 usReqAddr, u16 usNum, void *pParam, u8 ucArea) {
|
|
// 主站请求读取 usReqAddr 开始的 usNum 个参数
|
|
|
|
for(u16 i = 0; i < usNum; i++) {
|
|
u16 usIdx = GbParamSearchIndex(usReqAddr + i);
|
|
if(usIdx == 0xFFFF) continue; // 未找到
|
|
|
|
IECPARAM_T stParam;
|
|
stParam.uiInfoAddr = usReqAddr + i;
|
|
GbParamFillValue(&stParam, usIdx, ucArea); // 从指定定值区填充值
|
|
GbParamAddToResponse(&stParam); // 加入响应缓存
|
|
}
|
|
return usNum;
|
|
}
|
|
```
|
|
|
|
### 3.3 GbParamRunWting — 执行参数写入
|
|
|
|
参数写入有**预置 → 固化**两步流程 (南网规约) 或**直接写入** (标准规约):
|
|
|
|
```c
|
|
s32 GbParamRunWting(IECPARAM_T *pstParam, u8 ucType, void *pParam) {
|
|
// ucType: WRITE_PARAM_YZ (预置) / WRITE_PARAM_GH (固化)
|
|
|
|
u16 usIdx = GbParamSearchIndex(pstParam->uiInfoAddr);
|
|
|
|
if(ucType == WRITE_PARAM_YZ) {
|
|
// 预置: 暂存到编辑区,不立即生效
|
|
GbParamPresetValue(usIdx, &pstParam->unVal);
|
|
return 1;
|
|
} else if(ucType == WRITE_PARAM_GH) {
|
|
// 固化: 将编辑区值写入运行区
|
|
GbParamSolidifyValue(usIdx);
|
|
// ★ 触发参数生效逻辑 (如重启保护等)
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
```
|
|
|
|
### 3.4 GbParamGetTotalNum / GbParamGetIecParam — 参数信息查询
|
|
|
|
```c
|
|
s32 GbParamGetTotalNum(void *pParam) {
|
|
return g_stParamMapCount; // 返回参数表总数
|
|
}
|
|
|
|
s32 GbParamGetIecParam(IECPARAM_T *pstParam, u16 usIdx, void *pParam) {
|
|
pstParam->uiInfoAddr = g_stParamMap[usIdx].uiAddr;
|
|
pstParam->ucType = g_stParamMap[usIdx].ucTagType;
|
|
pstParam->ucLen = g_stParamMap[usIdx].ucDataLen;
|
|
return 1;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. 参数读写时序 (南网规约)
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Master as 主站
|
|
participant CBB as lib60870
|
|
participant App as 应用层(GbParamItfs)
|
|
|
|
Note over Master,CBB: === 读参数 ===
|
|
Master->>CBB: C_RS_NA_NANWANG (TypeID=108, COT=5)
|
|
CBB->>App: GbParamRunRding(起始地址, 数量)
|
|
App-->>CBB: 返回参数值列表
|
|
CBB->>Master: 参数数据帧
|
|
|
|
Note over Master,CBB: === 写参数 (预置) ===
|
|
Master->>CBB: C_SP_NA (TypeID=55, 预置, COT=6)
|
|
CBB->>App: GbParamRunWting(param, WRITE_PARAM_YZ)
|
|
App-->>CBB: 预置成功
|
|
CBB->>Master: 预置确认 (COT=7)
|
|
|
|
Note over Master,CBB: === 写参数 (固化) ===
|
|
Master->>CBB: C_SP_NA (TypeID=55, 固化, COT=6)
|
|
CBB->>App: GbParamRunWting(param, WRITE_PARAM_GH)
|
|
App-->>CBB: 固化成功
|
|
CBB->>Master: 固化确认 (COT=7)
|
|
```
|
|
|
|
**标准规约** (TypeID=202/203) 流程类似,但无需预置/固化两步,直接读/写即可。
|
|
|
|
---
|
|
|
|
## 5. 文件服务回调
|
|
|
|
```c
|
|
CS10x_S_FileReadOprtHandler(pstCs10x, Fm_GetDirFile, Fm_SearchDirFileNum, Fm_ReadFile, &pstEntity->stReadParam);
|
|
CS10x_S_FileWriteOprtHandler(pstCs10x, Cs10xWriteItfs, Cs10xWriteFileCheckItfs, Cs10xWriteFinishItfs, &pstEntity->stWriteParam);
|
|
CS10x_S_UpdateProcHandler(pstCs10x, NULL); // 升级 (当前未实现)
|
|
```
|
|
|
|
文件服务使用 TypeID=210 (F_FR_NA),支持:
|
|
- **目录召唤**: 返回文件列表
|
|
- **读文件**: 分段传输
|
|
- **写文件**: 用于参数配置下发
|
|
- **软件升级**: TypeID=211 (F_SR_NA)
|
|
|
|
### RTU 适配建议
|
|
|
|
文件服务在 RTU 场景中可能不需要 (通过 Web/WebSocket 管理配置更常见),可以暂时注册 `NULL`:
|
|
|
|
```c
|
|
CS10x_S_FileReadOprtHandler(pstCs10x, NULL, NULL, NULL, NULL);
|
|
CS10x_S_FileWriteOprtHandler(pstCs10x, NULL, NULL, NULL, NULL);
|
|
CS10x_S_UpdateProcHandler(pstCs10x, NULL);
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 参数类型映射表 (TAG_TYPE)
|
|
|
|
CBB 库内部使用的参数类型编码:
|
|
|
|
| 宏 | 值 | C 类型 |
|
|
|----|-----|--------|
|
|
| `TAG_TPYE_BOOL` | 1 | `bool` |
|
|
| `TAG_TPYE_INT` | 2 | `int` |
|
|
| `TAG_TPYE_STR` | 4 | `char[]` |
|
|
| `TAG_TPYE_UTINY` | 32 | `uint8_t` |
|
|
| `TAG_TPYE_SHORT` | 33 | `int16_t` |
|
|
| `TAG_TPYE_UINT` | 35 | `uint32_t` |
|
|
| `TAG_TPYE_LONG` | 36 | `int32_t` |
|
|
| `TAG_TPYE_ULONG` | 37 | `uint32_t` |
|
|
| `TAG_TPYE_FLOAT` | 38 | `float` |
|
|
| `TAG_TPYE_DOUBLE` | 39 | `double` |
|
|
| `TAG_TPYE_TINY` | 43 | `int8_t` |
|
|
| `TAG_TPYE_USHORT` | 45 | `uint16_t` |
|
|
|
|
---
|
|
|
|
## 7. 加密参数配置
|
|
|
|
```c
|
|
void SetProtocolEncryParam(CS10x *pstCs10x, void *pvArg) {
|
|
// 加密使能检查 (仅 4G 串口和维护口)
|
|
if((isSlave) && (isEncryptInterface)) {
|
|
CS10x_EncryptHandler(pstCs10x, Encryp_Encode); // 加密回调
|
|
CS10x_Md5ResultHandler(pstCs10x, Saft_Update_Md5); // MD5 校验
|
|
Saft_Config_Param(1, ...); // 加密参数配置
|
|
} else {
|
|
CS10x_EncryptHandler(pstCs10x, NULL);
|
|
CS10x_Md5ResultHandler(pstCs10x, NULL);
|
|
}
|
|
}
|
|
```
|
|
|
|
**RTU 注意**: 如果不需要加密,注册 NULL 即可。
|