feat(lib60870): 导入 IEC 60870-5-101/103/104 协议栈
- 从原工程 src/protocol/lib60870 完整复制(科大智能,2022) - 9 个头文件 + 8 个源文件,~16K 行 - 新增 cbb_compat.h: u8/u16/u32/f32/BOOL 类型别名 - 新增 myIec60870.h: 聚合入口 - makefile: -include cbb_compat.h 注入类型定义 - makefile: -Wno-implicit-function-declaration (gb103.c 已知问题) - copy_headers.sh: 注册 myIec60870.h
This commit is contained in:
parent
802e3c3f31
commit
a0b85f4bba
|
|
@ -69,5 +69,6 @@ copy_module "libcomm" "myComm.h"
|
|||
# 协议模块(protocol/)
|
||||
# ================================================================
|
||||
copy_proto_module "libmodbus" "myModbus.h"
|
||||
copy_proto_module "lib60870" "myIec60870.h"
|
||||
|
||||
echo "=== done ==="
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
include ./../../../linux.mk
|
||||
L := $(notdir $(realpath $(CURDIR)/..))
|
||||
M := lib60870
|
||||
O := $(LIB_REL)/$(M).a
|
||||
S := $(SRC_ROOT_DIR)/$(L)/lib60870/src
|
||||
I := -I$(SRC_ROOT_DIR)/$(L)/lib60870/inc
|
||||
B := $(CURDIR)/$(M)/obj
|
||||
SRCS := $(wildcard $(S)/*.c)
|
||||
OBJS := $(patsubst $(S)/%.c, $(B)/%.o, $(SRCS))
|
||||
F := $(C_FLAGS) $(I)
|
||||
F += -include cbb_compat.h
|
||||
F += -Wno-implicit-function-declaration
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@mkdir -p $(ROOT_DIR)/release/inc
|
||||
@$(MAKE) $(O)
|
||||
|
||||
$(O): $(OBJS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(AR) rcs $@ $^
|
||||
@echo "[$(M)] built"
|
||||
|
||||
$(B)/%.o: $(S)/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(F) -c $< -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(B) $(O)
|
||||
|
||||
.PHONY: rebuild
|
||||
rebuild: clean all
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS := ./libmodbus
|
||||
SUBDIRS := ./libmodbus ./lib60870
|
||||
define make_subdir
|
||||
for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done
|
||||
endef
|
||||
|
|
|
|||
|
|
@ -0,0 +1,283 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : ASDU.h
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年04月07日
|
||||
最近修改 :
|
||||
功能描述 : 101及104规约的公共部分ASUD域相关数据处理
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年04月07日
|
||||
修改内容 : 创建文件
|
||||
*******************************************************************************/
|
||||
#ifndef __ASDU_H
|
||||
#define __ASDU_H
|
||||
/**************************************文件包含*******************************/
|
||||
#include <stdio.h>
|
||||
#include "lib60870_common.h"
|
||||
#include "lib60870_public.h"
|
||||
#include "lib60870_process.h"
|
||||
#include "gb101.h"
|
||||
/**************************************宏定义*********************************/
|
||||
|
||||
#define MAX_FLOATYC_CNT 48
|
||||
#define INTYC_MAX_CNT 80
|
||||
#define MAX_Yx_CNT 127
|
||||
#define MAX_Dd_CNT 48
|
||||
#define MAX_Param_CNT 4
|
||||
#define MAX_COS_CNT 60
|
||||
/************************************数据结构定义*****************************/
|
||||
|
||||
typedef union
|
||||
{
|
||||
/*带品质描述词的单点信息*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucSPI: 1; /*0=开 1=合*/
|
||||
unsigned char ucRES: 3; /*备用*/
|
||||
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
|
||||
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
|
||||
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
|
||||
unsigned char ucIV : 1; /*0=有效 1=无效*/
|
||||
} SIQ;
|
||||
|
||||
/*带品质描述词的双点信息*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucDPI: 2; /*0=不确定或中间状态 1=确定状态开 2=确定状态合 3=不确定*/
|
||||
unsigned char ucRES: 2; /*备用*/
|
||||
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
|
||||
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
|
||||
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
|
||||
unsigned char ucIV : 1; /*0=有效 1=无效*/
|
||||
} DIQ;
|
||||
|
||||
/*品质描述词*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucOV : 1; /*0=未溢出 1=溢出*/
|
||||
unsigned char ucRES: 3; /*备用*/
|
||||
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
|
||||
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
|
||||
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
|
||||
unsigned char ucIV : 1; /*0=有效 1=无效*/
|
||||
} QDS;
|
||||
|
||||
/*继电保护设备事件的品质描述词*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucRES: 3; /*备用*/
|
||||
unsigned char ucEI : 1; /*0=动作时间有效 1=动作时间无效*/
|
||||
unsigned char ucBL : 1; /*0=未被锁定 1=锁定*/
|
||||
unsigned char ucSB : 1; /*0=未被取代 1=取代*/
|
||||
unsigned char ucNT : 1; /*0=当前值 1=非当前值*/
|
||||
unsigned char ucIV : 1; /*0=有效 1=无效*/
|
||||
} QDP;
|
||||
|
||||
/*带瞬变状态指示的值*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucI7 : 7; /*瞬变状态*/
|
||||
unsigned char ucBS1: 1; /*0=动作时间有效 1=动作时间无效*/
|
||||
} VTI;
|
||||
|
||||
|
||||
/*单命令*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucSCS: 1; /*0=开 1=合*/
|
||||
unsigned char ucRES: 1; /*备用*/
|
||||
unsigned char ucQU : 5; /*0=无另外定义 1=短脉冲持续时间 2=长脉冲持续时间 3=持续输出*/
|
||||
unsigned char ucSE : 1; /*0=执行 1=选择*/
|
||||
} SCO;
|
||||
|
||||
/*双命令*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucDCS: 2; /*0=不允许 1=开 2=合 3=不允许*/
|
||||
unsigned char ucQU : 5; /*0=无另外定义 1=短脉冲持续时间 2=长脉冲持续时间 3=持续输出*/
|
||||
unsigned char ucSE : 1; /*0=执行 1=选择*/
|
||||
} DCO;
|
||||
|
||||
/*步调节命令*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucRCS: 2; /*0=不允许 1=降一步 2=升一步 3=不允许*/
|
||||
unsigned char ucQU : 5; /*0=无另外定义 1=短脉冲持续时间 2=长脉冲持续时间 3=持续输出*/
|
||||
unsigned char ucSE : 1; /*0=执行 1=选择*/
|
||||
} RCO;
|
||||
|
||||
/*初始化原因*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucUI7: 7; /*0=当地电源合上 1=当地手动复位 2=远方复位*/
|
||||
unsigned char ucBS1: 1; /*0=未改变当地参数初始化 1=改变当地参数初始化*/
|
||||
} COI;
|
||||
|
||||
/*设定命令限定词*/
|
||||
struct
|
||||
{
|
||||
unsigned char ucQL: 7; /*0=缺省*/
|
||||
unsigned char ucSE: 1; /*0=执行 1=选择*/
|
||||
} QOS;
|
||||
|
||||
unsigned char ucBits;
|
||||
} ASDU_CMD_T;
|
||||
|
||||
/**************************************数据声明******************************/
|
||||
|
||||
|
||||
/**************************************内部函数声明***************************/
|
||||
unsigned char DecodeASDUCheck(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_M_EI_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_IC_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_CI_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_CS_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_RP_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_TS_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_F_FR_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_SR_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_RR_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_RS_NA(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_C_WS_NA(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_M_SPDP_NA(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_M_ME_NANBNC(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_M_IT_NB(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_M_IT_TC(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_C_SCDC_NA(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_M_FT_NA(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_M_DPSP_TB(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_F_SR_NA(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_C_CD_NA(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_RS_NA_NANWANG(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_C_WS_NA_YZ(CS10x *pstSelf);
|
||||
unsigned char DecodeCheck_C_WS_NA_GH(CS10x *pstSelf, unsigned char *pucPayload);
|
||||
unsigned char DecodeCheck_C_SP_NA(CS10x *pstSelf);
|
||||
void Do_SetTime(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_Summon(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_DdSummon(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_Reset_Process(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_DataTest(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_InitEnd(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_Yx(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_Yc(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_DdNoTime(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_DdWithTime(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_YKPro(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_SOE(CS10x *pstSelf);
|
||||
void Do_FaultEvent(CS10x *pstSelf);
|
||||
void Do_FilePro_Slave(CS10x *pstSelf, unsigned char ucType, unsigned char *pucBuf, unsigned short usFileDateLen);
|
||||
void Do_FilePro_Master(CS10x *pstSelf, unsigned char ucType, unsigned char *pucBuf);
|
||||
void Do_FilePro(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_Anomaly(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_ChgConst(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_ReadConst(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_ParamPreread(CS10x *pstSelf, unsigned short usReason);
|
||||
void Do_ParamPreset(CS10x *pstSelf, unsigned short usReason);
|
||||
|
||||
unsigned short CS10x_Send_Yx(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_SummonYx(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_COS(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
unsigned short CS10x_Send_Yc(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_SummonYc(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_ChangeYc(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
unsigned short CS10x_Send_SOE(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_FaultEvent(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
unsigned short CS10x_Send_DdData(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_SummonDd_Data(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_TimeDd_Data(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
unsigned short CS10x_Send_SynTime(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_Summon(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_DdSummon(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_ResetProcess(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_DataTest(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_InitEnd(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_FilePro(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_ChgConst(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_ReadConst(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_ParamPreread(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_ParamPreset(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_Yk(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_DdSummon_Data(CS10x *pstSelf, unsigned int uiParam);
|
||||
unsigned short CS10x_Send_Anomaly(CS10x *pstSelf, unsigned int param);
|
||||
unsigned short CS10x_Send_Update(CS10x *pstSelf, unsigned int uiParam);
|
||||
void Do_Update(CS10x *pstSelf, unsigned short usReason);
|
||||
unsigned short GetPayloadOffset(CS10x *pstSelf);
|
||||
void CheckFileDiff(CS10x *pstSelf);
|
||||
unsigned short DecodeAsduMember(CS10x *pstSelf, unsigned char * pucAsdu, unsigned short usAsduSz);
|
||||
unsigned short GetTaskTItype(CS10x *pstSelf, unsigned short usDataType);
|
||||
/************************************外部接口函数声明*************************/
|
||||
extern unsigned short GB10x_EncodeAsdu(CS10xHandle_t pstSelf, unsigned char * pucBuf);
|
||||
extern void DecodeAsduInfoObj(CS10x *pstSelf);
|
||||
extern unsigned short EncodeAsdu(CS10x *pstSelf);
|
||||
extern void DoAckFrame(CS10x *pstSelf);
|
||||
/********************************文件传输接口**************************************/
|
||||
void Revc_ReadFS_CallDir_S(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //召唤目录
|
||||
|
||||
void Revc_ReadFS_AckCallDir_M(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //召唤目录确认
|
||||
|
||||
void Revc_ReadFS_SelectFile_S(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件激活
|
||||
|
||||
void Revc_ReadFS_AckSelectFile_M(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件激活确认
|
||||
|
||||
void Revc_ReadFS_CallFileSeg_M(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件数据
|
||||
|
||||
void Revc_ReadFS_AckFileSeg_S(CS10x *pstSelf, unsigned char *pucBuf, tFILEDIR_RD_SET *pstRdSet); //读文件数据响应
|
||||
|
||||
void Recv_WriteFS_SelectFile_S(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
void Recv_WriteFS_AckSelectFile_M(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
void Recv_WriteFS_DownFileSeg_S(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet, unsigned short usFileDateLen);
|
||||
|
||||
void Recv_WriteFS_AckDownFileSeg_M(CS10x *pstSelf, unsigned char *pucBuf, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
unsigned short Send_ReadFS_CallDir_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
|
||||
|
||||
unsigned short Send_ReadFS_AckCallDir_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
|
||||
|
||||
unsigned short Send_ReadFS_SelectFile_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
|
||||
|
||||
unsigned short Send_ReadFS_AckSelectFile_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
|
||||
|
||||
unsigned short Send_ReadFS_CallFileSeg_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
|
||||
|
||||
unsigned short Send_ReadFS_AckFileSeg_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILEDIR_RD_SET *pstRdSet);
|
||||
|
||||
unsigned short Send_WriteFS_SelectFile_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
unsigned short Send_WriteFS_AckSelectFile_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
unsigned short Send_WriteFS_DownFileSeg_M(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
unsigned short Send_WriteFS_AckDownFileSeg_S(CS10x *pstSelf, unsigned short usFileProType, ASDU_Element *pstAsdus, tFILE_WD_SET *pstWdSet);
|
||||
|
||||
void Do_ObtainDelay(CS10x *pstSelf, unsigned short usReason);
|
||||
|
||||
unsigned short CS10x_Send_ObtainDelay(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
void Do_ParamRead_NanWang(CS10x *pstSelf, unsigned short usReason);
|
||||
|
||||
unsigned short CS10x_Send_ParamRead_NanWang(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
unsigned short CS10x_Send_ParamRdResponse_NanWang(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
unsigned short CS10x_Send_ParamSolidify_NanWang(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
void Do_ParamPreset_NanWang(CS10x *pstSelf, unsigned short usReason);
|
||||
|
||||
void DoParamSolidify_NanWang(CS10x *pstSelf, unsigned short usReason);
|
||||
|
||||
unsigned short CS10x_Send_ParamPreset_NanWang(CS10x *pstSelf, unsigned int uiParam);
|
||||
|
||||
void Do_ParamWrite_Nanwang(CS10x *pstSelf, unsigned short usReason);
|
||||
|
||||
unsigned short CS10x_Send_ParamWrite_Nanwang(CS10x *pstSelf, unsigned int uiParam);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* cbb_compat.h — CBB 库兼容类型别名
|
||||
*
|
||||
* CBB 库(lib60870)使用了 u8/u16/u32/s16/s32/f32/BOOL/TRUE/FALSE
|
||||
* 等自定义类型/宏,这些类型在原库中依赖 ostype.h 外部定义。
|
||||
* 此处通过 gcc -include 注入,不修改 CBB 库任何源文件。
|
||||
*/
|
||||
#ifndef _CBB_COMPAT_H_
|
||||
#define _CBB_COMPAT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef float f32;
|
||||
typedef bool BOOL;
|
||||
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
|
||||
#endif /* _CBB_COMPAT_H_ */
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : gb101.h
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年03月23日
|
||||
最近修改 :
|
||||
功能描述 : gb101.c的头文件
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年03月23日
|
||||
修改内容 : 创建文件
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __GB101_H
|
||||
#define __GB101_H
|
||||
/**************************************文件包含*******************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib60870_common.h"
|
||||
#include "lib60870_public.h"
|
||||
#include "lib60870_process.h"
|
||||
#include "Asdu.h"
|
||||
/**************************************宏定义*********************************/
|
||||
#define START_CODE_101_LONG 0x68 //101规约长帧头
|
||||
#define START_CODE_101_SHORT 0x10 //101规约短帧头
|
||||
#define TAIL_CODE_101 0x16 //101规约报文尾
|
||||
#define HEAD_LEN_101 7 //101规约ASDU前的字节长度 包含控制域及2字节地址
|
||||
#define SHORT_LEN_S 5 //公共地址单字节时101短帧长度
|
||||
#define SHORT_LEN 6 //公共地址双字节时101短帧长度
|
||||
#define HEAD_TAIL_LEN 6 //101规约长帧头尾总长度
|
||||
#define HEAD_LEN 4 //101规约长帧头长度
|
||||
|
||||
|
||||
#define RESET_LINK 0 //复位链路
|
||||
#define TEST_LINK 2 //测试帧
|
||||
#define ACK_LINK 0 //确认帧
|
||||
#define DATA_SEND 3 //长帧的功能码
|
||||
#define NONE_DATA 4 //无回答数据
|
||||
#define REQUEST_LINK 9 //请求链路状态
|
||||
#define LINKSTATUS 11 //请求链路状态回复帧
|
||||
#define FCVOFF 0 //FCB位无效
|
||||
#define FCVON 1 //FCB位有效
|
||||
#define PRM_MASTER 1 //启动站 这里与主站 终端有区别
|
||||
#define PRM_SLAVE 0 //从动站 这里与主站 终端有区别
|
||||
|
||||
#define WAITTIME_101 10000 //短帧等待最大超时时间
|
||||
#define TIMEOUT 3000 //101短帧超时重发时间
|
||||
#define RESENDCNT_MAX 5 //重发次数
|
||||
#define REINITTIME 300000 //5min重发初始化
|
||||
/************************************数据结构定义*****************************/
|
||||
/**
|
||||
* @brief 平衡101规约控制域定义
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct //上行 低位在上
|
||||
{
|
||||
unsigned char FC : 4;
|
||||
unsigned char DFC : 1;
|
||||
unsigned char RES : 1;
|
||||
unsigned char PRM : 1;
|
||||
unsigned char DIR : 1;
|
||||
} bits_up;
|
||||
|
||||
struct //下行
|
||||
{
|
||||
unsigned char FC : 4;
|
||||
unsigned char FCV : 1;
|
||||
unsigned char FCB : 1;
|
||||
unsigned char PRM : 1;
|
||||
unsigned char DIR : 1;
|
||||
} bits_down;
|
||||
|
||||
unsigned char control;
|
||||
} CONTROL101;
|
||||
|
||||
/**************************************数据声明******************************/
|
||||
|
||||
/**************************************内部函数声明***************************/
|
||||
char GB101_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen);
|
||||
void GB101_LongFrame(CS10xHandle_t pstSelf, unsigned char *pucFrameStart);
|
||||
void GB101_ShortFrame(CS10xHandle_t pstSelf, unsigned char *pucFrameStart);
|
||||
char GB101_EncodeFrame(CS10xHandle_t pstSelf);
|
||||
char GB101_EncodeOther(CS10xHandle_t pstSelf);
|
||||
void GB101_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
void GB101_Resend(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
void GB101_Link_Init(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
unsigned short GB101_EncodeFrameHead(CS10xHandle_t pstSelf, VIec101Frame * pstFrame);
|
||||
void GB101_EncodeFrameTail(CS10xHandle_t pstSelf, VIec101Frame *pstFrame);
|
||||
void GB101_Summon(CS10xHandle_t pstSelf);
|
||||
void GB101_TimeSyn(CS10xHandle_t pstSelf);
|
||||
void GB101_Heart(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
void GB101_SendAck(CS10xHandle_t pstSelf);
|
||||
void GB101_SendLinkStatus(CS10xHandle_t pstSelf);
|
||||
void GB101_SendResetLink(CS10xHandle_t pstSelf);
|
||||
void GB101_SendRequestLink(CS10xHandle_t pstSelf);
|
||||
void GB101_SendTestLink(CS10xHandle_t pstSelf);
|
||||
unsigned char GB101_Control(CS10xHandle_t pstSelf, unsigned char ucPRM, unsigned char ucFCV, unsigned char ucFC);
|
||||
/************************************外部接口函数声明*************************/
|
||||
|
||||
extern void CS10x_101Init(CS10xHandle_t pstSelf, CS10x_SendCb cb, void *arg, CS10x_Type enType);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* IEC103Type.h
|
||||
*/
|
||||
|
||||
#ifndef IEC103TYPE_H_
|
||||
#define IEC103TYPE_H_
|
||||
|
||||
//#include "ostype.h"
|
||||
#include "lib60870_common.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CS103_TYPE_S = 0, /*CS103 从*/
|
||||
CS103_TYPE_M, /*CS103 主*/
|
||||
}CS103_Type;
|
||||
|
||||
enum ASDU_TYPE
|
||||
{
|
||||
ASDU_1 = 0x01,
|
||||
ASDU_2 = 0x02,
|
||||
ASDU_10 = 0x0A,
|
||||
ASDU_40 = 0x28,
|
||||
ASDU_41 = 0x29,
|
||||
ASDU_42 = 0x2A,
|
||||
ASDU_43 = 0x2B,
|
||||
ASDU_44 = 0x2C,
|
||||
ASDU_45 = 0x2D,
|
||||
ASDU_46 = 0x2E,
|
||||
ASDU_50 = 0x32,
|
||||
};
|
||||
|
||||
enum CMD_SEND
|
||||
{
|
||||
CMD_RESET_CON = 1,
|
||||
CMD_RESET_NUM,
|
||||
CMD_RESET_TIMESTAMP, //对时
|
||||
CMD_RESET_EVENT, //复归命令
|
||||
CMD_SETTING_DOWNLOAD, //定值下载
|
||||
CMD_SETTING_MODIFY, //定值修改
|
||||
CMD_YK, //遥控功能
|
||||
CMD_GET_ALL,
|
||||
CMD_GET_DATA_LV1, //获取一级数据
|
||||
CMD_GET_DATA_LV2, //获取二级数据
|
||||
CMD_GET_SINGLE_SETTING_VALUE, //获取单个条目值
|
||||
CMD_GENERAL_READ_YX_GROUP_VALUE,
|
||||
CMD_GENERAL_READ_YC_GROUP_VALUE,
|
||||
};
|
||||
|
||||
//标志位在报文中的位置
|
||||
#define CODE_POSI 4 //控制域
|
||||
#define TYP_POSI 6 //类型标识
|
||||
#define VSQ_POSI 7 //可变结构限定词
|
||||
#define COT_POSI 8 //传送原因
|
||||
#define ADDR_POSI 9 //设备地址
|
||||
#define FUN_POSI 10 //功能类型
|
||||
#define INF_POSI 11 //信息序号
|
||||
#define RII_POSI 12 //返回信息标识符
|
||||
#define DPI_POSI 12 //双点信息
|
||||
#define RET_POSI 13 //相对时间 表示装置启动到该元件动作的相对时间,毫秒
|
||||
#define FAN_POSI 15 //故障序号
|
||||
#define ASDU_1_TIMESTAMP 13 //ASDU1中四字节时间起始位置
|
||||
#define ASDU_2_TIMESTAMP 17 //ASDU2中四字节时间起始位置
|
||||
#define GROUP_POSI 14 //组号
|
||||
#define TNTRY_POSI 15 //条目号
|
||||
#define KOD_POSI 16 //描述的类别
|
||||
#define GDD_POSI 17 //通用分类数据描述
|
||||
#define GID_POSI 20 //通用分类标识数据
|
||||
#define NGD_POSI 13 //通用分类数据集数目
|
||||
|
||||
|
||||
|
||||
#define START_10H 0x10 //固定长度报文启动字符
|
||||
#define START_68H 0x68 //可变长度报文启动字符
|
||||
#define END_16H 0x16 //结束字符
|
||||
#define FCB_1 0x20 //帧计数位
|
||||
#define FCV_1 0x10 //帧计数有效位
|
||||
#define ACD_1 0x20 //有一级数据上送
|
||||
#define PRA_1 0x40 //启动报文位 主到从
|
||||
#define KOD_1 0x01 //描述类别 1为实际值
|
||||
|
||||
//功能码定义
|
||||
#define FNA_S2C_RESET_CON 0 //复位通信功能码
|
||||
#define FNA_S2C_RESET_NUM 7 //复位帧计数位功能码
|
||||
#define FNA_S2C_POSTDATA_3 3 //传送数据(发送/确认帧)
|
||||
#define FNA_S2C_POSTDATA_4 4 //传送数据(发送/无回答帧)
|
||||
#define FNA_S2C_GETDATA_LV1 10 //召唤一级数据功能码
|
||||
#define FNA_S2C_GETDATA_LV2 11 //召唤二级数据功能码
|
||||
|
||||
//ASDU号定义
|
||||
#define ASDU6_TIMESTAMP 6 // 对时
|
||||
#define ASDU7_GETALL 7 // 总召唤,遥信
|
||||
#define ASDU20_RESET 20 // 复归
|
||||
#define ASDU21_GETGROUP 21 // 总召唤,要测
|
||||
#define ASDU10_SETTING 10 // 定值
|
||||
#define ASDU20_RESET 20 // 复归
|
||||
#define ASDU21_GETGROUP 21 // 总召唤,遥测
|
||||
#define ASDU60 60 // 遥控
|
||||
|
||||
//COT传送原因定义
|
||||
//控制方向
|
||||
#define COT_S2C_TIMESTAMP 8 //时间同步
|
||||
#define COT_S2C_GETALL_START 9 //总查询(总召唤)的启动
|
||||
#define COT_S2C_REMOTE 0x0c //远方操作
|
||||
#define COT_S2C_COMMON_ORDER 0x14 //一般命令
|
||||
#define COT_S2C_GENERAL_WRITE 0x28 //通用分类写命令
|
||||
#define COT_S2C_GENERAL_READ 0x2A //通用分类读命令
|
||||
|
||||
//FUN定义
|
||||
#define FUN_GLB 0xFF //全局功能类型
|
||||
#define FUN_GEN 0xFE //通用分类服务功能类型
|
||||
|
||||
|
||||
//INF定义
|
||||
#define INF_RESET_ORDER 0x13 //复归命令,所有装置相同
|
||||
#define INF_READ_GROUP 0xF1 //读一个组的全部条目的值或者属性
|
||||
#define INF_READ_EBTRY 0xF4 //读一个条目的值或者属性
|
||||
#define INF_CONFIRM_WRITE 0xF9 //带确认的写条目
|
||||
#define INF_EXEC_WRITE 0xFA //带执行的写条目
|
||||
|
||||
#define MAX_SIZE 1024
|
||||
|
||||
|
||||
typedef struct {
|
||||
u8 fcb; // 桢记数位
|
||||
u8 fcv; // 桢记数有效位
|
||||
} IEC103CodeS2C;
|
||||
|
||||
typedef union
|
||||
{
|
||||
u32 uValue;
|
||||
f32 fValue;
|
||||
u8 buf[4];
|
||||
}UnionConvert4Byte;
|
||||
|
||||
typedef union
|
||||
{
|
||||
s16 value;
|
||||
u16 uValue;
|
||||
u8 buf[2];
|
||||
}UnionConvert2Byte;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//通用分类标识序号GIN
|
||||
u8 groupNo; //组号
|
||||
u8 entryNo; //条目号
|
||||
|
||||
//描述的类别KOD
|
||||
u8 kod; //1为实际值
|
||||
|
||||
//通用分类数据描述GDD
|
||||
u8 datatype; //数据类型
|
||||
u8 datasize; //数据宽度
|
||||
u8 number:7, //数目
|
||||
cont:1; //后续状态位
|
||||
}stDataUnit; //通用分类数据单元
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 msec; //毫秒
|
||||
u8 min:6, //分钟
|
||||
res1:1, //备用
|
||||
iv:1; //IV=0为有效 =1为无效
|
||||
u8 hour:7, //小时
|
||||
su:1; //su夏时制标志
|
||||
u8 day:5, //日
|
||||
dayofweek:3; //未采用
|
||||
u8 month:4, //月
|
||||
res2:4; //备用
|
||||
u8 year:7, //年
|
||||
res3:1; //备用
|
||||
}stTime7Byte;
|
||||
|
||||
|
||||
|
||||
// 带品质描述词的被测量(MEA)
|
||||
typedef struct {
|
||||
union {
|
||||
s16 mval:13, // 带符号规一化定点数,最高位符合位,数据位占12位
|
||||
res:1, // 备用位:未用(常为0)
|
||||
er:1, // 差错位:0-有效,1-无效
|
||||
ov:1; // 溢出位:0-无溢出,1-溢出
|
||||
|
||||
s16 wVal;
|
||||
}mea;
|
||||
}MEA;
|
||||
|
||||
|
||||
/**
|
||||
* \brief GetLayerSt 获取链路层状态,检测是否满足发送条件
|
||||
* \param
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
typedef s32 (*CS103_SendCb) (u8 *buf, u16 usLen, void *arg);
|
||||
|
||||
/**
|
||||
* \brief SetValue 规约更新应用数据
|
||||
* \param
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
typedef s32 (*CS103_SetValue) (u8 ucFun, u8 ucInf, f32 fVal, void *pParam);
|
||||
|
||||
/**
|
||||
* \brief SetStatus 规约更新应用状态
|
||||
* \param
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
typedef s32 (*CS103_SetStatus) (u8 ucFun, u8 ucInf, u8 ucSt, void *pParam);
|
||||
|
||||
/**
|
||||
* \brief AddSOE 规约添加SOE信息
|
||||
* \param
|
||||
*
|
||||
* \return
|
||||
*/
|
||||
typedef s32 (*CS103_AddSOE) (u8 ucFun, u8 ucInf, u8 ucSt, stTime7Byte *pTime, void *pParam);
|
||||
|
||||
|
||||
typedef struct {
|
||||
void *pUsrData; /*用户自定义数据接口*/
|
||||
|
||||
u16 usFirstNum;
|
||||
|
||||
u16 usTaskID;
|
||||
VFLAGS stTaskFlags;
|
||||
|
||||
IEC103CodeS2C stIEC103CodeS2C; /*103控制域主到从*/
|
||||
u8 ucAddr; /*从站地址*/
|
||||
u8 ucReSend_Num; /*重发次数*/
|
||||
u16 usReSend_Gap; /*重发间隔*/
|
||||
u32 ulSummon_Gap; /*总召间隔*/ //参数关联
|
||||
u32 ulSyn_Gap; /*同步间隔*/ //参数关联
|
||||
// u32 ulHeart_Gap; /*心跳间隔*/ //参数关联
|
||||
u32 ulSend_Gap; /*数据发送间隔参数*/
|
||||
|
||||
|
||||
// u32 ulHeart_Tcn; /* 心跳累计时间计数 */
|
||||
u32 ulSummon_Tcn; /* 定时总招时间计数 */
|
||||
u32 ulTimeSyn_Tcn; /* 定时对时时间计数 */
|
||||
|
||||
u8 usResend_Ncn; /* 重发次数计数 */
|
||||
u16 usResend_Tcn; /* 重发间隔时间计数 */
|
||||
|
||||
BOOL bIsResetConEnd; /*复位通信*/
|
||||
|
||||
BOOL bIsResetNumEnd; //复位帧计数位
|
||||
BOOL bIsGetAllEnd; //总召唤
|
||||
|
||||
u8 ucIDCount;
|
||||
|
||||
u8 ucYcGroupNum;
|
||||
u8 ucYxGroupNum;
|
||||
|
||||
u8 ucGroupNo;
|
||||
u8 ucEntryNo;
|
||||
|
||||
u8 ucYkFun;
|
||||
u8 ucYkInf;
|
||||
u8 ucYkSE;
|
||||
u8 ucYkACT;
|
||||
u8 ucYkDCS;
|
||||
u8 ucYkQU;
|
||||
|
||||
CS10x_Send_Cb SendCb; /*数据发送接口*/
|
||||
CS10x_GetTime GetTime; /*获取事件*/
|
||||
/*对外提供数据*/
|
||||
CS103_SetValue SetValue; /*规约更新应用数据*/
|
||||
CS103_SetStatus SetStatus; /*规约更新应用状态*/
|
||||
CS103_AddSOE AddSOE; /*添加SOE信息*/
|
||||
|
||||
struct VCommBuf stRecvBuf; /*接收数据缓冲区*/
|
||||
struct VCommBuf stSendBuf; /*发送数据缓冲区*/
|
||||
}CS103;
|
||||
|
||||
/**
|
||||
* @brief 设置设备地址
|
||||
*
|
||||
* @param self
|
||||
* @param pstParam
|
||||
*/
|
||||
void CS103_SetAddr(CS103 *self, u8 ucAddr);
|
||||
|
||||
/**
|
||||
* @brief 设置总召定时间隔关联
|
||||
*
|
||||
* @param self
|
||||
* @param pstParam
|
||||
*/
|
||||
void CS103_SetSummonGap(CS103 *self, u32 ulGap);
|
||||
|
||||
/**
|
||||
* @brief 设置对时同步间隔关联
|
||||
*
|
||||
* @param self
|
||||
* @param pstParam
|
||||
*/
|
||||
void CS103_SetSynTimeGap(CS103 *self, u32 ulGap);
|
||||
|
||||
/**
|
||||
* @brief 101规约重发间隔时间参数输入
|
||||
* @param self
|
||||
* @param pstParam
|
||||
*/
|
||||
void CS103_ResendGap(CS103 *self, u16 usGap);
|
||||
/**
|
||||
* @brief 101规约重发次数参数输入
|
||||
* @param self
|
||||
* @param pstParam
|
||||
*/
|
||||
void CS103_ResendCnt(CS103 *self, u8 ucCnt);
|
||||
|
||||
/**
|
||||
* @brief 获取时间接口
|
||||
*
|
||||
* @param self
|
||||
* @param cb
|
||||
*/
|
||||
void CS103_GetTimeHandler(CS103 *self, CS10x_GetTime cb);
|
||||
|
||||
/**
|
||||
* @brief 设置接收遥测接口
|
||||
*
|
||||
* @param self
|
||||
* @param cb
|
||||
*/
|
||||
void CS103_SetValueHandler(CS103 *self, CS103_SetValue cb);
|
||||
|
||||
/**
|
||||
* @brief 设置接收遥信接口
|
||||
*
|
||||
* @param self
|
||||
* @param cb
|
||||
*/
|
||||
void CS103_SetStatusHandler(CS103 *self, CS103_SetStatus cb);
|
||||
|
||||
/**
|
||||
* @brief 设置接收SOE处理函数
|
||||
*
|
||||
* @param self
|
||||
* @param cb
|
||||
*/
|
||||
void CS103_AddSOEHandler(CS103 *self, CS103_AddSOE cb);
|
||||
|
||||
CS103 *CS103_Init(CS103_SendCb cb, void *arg, CS103_Type type);
|
||||
void CS103_Destory(CS103 *self);
|
||||
BOOL CS103_DoRecv(CS103 *self, u8 *pBuf, u16 usLen);
|
||||
void CS103_TimerHandle(CS103 *self, u16 usGap);
|
||||
|
||||
#endif /* IEC103TYPE_H_ */
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : gb104.h
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年03月23日
|
||||
最近修改 :
|
||||
功能描述 : gb104.c的头文件
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年03月23日
|
||||
修改内容 : 创建文件
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __GB104_H
|
||||
#define __GB104_H
|
||||
/**************************************文件包含*******************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib60870_common.h"
|
||||
#include "lib60870_public.h"
|
||||
#include "lib60870_process.h"
|
||||
#include "Asdu.h"
|
||||
/**************************************宏定义*********************************/
|
||||
#define START_CODE 0x68
|
||||
#define FRM_I 0
|
||||
#define FRM_S 1
|
||||
#define FRM_U 3
|
||||
|
||||
#define MAX_FRAME_COUNTER 0x7fff
|
||||
#define COUNTER_LIMIT 0x8000
|
||||
|
||||
#define STARTDT_ACT 0x07
|
||||
#define STARTDT_CON 0x0B
|
||||
#define STOPDT_ACT 0x13
|
||||
#define STOPDT_CON 0x23
|
||||
#define TESTFR_ACT 0x43
|
||||
#define TESTFR_CON 0x83
|
||||
|
||||
#define T0_TimeHandle 0
|
||||
#define T1_TimeHandle 1
|
||||
#define T2_TimeHandle 2
|
||||
#define T3_TimeHandle 3
|
||||
/************************************数据结构定义*****************************/
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
/**************************************数据声明******************************/
|
||||
|
||||
/**************************************内部函数声明***************************/
|
||||
char GB104_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen);
|
||||
void GB104_Preprocessor(CS10xHandle_t pstSelf);
|
||||
void DoSFrame(CS10xHandle_t pstSelf);
|
||||
void DoUFrame(CS10xHandle_t pstSelf);
|
||||
|
||||
char GB104_EncodeFrame(CS10xHandle_t pstSelf);
|
||||
char GB104_EncodeOther(CS10xHandle_t pstSelf);
|
||||
|
||||
unsigned short GB104_EncodeApci(CS10xHandle_t pstSelf, unsigned char ucFrameType, VIec104Frame * pstFrame);
|
||||
void GB104_EncodeApduLen(CS10xHandle_t pstSelf, VIec104Frame * pstApdu);
|
||||
void GB104_FrameTimerHdl(CS10xHandle_t pstSelf, VIec104Frame * pstApdu);
|
||||
|
||||
void GB104_SendAck(CS10xHandle_t pstSelf);
|
||||
void SendUFrame(CS10xHandle_t pstSelf, unsigned char ucType);
|
||||
|
||||
void StopTimer(CS10xHandle_t pstSelf, unsigned short usTimerId);
|
||||
void StartTimer(CS10xHandle_t pstSelf, unsigned short usTimerId);
|
||||
void GB104_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
bool Check_IEC_104(unsigned char* pstBuf, unsigned short uslen);
|
||||
/************************************外部接口函数声明*************************/
|
||||
extern void CS10x_104Init(CS10xHandle_t pstSelf, CS10x_SendCb cb, void *arg, CS10x_Type enType);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef __LIB60870_INC_H__
|
||||
#define __LIB60870_INC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h> //字符串处理
|
||||
#include <stdio.h>
|
||||
|
||||
#define IEC_LOBYTE(w) ((unsigned char)(w))
|
||||
#define IEC_HIBYTE(w) ((unsigned char)((unsigned short)(w) >> 8))
|
||||
#define IEC_MAKEWORD(low, high) ((unsigned short)((unsigned char)(low) | (((unsigned short)((unsigned char)(high))) << 8)))
|
||||
|
||||
|
||||
#ifndef IEC_PRINT
|
||||
#define IEC_PRINT(fmt, args...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : lib60870_process.h
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年04月07日
|
||||
最近修改 :
|
||||
功能描述 : lib60870_process.c的头文件 101及104规约共用流程
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年04月07日
|
||||
修改内容 : 创建文件
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __LIB60870_PROCESS_H
|
||||
#define __LIB60870_PROCESS_H
|
||||
/**************************************文件包含*******************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib60870_common.h"
|
||||
#include "Asdu.h"
|
||||
/**************************************宏定义*********************************/
|
||||
|
||||
|
||||
/************************************数据结构定义*****************************/
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
|
||||
/**************************************数据声明******************************/
|
||||
|
||||
/**************************************内部函数声明***************************/
|
||||
|
||||
/************************************外部接口函数声明*************************/
|
||||
extern void CheckUpdate_SoeEvent(CS10xHandle_t pstSelf);
|
||||
extern void CheckSOE_SendInfo(CS10xHandle_t pstSelf);
|
||||
extern void CheckFaultEvent_SendInfo(CS10xHandle_t pstSelf);
|
||||
extern void CheckTimeDd_SendInfo(CS10xHandle_t pstSelf);
|
||||
extern void CheckDiturbYc_SendInfo(CS10xHandle_t pstSelf);
|
||||
extern void CheckUpdate_DiturbYcEvent(CS10xHandle_t pstSelf);
|
||||
extern void CS10x_M_Scheduled(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
extern void CS10x_M_Finish(CS10xHandle_t pstSelf);
|
||||
extern void PollFileTransTask(CS10xHandle_t pstSelf);
|
||||
extern void CheckSummonSlaveDelay(CS10xHandle_t pstSelf, unsigned short usGap);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : lib60870_public.h
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年04月07日
|
||||
最近修改 :
|
||||
功能描述 : lib60870_public.c的头文件 101及104规约实现中的任务管理及校验等功能
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年04月07日
|
||||
修改内容 : 创建文件
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __LIB60870_PUBLIC_H
|
||||
#define __LIB60870_PUBLIC_H
|
||||
/**************************************文件包含*******************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib60870_common.h"
|
||||
/**************************************宏定义*********************************/
|
||||
#define TAG_TPYE_BOOL 1 //布尔
|
||||
#define TAG_TPYE_INT 2 //整形
|
||||
#define TAG_TPYE_STR 4 //字符串
|
||||
#define TAG_TPYE_UTINY 32 //无符号小整形
|
||||
#define TAG_TPYE_SHORT 33 //短整形
|
||||
#define TAG_TPYE_UINT 35 //无符号整形
|
||||
#define TAG_TPYE_LONG 36 //长整形
|
||||
#define TAG_TPYE_ULONG 37 //无符号长整形
|
||||
#define TAG_TPYE_FLOAT 38 //单精度浮点
|
||||
#define TAG_TPYE_DOUBLE 39 //双精度浮点
|
||||
#define TAG_TPYE_TINY 43 //小整形
|
||||
#define TAG_TPYE_USHORT 45 //无符号短整形
|
||||
|
||||
/************************************数据结构定义*****************************/
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
|
||||
/**************************************数据声明*******************************/
|
||||
|
||||
/**************************************内部函数声明***************************/
|
||||
|
||||
/************************************外部接口函数声明*************************/
|
||||
extern unsigned char CS10x_SendTask(CS10xHandle_t pstSelf);
|
||||
extern void SetSendTask(CS10xHandle_t pstSelf, unsigned int uiFlagNo, unsigned short usParam_low, unsigned short usParam_hig);
|
||||
extern void SetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
|
||||
extern unsigned int GetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
|
||||
extern void ClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
|
||||
extern int CheckClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo);
|
||||
extern void ClearAllTaskflgs(CS10xHandle_t pstSelf);
|
||||
extern unsigned char checksum_8(unsigned char *pucBuf, unsigned char ucLen);
|
||||
extern int CheckParamTagAndLen(unsigned char ucTag, unsigned char ucLen);
|
||||
extern unsigned char CP56Time2a_Pack2Buf(unsigned char *pucOutBuf, const __CP56Time2a *pstCp56);
|
||||
extern unsigned char CP56Time2a_GetFromBuf(const unsigned char *pucInBuf, __CP56Time2a *pstCp56);
|
||||
extern unsigned char IntBytes_Pack2Buf(unsigned char *pucOutBuf, unsigned int uiVal, unsigned char ucSize);
|
||||
extern unsigned int IntBytes_GetFromBuf(const unsigned char *pucInBuf, unsigned char ucSize);
|
||||
extern unsigned char Float_Pack2Buf(unsigned char *pucOutBuf, float fVal);
|
||||
extern float Float_GetFromBuf(const unsigned char *pucInBuf);
|
||||
extern unsigned char U16_Pack2Buf(unsigned char *pucOutBuf, unsigned short usVal);
|
||||
extern unsigned short U16_GetFromBuf(const unsigned char *pucInBuf);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
#ifndef _MD5_H_
|
||||
#define _MD5_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned char *POINTER;
|
||||
typedef uint16_t UINT2;
|
||||
typedef uint32_t UINT4;
|
||||
|
||||
#define MD5_BIT16 0x10
|
||||
#define MD5_BIT32 0x20
|
||||
|
||||
#define PROTO_LIST(list) list
|
||||
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
typedef struct _MD5_CTX
|
||||
{
|
||||
UINT4 state[4];
|
||||
UINT4 count[2];
|
||||
unsigned char buffer[64];
|
||||
} MD5_CTX;
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac);\
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
#define TEST_BLOCK_LEN 1000
|
||||
#define TEST_BLOCK_COUNT 1000
|
||||
|
||||
void StartMD5(MD5_CTX * context);
|
||||
void EncodeMD5(MD5_CTX * context, unsigned char * input, int len);
|
||||
void GetMD5(MD5_CTX * context, unsigned char * result);
|
||||
void GetMD5String(MD5_CTX * context, char * result, unsigned char mode);
|
||||
|
||||
#endif //_MD5_H_
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @file myIec60870.h
|
||||
* @brief IEC 60870-5-101/103/104 协议栈统一入口
|
||||
* @details 原工程自研协议栈(科大智能,2022)。
|
||||
* 本项目不修改库源码,本文件仅作为聚合入口。
|
||||
* 调用者只需 #include "myIec60870.h" 即可获取全部 IEC 60870 接口。
|
||||
*/
|
||||
#ifndef _MY_IEC60870_H_
|
||||
#define _MY_IEC60870_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "lib60870_common.h" /* 公共数据结构、回调函数类型、CS10xHandle_t */
|
||||
#include "lib60870_public.h" /* 任务管理、校验、CP56Time2a 编解码 */
|
||||
#include "lib60870_process.h" /* 协议处理主流程 */
|
||||
#include "lib60870_inc.h" /* 内部参数宏定义 */
|
||||
#include "Asdu.h" /* ASDU 域数据编解码 */
|
||||
#include "gb104.h" /* IEC 60870-5-104 协议实现 */
|
||||
#include "gb101.h" /* IEC 60870-5-101 协议实现 */
|
||||
#include "gb103.h" /* IEC 60870-5-103 协议实现 */
|
||||
#include "md5.h" /* MD5 辅助 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MY_IEC60870_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,747 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : gb104.c
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年03月23日
|
||||
最近修改 :
|
||||
功能描述 : 104规约实现主体
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年03月23日
|
||||
修改内容 : 创建文件
|
||||
*******************************************************************************/
|
||||
/*************************************文件包含*********************************/
|
||||
#include "gb104.h"
|
||||
/***************************************static函数声明*******************************/
|
||||
static unsigned char GB104_GetOneFrame(CS10xHandle_t pstSelf, unsigned char *pucFramePt, unsigned short usLastLen, unsigned short *pusSearchLen);
|
||||
static void GB104_DecodeOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf) ; //解析单帧数据
|
||||
/*************************************外部接口函数*****************************/
|
||||
/**
|
||||
* @brief 规约使用前初始化
|
||||
* @param[in] pstSelf-函数实体指针
|
||||
* @param[in] cb-发送函数指针
|
||||
* @param[in] arg-用户数据指针
|
||||
* @param[in] enType-规约类型 主从
|
||||
* @param[out] 无
|
||||
* @return 规约实体指针
|
||||
*/
|
||||
void CS10x_104Init(CS10xHandle_t pstSelf, CS10x_SendCb pcb, void *arg, CS10x_Type enType)
|
||||
{
|
||||
pstSelf->eCS10x_Type = enType;
|
||||
pstSelf->pfnSendCb = pcb;
|
||||
pstSelf->pUsrData = arg;
|
||||
pstSelf->pfnDecodeProcess = GB104_DecodeProcess;
|
||||
pstSelf->pfnEncodeFrame = GB104_EncodeFrame;
|
||||
pstSelf->pfnEncodeOther = GB104_EncodeOther;
|
||||
pstSelf->pfnTimerManager = GB104_TimerOut;
|
||||
|
||||
if(enType == CS104_TYPE_M) //主模式注册轮询文件传输任务函数
|
||||
{
|
||||
pstSelf->pfnPollFileTransTask = PollFileTransTask;
|
||||
pstSelf->uiTransTimerMax = TRANS_TIMEOUT_MAX / TRANS_SCH_GAP;
|
||||
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USACT, 0); //此处需修改
|
||||
}
|
||||
|
||||
/*默认初始化参数*/
|
||||
pstSelf->usYcType = YC_TYPE_ME_NC;
|
||||
pstSelf->usYxType = YX_TYPE_M_SP;
|
||||
pstSelf->usYkType = YK_TYPE_C_SC;
|
||||
pstSelf->usDdType = DD_TYPE_IT_NB;
|
||||
pstSelf->usAsduPublicAddr = 1;
|
||||
/*应用参数*/
|
||||
pstSelf->stAppParameters.iSzOfLinkAddr = 2;
|
||||
pstSelf->stAppParameters.iSzOfTypeId = 1;
|
||||
pstSelf->stAppParameters.iSzOfVSQ = 1;
|
||||
pstSelf->stAppParameters.iSzOfCOT = 2;
|
||||
pstSelf->stAppParameters.iSzOfCA = 2;
|
||||
pstSelf->stAppParameters.iSzOfIOA = 3;
|
||||
pstSelf->stAppParameters.iLinkAddr = 1;
|
||||
pstSelf->stAppParameters.iPublicAddr = 1;
|
||||
/*总招对时时间*/
|
||||
pstSelf->uiSummon_Gap = 300000; /*300秒*/
|
||||
pstSelf->uiSyn_Gap = 300000; /*300秒*/
|
||||
pstSelf->uiSend_Gap = 100; /*100ms*/
|
||||
/*104*/
|
||||
pstSelf->stAPCIParameters.iT0 = 10;
|
||||
pstSelf->stAPCIParameters.iT1 = 12;
|
||||
pstSelf->stAPCIParameters.iT2 = 8;
|
||||
pstSelf->stAPCIParameters.iT3 = 15;
|
||||
pstSelf->stAPCIParameters.iK = 12;
|
||||
pstSelf->stAPCIParameters.iW = 8;
|
||||
pstSelf->ucMultiFrameEn = 0; //104多帧发送使能
|
||||
pstSelf->usFaultEnable = 1; //故障事件使能
|
||||
pstSelf->ucSenSoeEa = 1; //发送SOE使能
|
||||
pstSelf->ucSenCosEa = 1; //发送COS使能
|
||||
pstSelf->ucYKEndFrame = 1; //遥控结束帧投入
|
||||
pstSelf->ucOffLineSoeReissueEn = 1;//离线SOE补发使能
|
||||
pstSelf->ucReadFileVSQ = 0; //读文件数据传输VSQ状态值
|
||||
pstSelf->ucPreSetContType = 0; /* 默认为正常参数预置流程*/
|
||||
#ifdef IEC_DEBUG_MSG
|
||||
IEC_PRINT("Create IEC104 %s\n", enType == CS104_TYPE_M ? "主站" : "从站");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************内部调用函数*****************************/
|
||||
/**
|
||||
* @brief 104规约数据帧处理
|
||||
* @param[in] pstself-规约实体指针 参数
|
||||
* @param[in] pucBuf-报文数据指针 接收的报文
|
||||
* @param[in] usLen-报文长度
|
||||
* @param[out] 无
|
||||
* @return 无实际意义
|
||||
*/
|
||||
char GB104_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen)
|
||||
{
|
||||
unsigned short usFramePos = 0; //一条报文中含有多帧104时,表示每帧起始在报文中起始位置
|
||||
unsigned short usSearchLen = 0; //本次查找返回的报文的长度(包括错误帧)
|
||||
|
||||
do //拆分多帧报文并解析
|
||||
{
|
||||
if(GB104_GetOneFrame(pstSelf, pucBuf + usFramePos, usLen - usFramePos, &usSearchLen)) //查找单帧报文
|
||||
{
|
||||
GB104_DecodeOneFrame(pstSelf, pstSelf->stPubBuf.pBuf); //解析单帧
|
||||
usFramePos += usSearchLen; //报文解析起始位置更新
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while(usFramePos < usLen); //越界判断
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 查找单帧报文 并复制到公共缓冲区
|
||||
* @param[in] pstSelf-规约实体指针 包括参数与公共接收报文缓冲
|
||||
* @param[in] *pucFramePt- 接收数据全部报文指针
|
||||
* @param[in] usLastLen-接受的全部报文长度
|
||||
* @param[out] *pusSearchLen-解析单帧报文长度包括错误帧
|
||||
* @return 0无有效帧 1存在有效单帧
|
||||
*/
|
||||
static unsigned char GB104_GetOneFrame(CS10xHandle_t pstSelf, unsigned char *pucFramePt, unsigned short usLastLen, unsigned short *pusSearchLen)
|
||||
{
|
||||
if(Check_IEC_104(pucFramePt, usLastLen) == 0) //核对104报文
|
||||
{
|
||||
*pusSearchLen = usLastLen;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->stPubBuf.usWritePtr = pucFramePt[1] + 2; //单帧报文全部长度
|
||||
memcpy(pstSelf->stPubBuf.pBuf, pucFramePt, pstSelf->stPubBuf.usWritePtr);//拷贝当前帧到公共缓存待解析
|
||||
*pusSearchLen = pstSelf->stPubBuf.usWritePtr; //更新指针偏移
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 解析全部类型的单帧报文
|
||||
* @param[in] pstSelf-规约实体指针 包括参数与公共接收报文缓冲
|
||||
* @param[in] pucBuf-报文数据指针 接收数据分帧后的单帧报文
|
||||
* @param[in]
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
static void GB104_DecodeOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf) //解析单帧数据
|
||||
{
|
||||
unsigned char ucContolParam = 0;
|
||||
StartTimer(pstSelf, T3_TimeHandle); // receive any I,U,S frame, to start T3
|
||||
ucContolParam = pucBuf[2]; //控制帧 单帧报文第三位控制帧区分报文类型
|
||||
|
||||
switch(ucContolParam & 0x03)
|
||||
{
|
||||
case FRM_I:
|
||||
GB104_Preprocessor(pstSelf); //I帧信息
|
||||
break;
|
||||
|
||||
case FRM_S:
|
||||
DoSFrame(pstSelf); //确认帧信息
|
||||
break;
|
||||
|
||||
case FRM_U:
|
||||
DoUFrame(pstSelf); //控制帧信息
|
||||
break;
|
||||
|
||||
default:
|
||||
GB104_Preprocessor(pstSelf);
|
||||
break;
|
||||
}
|
||||
|
||||
if(pstSelf->usSendNum > pstSelf->usAckSendNum && (pstSelf->usSendNum - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
|
||||
{
|
||||
pstSelf->bContinueSendFlag = 0;
|
||||
StartTimer(pstSelf, T1_TimeHandle);
|
||||
|
||||
if((pstSelf->usSendNum - pstSelf->usAckSendNum) >= 2 * pstSelf->stAPCIParameters.iK)
|
||||
{
|
||||
pstSelf->ucInitStatus = 0;
|
||||
|
||||
if(pstSelf->pfnLinkClose)
|
||||
{
|
||||
pstSelf->pfnLinkClose(pstSelf->pUsrData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((pstSelf->usSendNum < pstSelf->usAckSendNum) && (pstSelf->usSendNum + COUNTER_LIMIT - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
|
||||
{
|
||||
pstSelf->bContinueSendFlag = 0;
|
||||
StartTimer(pstSelf, T1_TimeHandle);
|
||||
|
||||
if((pstSelf->usSendNum + COUNTER_LIMIT - pstSelf->usAckSendNum) >= 2 * pstSelf->stAPCIParameters.iK)
|
||||
{
|
||||
pstSelf->ucInitStatus = 0;
|
||||
|
||||
if(pstSelf->pfnLinkClose)
|
||||
{
|
||||
pstSelf->pfnLinkClose(pstSelf->pUsrData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->bContinueSendFlag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约收到的长帧解析处理接口函数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void GB104_Preprocessor(CS10xHandle_t pstSelf)
|
||||
{
|
||||
unsigned short usAckNum = 0;
|
||||
unsigned short usRecvNum = 0;
|
||||
VIec104Frame *pstReceive = (VIec104Frame *)pstSelf->stPubBuf.pBuf;
|
||||
|
||||
/*未进行初始化时,不响应数据*/
|
||||
if(pstSelf->ucInitStatus != 1)
|
||||
{
|
||||
if((pstSelf->eCS10x_Type == CS104_TYPE_S) || ((pstSelf->eCS10x_Type == CS104_TYPE_M) && (pstReceive->byASDU[0] != M_EI_NA)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
StartTimer(pstSelf, T2_TimeHandle); // when Receve I frame, start T2
|
||||
StopTimer(pstSelf, T1_TimeHandle); // stop T1
|
||||
/*处理APCI信息 */
|
||||
usAckNum = IEC_MAKEWORD(pstReceive->byControl3, pstReceive->byControl4);
|
||||
usRecvNum = IEC_MAKEWORD(pstReceive->byControl1, pstReceive->byControl2);
|
||||
usAckNum >>= 1; //最低位不是收发序列号
|
||||
usRecvNum >>= 1;
|
||||
pstSelf->usRecvNum = usRecvNum + 1;
|
||||
pstSelf->usAckSendNum = usAckNum;
|
||||
DoAckFrame(pstSelf);// 检查扰动遥测和SOE
|
||||
|
||||
// 判断终端是否需要给主站回复确认帧
|
||||
if((pstSelf->usRecvNum - pstSelf->usAckRecvNum) > pstSelf->stAPCIParameters.iW)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0);
|
||||
}
|
||||
|
||||
/*处理ASDU元素*/
|
||||
DecodeAsduMember(pstSelf, pstReceive->byASDU, pstReceive->byAPDULen - 4);
|
||||
/*处理ASDU信息体*/
|
||||
DecodeAsduInfoObj(pstSelf);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约S帧解析
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void DoSFrame(CS10xHandle_t pstSelf)
|
||||
{
|
||||
/*未进行初始化时,不响应数据*/
|
||||
if(pstSelf->ucInitStatus != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned short usAckNum = 0; //序列号
|
||||
VIec104Frame *pstReceive = NULL;
|
||||
pstReceive = (VIec104Frame *)pstSelf->stPubBuf.pBuf;
|
||||
StopTimer(pstSelf, T1_TimeHandle);
|
||||
usAckNum = IEC_MAKEWORD(pstReceive->byControl3, pstReceive->byControl4);
|
||||
pstSelf->usAckSendNum = usAckNum >> 1;
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_S) //作为从站时
|
||||
{
|
||||
DoAckFrame(pstSelf);
|
||||
if(pstSelf->pfnAckFrameNotification)
|
||||
{
|
||||
pstSelf->pfnAckFrameNotification();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约U帧解析处理函数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void DoUFrame(CS10xHandle_t pstSelf)
|
||||
{
|
||||
VIec104Frame *pstReceive = NULL;
|
||||
pstReceive = (VIec104Frame *)pstSelf->stPubBuf.pBuf;
|
||||
|
||||
switch(pstReceive->byControl1)
|
||||
{
|
||||
case STARTDT_ACT: //收到启动链路
|
||||
ClearAllTaskflgs(pstSelf);
|
||||
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USTCON, 0);
|
||||
SetSendTask(pstSelf, TSKID_InitFinish, COT_INIT, 0);
|
||||
pstSelf->bContinueSendFlag = 1;
|
||||
pstSelf->ucInitStatus = 1;
|
||||
break;
|
||||
|
||||
case STOPDT_ACT: //收到断开链路
|
||||
ClearAllTaskflgs(pstSelf);
|
||||
SetSendTask(pstSelf, TSKID_StopLink, TSK_PARM_USTCON, 0);
|
||||
break;
|
||||
|
||||
case TESTFR_ACT: //收到测试
|
||||
|
||||
/*仅初始化完成,响应测试帧*/
|
||||
if(pstSelf->ucInitStatus == 1)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_UTest, TSK_PARM_USTCON, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STARTDT_CON: //启动链路响应
|
||||
StopTimer(pstSelf, T0_TimeHandle);
|
||||
pstSelf->bContinueSendFlag = 1;
|
||||
ClearTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink); //主模式复位启动链路发送标志
|
||||
break;
|
||||
|
||||
case STOPDT_CON: //断开链路响应
|
||||
pstSelf->bContinueSendFlag = false;
|
||||
StopTimer(pstSelf, T0_TimeHandle);
|
||||
StopTimer(pstSelf, T1_TimeHandle);
|
||||
StopTimer(pstSelf, T2_TimeHandle);
|
||||
StopTimer(pstSelf, T3_TimeHandle);
|
||||
|
||||
if(pstSelf->pfnLinkClose)
|
||||
{
|
||||
pstSelf->pfnLinkClose(pstSelf->pUsrData);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TESTFR_CON:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************104组帧接口函数*********/
|
||||
/**
|
||||
* @brief 104规约I帧组帧函数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无实际意义
|
||||
*/
|
||||
char GB104_EncodeFrame(CS10xHandle_t pstSelf)
|
||||
{
|
||||
pstSelf->stSendBuf.usReadPtr = 0;
|
||||
VIec104Frame * pstApdu = (VIec104Frame *)pstSelf->stSendBuf.pBuf;
|
||||
pstSelf->stSendBuf.usWritePtr += GB104_EncodeApci(pstSelf, FRM_I, pstApdu);
|
||||
pstSelf->stSendBuf.usWritePtr += GB10x_EncodeAsdu(pstSelf, (unsigned char *)pstApdu + pstSelf->stSendBuf.usWritePtr);
|
||||
GB104_EncodeApduLen(pstSelf, pstApdu);
|
||||
GB104_FrameTimerHdl(pstSelf, pstApdu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约短帧组帧函数 U帧S帧
|
||||
* @param[in] stSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无实际意义
|
||||
*/
|
||||
char GB104_EncodeOther(CS10xHandle_t pstSelf)
|
||||
{
|
||||
switch(pstSelf->byTaskFlagId)
|
||||
{
|
||||
//启动链路发起及响应
|
||||
case TSKID_StartLink:
|
||||
pstSelf->uiaTaskParam[TSKID_StartLink] = TSK_PARM_NONE;
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_S)
|
||||
{
|
||||
SendUFrame(pstSelf, STARTDT_CON);
|
||||
}
|
||||
else if(pstSelf->eCS10x_Type == CS104_TYPE_M)
|
||||
{
|
||||
SendUFrame(pstSelf, STARTDT_ACT);
|
||||
pstSelf->usSendNum = 0;
|
||||
pstSelf->usRecvNum = 0;
|
||||
pstSelf->usAckRecvNum = 0;
|
||||
pstSelf->usAckRecvNum = 0;
|
||||
StartTimer(pstSelf, T0_TimeHandle);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
//断开链路发起及响应
|
||||
case TSKID_StopLink:
|
||||
pstSelf->uiaTaskParam[TSKID_StopLink] = TSK_PARM_NONE;
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_S)
|
||||
{
|
||||
SendUFrame(pstSelf, STOPDT_CON);
|
||||
}
|
||||
else if(pstSelf->eCS10x_Type == CS104_TYPE_M)
|
||||
{
|
||||
SendUFrame(pstSelf, STOPDT_ACT);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// TEST发起及响应
|
||||
case TSKID_UTest:
|
||||
if((pstSelf->uiaTaskParam[TSKID_UTest] & 0xFF) == TSK_PARM_USTCON)
|
||||
{
|
||||
SendUFrame(pstSelf, TESTFR_CON);
|
||||
}
|
||||
else if((pstSelf->uiaTaskParam[TSKID_UTest] & 0xFF) == TSK_PARM_USACT)
|
||||
{
|
||||
SendUFrame(pstSelf, TESTFR_ACT);
|
||||
}
|
||||
|
||||
pstSelf->uiaTaskParam[TSKID_UTest] = TSK_PARM_NONE;
|
||||
break;
|
||||
|
||||
//应答 S帧
|
||||
case TSKID_Ack:
|
||||
pstSelf->uiaTaskParam[TSKID_Ack] = TSK_PARM_NONE;
|
||||
GB104_SendAck(pstSelf);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约ASDU域确认前处理函数 发送帧序号处理
|
||||
* @param[in] stSelf-规约实体指针
|
||||
* @param[in] ucFrameType-帧类型
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
unsigned short GB104_EncodeApci(CS10xHandle_t pstSelf, unsigned char ucFrameType, VIec104Frame * pstFrame)
|
||||
{
|
||||
unsigned short usSendNum = 0;
|
||||
unsigned short usRecvNum = 0;
|
||||
pstSelf->usSendNum %= (MAX_FRAME_COUNTER + 1);
|
||||
pstSelf->usRecvNum %= (MAX_FRAME_COUNTER + 1);
|
||||
usSendNum = pstSelf->usSendNum << 1;
|
||||
usRecvNum = pstSelf->usRecvNum << 1;
|
||||
|
||||
if(NULL == pstFrame)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pstFrame->byStartCode = START_CODE;
|
||||
|
||||
switch(ucFrameType)
|
||||
{
|
||||
case FRM_I:
|
||||
pstFrame->byControl1 = IEC_LOBYTE(usSendNum);
|
||||
pstFrame->byControl2 = IEC_HIBYTE(usSendNum);
|
||||
pstFrame->byControl3 = IEC_LOBYTE(usRecvNum);
|
||||
pstFrame->byControl4 = IEC_HIBYTE(usRecvNum);
|
||||
pstSelf->usAckRecvNum = pstSelf->usRecvNum;
|
||||
break;
|
||||
|
||||
case FRM_S:
|
||||
pstFrame->byControl1 = FRM_S;
|
||||
pstFrame->byControl2 = 0;
|
||||
pstFrame->byControl3 = IEC_LOBYTE(usRecvNum);
|
||||
pstFrame->byControl4 = IEC_HIBYTE(usRecvNum);
|
||||
pstSelf->usAckRecvNum = pstSelf->usRecvNum;
|
||||
break;
|
||||
|
||||
case FRM_U:
|
||||
pstFrame->byControl1 = FRM_U;
|
||||
pstFrame->byControl2 = 0;
|
||||
pstFrame->byControl3 = 0;
|
||||
pstFrame->byControl4 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return APCI_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约ASDU域确认前处理函数 发送帧序号处理
|
||||
* @param[in] stSelf-规约实体指针
|
||||
* @param[in] ucFrameType-帧类型
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void GB104_EncodeApduLen(CS10xHandle_t pstSelf, VIec104Frame * pstApdu)
|
||||
{
|
||||
pstApdu->byAPDULen = pstSelf->stSendBuf.usWritePtr - 2;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约ASDU域确认后处理函数
|
||||
* @param[in] stSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void GB104_FrameTimerHdl(CS10xHandle_t pstSelf, VIec104Frame * pstApdu)
|
||||
{
|
||||
if((pstApdu->byControl1 & 0x1) == FRM_I)
|
||||
{
|
||||
/*仅存储I帧*/
|
||||
// SaveSendFrame(pstSelf, pstSelf->usSendNum, pstSelf->stSendBuf.usWritePtr, pstSelf->stSendBuf.pBuf);
|
||||
StopTimer(pstSelf, T2_TimeHandle); // when send I frame, stop T2
|
||||
pstSelf->usSendNum++;
|
||||
|
||||
if(pstSelf->usSendNum >= COUNTER_LIMIT)
|
||||
{
|
||||
pstSelf->usSendNum = 0;
|
||||
}
|
||||
|
||||
if(pstSelf->usSendNum > pstSelf->usAckSendNum && (pstSelf->usSendNum - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
|
||||
{
|
||||
pstSelf->bContinueSendFlag = 0;
|
||||
StartTimer(pstSelf, T1_TimeHandle);
|
||||
}
|
||||
else if((pstSelf->usSendNum < pstSelf->usAckSendNum) && (pstSelf->usSendNum + COUNTER_LIMIT - pstSelf->usAckSendNum) >= pstSelf->stAPCIParameters.iK)
|
||||
{
|
||||
pstSelf->bContinueSendFlag = 0;
|
||||
StartTimer(pstSelf, T1_TimeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约S帧组帧函数
|
||||
* @param[in] stSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void GB104_SendAck(CS10xHandle_t pstSelf)
|
||||
{
|
||||
VIec104Frame *pstApdu = (VIec104Frame *)pstSelf->stSendBuf.pBuf;
|
||||
pstSelf->stSendBuf.usWritePtr += GB104_EncodeApci(pstSelf, FRM_S, pstApdu);
|
||||
GB104_EncodeApduLen(pstSelf, pstApdu);
|
||||
GB104_FrameTimerHdl(pstSelf, pstApdu);
|
||||
StopTimer(pstSelf, T2_TimeHandle); // when send S frame, stop T2
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 104规约U帧组帧函数
|
||||
* @param[in] stSelf-规约实体指针
|
||||
* @param[in] ucType-U帧类型
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void SendUFrame(CS10xHandle_t pstSelf, unsigned char ucType)
|
||||
{
|
||||
VIec104Frame *pstApdu = (VIec104Frame *)pstSelf->stSendBuf.pBuf;
|
||||
pstSelf->stSendBuf.usWritePtr += GB104_EncodeApci(pstSelf, FRM_U, pstApdu);
|
||||
pstApdu->byControl1 |= ucType;
|
||||
GB104_EncodeApduLen(pstSelf, pstApdu);
|
||||
GB104_FrameTimerHdl(pstSelf, pstApdu);
|
||||
return;
|
||||
}
|
||||
|
||||
/***************104规约计时******************/
|
||||
/**
|
||||
* @brief 104规约定时处理函数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[in] usGap-间隔时间ms
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void GB104_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap)
|
||||
{
|
||||
if(pstSelf->stM_vTimer[0].bRun)
|
||||
{
|
||||
pstSelf->stM_vTimer[0].uiCounter -= usGap;
|
||||
|
||||
if(pstSelf->stM_vTimer[0].uiCounter < usGap) //建立连接超时
|
||||
{
|
||||
#ifdef IEC_DEBUG_MSG
|
||||
IEC_PRINT("iec104 slave T0 timeout,close TCP!\n");
|
||||
#endif
|
||||
// to do:when T1 timeout,close tcp connect
|
||||
ClearAllTaskflgs(pstSelf);
|
||||
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USACT, 0);
|
||||
|
||||
if(pstSelf->pfnLinkClose)
|
||||
{
|
||||
pstSelf->pfnLinkClose(pstSelf->pUsrData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->stM_vTimer[1].bRun)
|
||||
{
|
||||
pstSelf->stM_vTimer[1].uiCounter -= usGap;
|
||||
|
||||
if(pstSelf->stM_vTimer[1].uiCounter < usGap) //发送数据超时
|
||||
{
|
||||
#ifdef IEC_DEBUG_MSG
|
||||
IEC_PRINT("iec104 slave T1 timeout,close TCP!\n");
|
||||
#endif
|
||||
StopTimer(pstSelf, T1_TimeHandle);
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_M)
|
||||
{
|
||||
// to do:when T1 timeout,close tcp connect
|
||||
SetSendTask(pstSelf, TSKID_StartLink, TSK_PARM_USACT, 0);
|
||||
}
|
||||
else if(pstSelf->eCS10x_Type == CS104_TYPE_S)
|
||||
{
|
||||
pstSelf->ucInitStatus = 0; // 初始化完成状态
|
||||
|
||||
if(pstSelf->pfnLinkClose)
|
||||
{
|
||||
pstSelf->pfnLinkClose(pstSelf->pUsrData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->stM_vTimer[2].bRun)
|
||||
{
|
||||
pstSelf->stM_vTimer[2].uiCounter -= usGap;
|
||||
|
||||
if(pstSelf->stM_vTimer[2].uiCounter < usGap) //无数据报文超时给应答
|
||||
{
|
||||
// to do:when T2 timeout, send S frame
|
||||
SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0);
|
||||
StopTimer(pstSelf, T2_TimeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->stM_vTimer[3].bRun)
|
||||
{
|
||||
pstSelf->stM_vTimer[3].uiCounter -= usGap;
|
||||
|
||||
if(pstSelf->stM_vTimer[3].uiCounter < usGap) //无数据超时测试帧
|
||||
{
|
||||
// to do:when T3 timeout
|
||||
if(pstSelf->ucInitStatus == 1)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_UTest, TSK_PARM_USACT, 0);
|
||||
}
|
||||
|
||||
StopTimer(pstSelf, T3_TimeHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止定时计数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[in] usTimerId-定时ID
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void StopTimer(CS10xHandle_t pstSelf, unsigned short usTimerId)
|
||||
{
|
||||
if(usTimerId > T3_TimeHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pstSelf->stM_vTimer[usTimerId].bRun = 0;
|
||||
pstSelf->stM_vTimer[usTimerId].uiCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开始定时计数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[in] usTimerId-定时ID
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void StartTimer(CS10xHandle_t pstSelf, unsigned short usTimerId)
|
||||
{
|
||||
if(usTimerId > T3_TimeHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pstSelf->stM_vTimer[usTimerId].bRun = 1;
|
||||
|
||||
if(usTimerId == T0_TimeHandle)
|
||||
{
|
||||
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT0 * 1000;
|
||||
}
|
||||
else if(usTimerId == T1_TimeHandle)
|
||||
{
|
||||
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT1 * 1000;
|
||||
}
|
||||
else if(usTimerId == T2_TimeHandle)
|
||||
{
|
||||
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT2 * 1000;
|
||||
}
|
||||
else if(usTimerId == T3_TimeHandle)
|
||||
{
|
||||
pstSelf->stM_vTimer[usTimerId].uiCounter = pstSelf->stAPCIParameters.iT3 * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 规约格式判定
|
||||
* @param pucBuf 数据指针
|
||||
* @param uslen 数据长度
|
||||
* @return true 符合104规约格式
|
||||
* @return false 不符合
|
||||
*/
|
||||
bool Check_IEC_104(unsigned char* pucBuf, unsigned short uslen)
|
||||
{
|
||||
if(pucBuf[0] != 0x68) //包头必须68
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(pucBuf[1] + 2 > uslen) //缺帧
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(pucBuf[1] + 2 < uslen) //连帧
|
||||
{
|
||||
if(pucBuf[pucBuf[1] + 2] != 0x68) //连包 检查下一帧报文是否0x68开头
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,440 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : lib60870_process.c
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年04月07日
|
||||
最近修改 :
|
||||
功能描述 : 101及104规约实现中的公共流程实现模块
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年04月07日
|
||||
修改内容 : 创建文件
|
||||
*******************************************************************************/
|
||||
/*************************************文件包含*********************************/
|
||||
#include "lib60870_process.h"
|
||||
|
||||
/***************************************数据定义*******************************/
|
||||
|
||||
/*************************************外部接口函数*****************************/
|
||||
/**
|
||||
* @brief 更新数据池中故障事件及SOE指针
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CheckUpdate_SoeEvent(CS10xHandle_t pstSelf)
|
||||
{
|
||||
if(pstSelf->usSoeSendNoAckNum)
|
||||
{
|
||||
if(NULL != pstSelf->pfnUpdata_SOE_Pout)
|
||||
{
|
||||
pstSelf->pfnUpdata_SOE_Pout(pstSelf->pUsrData, pstSelf->usSoeSendNoAckNum);
|
||||
pstSelf->usCosSendNoAckNum -= pstSelf->usSoeSendNoAckNum;
|
||||
pstSelf->usSoeSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->usEventSendNoAckNum)
|
||||
{
|
||||
if(NULL != pstSelf->pfnUpdata_FaultEvent_Pout)
|
||||
{
|
||||
pstSelf->pfnUpdata_FaultEvent_Pout(pstSelf->pUsrData, pstSelf->usEventSendNoAckNum);
|
||||
pstSelf->usEventSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->usDduSendNoAckNum)
|
||||
{
|
||||
if(NULL != pstSelf->pfnUpdata_TimeDdu_Pout)
|
||||
{
|
||||
pstSelf->pfnUpdata_TimeDdu_Pout(pstSelf->pUsrData, pstSelf->usDduSendNoAckNum);
|
||||
pstSelf->usDduSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 更新数据池中扰动遥测指针
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CheckUpdate_DiturbYcEvent(CS10xHandle_t pstSelf)
|
||||
{
|
||||
if(pstSelf->usDiturbYcSendNoAckNum)
|
||||
{
|
||||
if(NULL != pstSelf->pfnUpdata_DiturbYc_Pout)
|
||||
{
|
||||
pstSelf->pfnUpdata_DiturbYc_Pout(pstSelf->pUsrData, pstSelf->usDiturbYcSendNoAckNum);
|
||||
pstSelf->usDiturbYcSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查数据池中SOE待发送数量
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CheckSOE_SendInfo(CS10xHandle_t pstSelf)
|
||||
{
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(NULL == pstSelf->pfnGetSOE_SendNum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* 链路未初始化完成,不进行任务调度*/
|
||||
if(1 != pstSelf->ucInitStatus)
|
||||
{
|
||||
pstSelf->usSoeSendSetup = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*cos-soe处理*/
|
||||
pstSelf->usSoeSendNum = pstSelf->pfnGetSOE_SendNum(pstSelf->pUsrData);
|
||||
|
||||
if(0 == pstSelf->usSoeSendSetup)
|
||||
{
|
||||
if(pstSelf->ucOffLineSoeReissueEn)
|
||||
{
|
||||
pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->pfnUpdata_SOE_Pout(pstSelf->pUsrData, pstSelf->usSoeSendNum);
|
||||
pstSelf->usSoeSendNum = 0;
|
||||
pstSelf->usCosSendNoAckNum = 0;
|
||||
}
|
||||
pstSelf->usSoeSendSetup = 1;
|
||||
}
|
||||
|
||||
if(pstSelf->usSoeSendNum)
|
||||
{
|
||||
if(pstSelf->usSoeSendNum != pstSelf->usSoeSendNoAckNum)
|
||||
{
|
||||
if(pstSelf->usSoeSendNum > pstSelf->usCosSendNoAckNum)
|
||||
{
|
||||
// 发送SOE/COS使能参数
|
||||
if(pstSelf->ucSenCosEa == 0)
|
||||
{
|
||||
pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_SendCOS, COT_SPONT, 0); //正常发送COS
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 发送SOE/COS使能参数
|
||||
pstSelf->usCosSendNoAckNum = pstSelf->usSoeSendNum;
|
||||
|
||||
if(pstSelf->ucSenSoeEa == 0)
|
||||
{
|
||||
pstSelf->usSoeSendNoAckNum = pstSelf->usSoeSendNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_SendSOE, COT_SPONT, 0); //正常发送SOE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->usSoeSendNoAckNum = 0;
|
||||
pstSelf->usCosSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查数据池中故障事件待发送数量
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CheckFaultEvent_SendInfo(CS10xHandle_t pstSelf)
|
||||
{
|
||||
unsigned short usEventSendNum = 0;
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(NULL == pstSelf->pfnGetEvent_SendNum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* 链路未初始化完成,不进行任务调度*/
|
||||
if(1 != pstSelf->ucInitStatus)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* 故障事件处理*/
|
||||
if(pstSelf->usFaultEnable)
|
||||
{
|
||||
usEventSendNum = pstSelf->pfnGetEvent_SendNum(pstSelf->pUsrData);
|
||||
|
||||
if(usEventSendNum)
|
||||
{
|
||||
if(usEventSendNum != pstSelf->usEventSendNoAckNum)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_FaultSoe, COT_SPONT, 0); // 第一次重启补发SOE
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->usEventSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查数据池中电度待发送数量
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CheckTimeDd_SendInfo(CS10xHandle_t pstSelf)
|
||||
{
|
||||
unsigned short usTimeDdSendNum = 0;
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(NULL == pstSelf->pfnGetTimeDdu_SendNum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* 链路未初始化完成,不进行任务调度*/
|
||||
if(1 != pstSelf->ucInitStatus)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* 电度数据处理*/
|
||||
usTimeDdSendNum = pstSelf->pfnGetTimeDdu_SendNum(pstSelf->pUsrData);
|
||||
|
||||
if(usTimeDdSendNum)
|
||||
{
|
||||
if(usTimeDdSendNum != pstSelf->usDduSendNoAckNum)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_DdTimeData, COT_SPONT, 0); // 第一次重启补发SOE
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->usDduSendNoAckNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 检查数据池中扰动遥测待发送数量
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CheckDiturbYc_SendInfo(CS10xHandle_t pstSelf)
|
||||
{
|
||||
unsigned short usDiturbYcSendNum = 0;
|
||||
|
||||
if(pstSelf->eCS10x_Type == CS104_TYPE_M || pstSelf->eCS10x_Type == CS101_TYPE_M) //作为主站时直接返回
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(NULL == pstSelf->pfnGetDiturbYc_SendNum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
usDiturbYcSendNum = pstSelf->pfnGetDiturbYc_SendNum(pstSelf->pUsrData); //获取数据表中待发的数量
|
||||
|
||||
if(usDiturbYcSendNum)
|
||||
{
|
||||
/*未初始化完成,直接清空缓冲*/
|
||||
if((0 == pstSelf->ucInitStatus) && (NULL != pstSelf->pfnUpdata_DiturbYc_Pout))
|
||||
{
|
||||
pstSelf->pfnUpdata_DiturbYc_Pout(pstSelf->pUsrData, usDiturbYcSendNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_YcDisturb, COT_SPONT, 0); //正常发送扰动遥测
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查是否有读取任务
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void PollFileTransTask(CS10xHandle_t pstSelf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(NULL == pstSelf->pfnCheckTransFileObj ||
|
||||
NULL == pstSelf->pfnCheckTransTimeOut)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
if(GetTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink)
|
||||
|| pstSelf->bContinueSendFlag == false)
|
||||
{
|
||||
//IEC_PRINT("主模式下, 存在U帧激活任务, 直接返回\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
if(pstSelf->ucTransStatus != FILE_ST_IDLE) //主模式每次传输目录/文件完成, 置位传输状态
|
||||
{
|
||||
ret = pstSelf->pfnCheckTransTimeOut(pstSelf->pUsrData);
|
||||
|
||||
if(ret < 0)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstSelf->ucTransStatus = FILE_ST_IDLE;
|
||||
ClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FilePro);// 直接清空上次文件传输任务
|
||||
}
|
||||
}
|
||||
|
||||
ret = pstSelf->pfnCheckTransFileObj(&pstSelf->stRdSet, pstSelf->pUsrData);
|
||||
|
||||
if(ret == TRANS_DIR)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_FilePro, FILE_ST_RD_DIR, 0);
|
||||
pstSelf->ucTransStatus = FILE_ST_RD_DIR;
|
||||
}
|
||||
else if(ret == TRANS_FILE)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_FilePro, FILE_ST_RD_FILE_ACT, 0);
|
||||
pstSelf->ucTransStatus = FILE_ST_RD_FILE_ACT;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置M端对S端初始化后总召及对时处理
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void CS10x_M_Scheduled(CS10xHandle_t pstSelf, unsigned short usGap)
|
||||
{
|
||||
if(CS104_TYPE_M == pstSelf->eCS10x_Type || CS101_TYPE_M == pstSelf->eCS10x_Type) //主站
|
||||
{
|
||||
if(pstSelf->uiSummon_Gap) //总召间隔
|
||||
{
|
||||
pstSelf->uiSummon_Tcn += usGap;
|
||||
|
||||
if(pstSelf->uiSummon_Tcn >= pstSelf->uiSummon_Gap)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
|
||||
pstSelf->uiSummon_Tcn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->uiESummon_Gap) //总召间隔
|
||||
{
|
||||
pstSelf->uiESummon_Tcn += usGap;
|
||||
|
||||
if(pstSelf->uiESummon_Tcn >= pstSelf->uiESummon_Gap)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_DdSummon, COT_ACT, 0);
|
||||
pstSelf->uiESummon_Tcn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->uiSyn_Gap) //同步间隔
|
||||
{
|
||||
pstSelf->uiTimeSyn_Tcn += usGap;
|
||||
|
||||
if(pstSelf->uiTimeSyn_Tcn >= pstSelf->uiSyn_Gap)
|
||||
{
|
||||
pstSelf->uiTimeSyn_Tcn = 0;
|
||||
SetSendTask(pstSelf, TSKID_TimeSyn, COT_ACT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(pstSelf->pfnPollFileTransTask != NULL)
|
||||
{
|
||||
pstSelf->pfnPollFileTransTask(pstSelf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查从站总召延迟计数,延迟到期后触发遥信/遥测上送
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[in] usGap-本次定时器间隔(ms)
|
||||
* @return 无
|
||||
*/
|
||||
void CheckSummonSlaveDelay(CS10xHandle_t pstSelf, unsigned short usGap)
|
||||
{
|
||||
if(pstSelf->uiSummonSlaveDelayRemain == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(pstSelf->uiSummonSlaveDelayRemain > usGap)
|
||||
{
|
||||
pstSelf->uiSummonSlaveDelayRemain -= usGap;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 延迟时间到,触发遥信上送 */
|
||||
pstSelf->uiSummonSlaveDelayRemain = 0;
|
||||
SetSendTask(pstSelf, TSKID_SummonYx, COT_INTROGEN, pstSelf->ucSummonSlaveQoi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 接收到初始化完成标识
|
||||
* @return 无
|
||||
*/
|
||||
void CS10x_M_Finish(CS10xHandle_t pstSelf)
|
||||
{
|
||||
pstSelf->ucInitStatus = 1;
|
||||
|
||||
/*101主站模式*/
|
||||
if(CS101_TYPE_M == pstSelf->eCS10x_Type) //主站
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
|
||||
pstSelf->ucInitStatus = 1;
|
||||
pstSelf->uiInit_Tcn = 0;
|
||||
pstSelf->uiInit_Resend_Ncn = 0;
|
||||
pstSelf->ucRxLinkStatusFlag = 0;
|
||||
pstSelf->ucRxLinkRequestFlag = 0;
|
||||
pstSelf->ucRxAckFlag = 0;
|
||||
pstSelf->ucRxLinkResetFlag = 0;
|
||||
}
|
||||
else if(CS104_TYPE_M == pstSelf->eCS10x_Type)
|
||||
{
|
||||
SetSendTask(pstSelf, TSKID_SummonResponse, COT_ACT, 0);
|
||||
pstSelf->ucInitStatus = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************内部函数*******************************/
|
||||
|
|
@ -0,0 +1,788 @@
|
|||
/******************************************************************************
|
||||
|
||||
版权所有 (C), 2013-2023, 科大智能电气有限公司
|
||||
|
||||
******************************************************************************
|
||||
文 件 名 : lib60870_public.c
|
||||
版 本 号 : V1.0
|
||||
生成日期 : 2022年04月07日
|
||||
最近修改 :
|
||||
功能描述 : 101及104规约实现中的任务管理及校验等功能
|
||||
函数列表 :
|
||||
修改历史 :
|
||||
1.日 期 : 2022年04月07日
|
||||
修改内容 : 创建文件
|
||||
*******************************************************************************/
|
||||
/*************************************文件包含*********************************/
|
||||
#include "lib60870_public.h"
|
||||
|
||||
/***************************************数据定义*******************************/
|
||||
|
||||
/*************************************外部接口函数*****************************/
|
||||
/**
|
||||
* @brief 规约发送任务调度
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[out] 无
|
||||
* @return 任务执行结果
|
||||
*/
|
||||
unsigned char CS10x_SendTask(CS10xHandle_t pstSelf)
|
||||
{
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ReSend)) //重发标识
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ReSend;
|
||||
return RESEND_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_Anomaly)) //异常帧
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_Anomaly;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_Ack)) //回复应答帧
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_Ack;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_RequestLink)) // 101规约请求链路状态
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_RequestLink;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ResetLink)) // 101规约重置链路
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ResetLink;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_MResponse)) // 101规约链路状态回复帧
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_MResponse;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_HeartBeat)) // 101规约心跳
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_HeartBeat;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_StartLink)) // 104规约启动链路
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_StartLink;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_StopLink)) // 104规约断开链路
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_StopLink;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_UTest)) // 104规约U帧TEST
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_UTest;
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
/*规约不允许发送长帧,则直接返回*/
|
||||
if(CS104_TYPE_S == pstSelf->eCS10x_Type || CS104_TYPE_M == pstSelf->eCS10x_Type)
|
||||
{
|
||||
if(false == pstSelf->bContinueSendFlag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pstSelf->uiResend_Tcn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*初始化完成*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_InitFinish))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_InitFinish;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*遥控命令报文*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_YkProcess))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_YkProcess;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*COS信息*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SendCOS))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_SendCOS;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*事件顺序记录 SOE*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SendSOE))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_SendSOE;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/* 总招遥信响应遥信 */
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SummonYx))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_SummonYx;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/* 总招遥测响应遥测 */
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SummonYc))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_SummonYc;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*总召响应*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_SummonResponse))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_SummonResponse;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/* 故障事件 */
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FaultSoe))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_FaultSoe;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*时钟同步报文*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_TimeSyn))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_TimeSyn;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*扰动数据*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_YcDisturb))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_YcDisturb;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*延时获得命令*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ObtainDelay))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ObtainDelay;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*复位进程*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ResetProcess))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ResetProcess;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*文件数据响应*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_FilePro))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_FilePro;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*电能量数据发送*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DdData))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_DdData;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*总召电能量*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DdSummon))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_DdSummon;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*总召电能量*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DdTimeData))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_DdTimeData;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*修改参数定值区*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ChgConst))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ChgConst;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*读取参数定值区*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ReadConst))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ReadConst;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*读取定值参数*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamPreread))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamPreread;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*读取定值参数-南网*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamRead_NanWang))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamRead_NanWang;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*设置定值参数*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamPrewrite))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamPrewrite;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*写参数定值-南网(类型标识 55)*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamWrite_NanWang))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamWrite_NanWang;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*读定值参数响应传输-南网*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamReadResponse_NanWang))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamReadResponse_NanWang;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*参数预置-南网*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamPreset_NanWang))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamPreset_NanWang;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*固化定值参数-南网*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_ParamSolidify_NanWang))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_ParamSolidify_NanWang;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*启动升级*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_UpdateStart))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_UpdateStart;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*执行升级*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_UpdateExe))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_UpdateExe;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
/*长帧测试*/
|
||||
if(CheckClearTaskFlag(&pstSelf->stTaskFlags, TSKID_DataTest))
|
||||
{
|
||||
pstSelf->byTaskFlagId = TSKID_DataTest;
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 置规约发送任务接口函数
|
||||
* @param[in] pstSelf-规约实体指针
|
||||
* @param[in] uiFlagNo-任务ID
|
||||
* @param[in] usParam_low-传递参数低2字节,一般是指cot usParam_hig 传递参数高2字节 一般指报文尾部的限定词
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void SetSendTask(CS10xHandle_t pstSelf, unsigned int uiFlagNo, unsigned short usParam_low, unsigned short usParam_hig)
|
||||
{
|
||||
SetTaskFlag(&pstSelf->stTaskFlags, uiFlagNo);
|
||||
pstSelf->uiaTaskParam[uiFlagNo] = usParam_hig;
|
||||
pstSelf->uiaTaskParam[uiFlagNo] = (pstSelf->uiaTaskParam[uiFlagNo] << 16) + usParam_low;
|
||||
return;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* @brief SetTaskFlag
|
||||
设置标志,将pFlags缓冲区内的第FlagNo个位置位成1
|
||||
* @param[in] pstFlags 标志缓冲区首址
|
||||
uiFlagNo 标记号
|
||||
* @return
|
||||
***************************************************************/
|
||||
void SetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
|
||||
{
|
||||
unsigned int uiByteNo = 0; // FlagNo所处的字节号
|
||||
unsigned int uiBitNo = 0; // FlagNo在字节内所处的位号
|
||||
|
||||
if(uiFlagNo >= MAX_FLAGNO) //越界
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uiByteNo = uiFlagNo >> 3;
|
||||
uiBitNo = uiFlagNo & 0x7;
|
||||
// pstFlags->Flag[uiByteNo] |= aBitSelect[uiBitNo];
|
||||
pstFlags->ucFlag[uiByteNo] |= (1 << uiBitNo);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* @brief GetTaskFlag
|
||||
获取pFlags缓冲区内的第FlagNo个位置的状态位
|
||||
* @param[in] pstFlags 标志缓冲区首址
|
||||
uiFlagNo 标记号
|
||||
* @return 标志状态,1 有效,0 无效
|
||||
***************************************************************/
|
||||
unsigned int GetTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
|
||||
{
|
||||
// 设置每个模块的标志
|
||||
unsigned int uiByteNo = 0; // FlagNo所处的字节号
|
||||
unsigned int uiBitNo = 0; // FlagNo在字节内所处的位号
|
||||
unsigned char *pucFlag = (unsigned char *)pstFlags; //
|
||||
uiByteNo = uiFlagNo >> 3; //第5到8位
|
||||
uiBitNo = uiFlagNo & 7; //取低三位
|
||||
return (pucFlag[uiByteNo] & (1 << uiBitNo));
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* @brief ClearTaskFlag
|
||||
清除标志,将pFlags缓冲区内的第FlagNo个位置位成0
|
||||
* @param[in] pstFlags 标志缓冲区首址
|
||||
uiFlagNo 标记号
|
||||
* @return
|
||||
***************************************************************/
|
||||
void ClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
|
||||
{
|
||||
unsigned int uiByteNo = 0;
|
||||
unsigned int uiBitNo = 0;
|
||||
|
||||
if(uiFlagNo >= MAX_FLAGNO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uiByteNo = uiFlagNo >> 3;
|
||||
uiBitNo = uiFlagNo & 0x7;
|
||||
pstFlags->ucFlag[uiByteNo] &= ~(1 << uiBitNo);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* @brief CheckClearTaskFlag
|
||||
检查清除任务标志,若任务标志第dwFlagNo位有效,将其清除
|
||||
然后返回1,否则返回0
|
||||
* @param[in] pstFlags 标志缓冲区首址
|
||||
* uiFlagNo 标记号
|
||||
* @return 1 任务标志第uiFlagNo位有效
|
||||
0 任务标志第uiFlagNo位无效
|
||||
***************************************************************/
|
||||
int CheckClearTaskFlag(VFLAGS *pstFlags, unsigned int uiFlagNo)
|
||||
{
|
||||
if(!GetTaskFlag(pstFlags, uiFlagNo))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClearTaskFlag(pstFlags, uiFlagNo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除所有任务接口
|
||||
* @param[in] pstSelf
|
||||
* @param[out] 无
|
||||
* @return 无
|
||||
*/
|
||||
void ClearAllTaskflgs(CS10xHandle_t pstSelf)
|
||||
{
|
||||
pstSelf->stRecvBuf.usWritePtr = 0;
|
||||
pstSelf->stRecvBuf.usReadPtr = 0;
|
||||
pstSelf->stSendBuf.usWritePtr = 0;
|
||||
pstSelf->stSendBuf.usReadPtr = 0;
|
||||
memset(&pstSelf->stTaskFlags, 0, sizeof(VFLAGS)); //任务
|
||||
memset(pstSelf->uiaTaskParam, 0, MAX_FLAGNO * sizeof(unsigned short)); //任务参数
|
||||
pstSelf->byTaskFlagId = 0;
|
||||
pstSelf->ucInitStatus = 0; // 初始化完成状态
|
||||
pstSelf->ucFirstAct = 0;
|
||||
pstSelf->uiFrameTmCnt = 0;
|
||||
pstSelf->uiHeart_Tcn = 0;
|
||||
pstSelf->uiSummon_Tcn = 0;
|
||||
pstSelf->uiESummon_Tcn = 0;
|
||||
pstSelf->uiTimeSyn_Tcn = 0;
|
||||
pstSelf->usYxSendNum = 0;
|
||||
pstSelf->usYcSendNum = 0;
|
||||
pstSelf->usDisTurbYcSendNum = 0;
|
||||
pstSelf->usDdSendNum = 0;
|
||||
pstSelf->usSoeSendNum = 0;
|
||||
pstSelf->usSoeSendNoAckNum = 0; /*Soe发送未确认数量*/
|
||||
pstSelf->usCosSendNoAckNum = 0;
|
||||
pstSelf->usEventSendNoAckNum = 0; /*事件发送未确认数量*/
|
||||
pstSelf->usDduSendNoAckNum = 0;
|
||||
pstSelf->usDiturbYcSendNoAckNum = 0;
|
||||
pstSelf->usSoeSendSetup = 0;
|
||||
pstSelf->usDdSummonSetup = 0;
|
||||
pstSelf->ucParamFlag = 0;
|
||||
pstSelf->usParamSendNum = 0;
|
||||
pstSelf->ucPmPresetFlag = 0;
|
||||
pstSelf->uiPmPresetTimeout = 0;
|
||||
pstSelf->ucTransStatus = 0;
|
||||
pstSelf->uiTransTimerCur = 0;
|
||||
pstSelf->uiTransTimerMax = 0;
|
||||
pstSelf->bContinueSendFlag = 0;
|
||||
pstSelf->ucInitStep = 0;
|
||||
pstSelf->ucSelf_FCB = 0;
|
||||
pstSelf->ucRxAckFlag = 0;
|
||||
pstSelf->ucRxLinkStatusFlag = 0;
|
||||
pstSelf->ucRxLinkRequestFlag = 0;
|
||||
pstSelf->ucRxLinkResetFlag = 0;
|
||||
pstSelf->ucRxInitFinishFlag = 0;
|
||||
pstSelf->ucHeart_Resend_Flag = 0;
|
||||
pstSelf->ucFileTransFrame = 0;
|
||||
pstSelf->usFileNoneAckNum = 0;
|
||||
pstSelf->usResend_Ncn = 0;
|
||||
pstSelf->uiResend_Tcn = 0;
|
||||
pstSelf->uiRelink_Tcn = 0;
|
||||
pstSelf->uiInit_Tcn = 0;
|
||||
pstSelf->uiReInit_Tcn = 0;
|
||||
pstSelf->uiInit_Resend_Ncn = 0;
|
||||
pstSelf->usSendNum = 0; /*Send Counter */
|
||||
pstSelf->usRecvNum = 0; /*Receive Counter*/
|
||||
pstSelf->usAckSendNum = 0; /*Receive Ack Counter*/
|
||||
pstSelf->usAckRecvNum = 0; /*Have Ack Receive Counter*/
|
||||
pstSelf->stM_vTimer[0].bRun = 0;
|
||||
pstSelf->stM_vTimer[1].bRun = 0;
|
||||
pstSelf->stM_vTimer[2].bRun = 0;
|
||||
pstSelf->stM_vTimer[3].bRun = 0;
|
||||
pstSelf->uiSummonSlaveDelayRemain = 0;
|
||||
pstSelf->ucSummonSlaveQoi = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 8位校验和计算函数
|
||||
* @param[in] pucBuf-数据指针
|
||||
* @param[in] ucLen-数据长度
|
||||
* @param[out] 无
|
||||
* @return 校验和
|
||||
*/
|
||||
unsigned char checksum_8(unsigned char *pucBuf, unsigned char ucLen)
|
||||
{
|
||||
unsigned char ucSum = 0;
|
||||
unsigned char uci = 0;
|
||||
|
||||
for(uci = 0; uci < ucLen; uci++)
|
||||
{
|
||||
ucSum += pucBuf[uci];
|
||||
}
|
||||
|
||||
ucSum = ucSum & 0xff;
|
||||
return ucSum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check比对Tag类型与长度关系
|
||||
*
|
||||
* @param ucTag
|
||||
* @param ucLen
|
||||
* @return int
|
||||
*/
|
||||
int CheckParamTagAndLen(unsigned char ucTag, unsigned char ucLen)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
switch(ucTag)
|
||||
{
|
||||
case TAG_TPYE_BOOL:
|
||||
case TAG_TPYE_TINY:
|
||||
case TAG_TPYE_UTINY:
|
||||
if(ucLen != 1)
|
||||
{
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TAG_TPYE_SHORT:
|
||||
case TAG_TPYE_USHORT:
|
||||
if(ucLen != 2)
|
||||
{
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TAG_TPYE_INT:
|
||||
case TAG_TPYE_UINT:
|
||||
case TAG_TPYE_FLOAT:
|
||||
if(ucLen != 4)
|
||||
{
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TAG_TPYE_LONG:
|
||||
case TAG_TPYE_ULONG:
|
||||
case TAG_TPYE_DOUBLE:
|
||||
if(ucLen != 8)
|
||||
{
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TAG_TPYE_STR:
|
||||
if(ucLen > 64)
|
||||
{
|
||||
bResult = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
bResult = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : CP56Time2a_Pack2Buf
|
||||
* Description : 打包Cp56时间到缓冲
|
||||
* @param[in] : unsigned char *pucOutBuf
|
||||
* @param[in] : const __CP56Time2a *pstCp56
|
||||
* @param[out] : None
|
||||
* @Return :
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/6
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned char CP56Time2a_Pack2Buf(unsigned char *pucOutBuf, const __CP56Time2a *pstCp56)
|
||||
{
|
||||
if(NULL == pstCp56)
|
||||
{
|
||||
memset(pucOutBuf, 0, 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
pucOutBuf[0] = pstCp56->ucLMs;
|
||||
pucOutBuf[1] = pstCp56->ucHMs;
|
||||
pucOutBuf[2] = pstCp56->ucMin;
|
||||
pucOutBuf[3] = pstCp56->ucHour;
|
||||
pucOutBuf[4] = pstCp56->ucWeek;
|
||||
pucOutBuf[5] = pstCp56->ucMonth;
|
||||
pucOutBuf[6] = pstCp56->ucYear;
|
||||
}
|
||||
|
||||
return 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : CP56Time2a_GetFromBuf
|
||||
* Description : 从缓冲解析Cp56时间
|
||||
* @param[in] : const unsigned char *pucInBuf
|
||||
* @param[in] : __CP56Time2a *pstCp56
|
||||
* @param[out] : None
|
||||
* @Return : 0=失败 1=成功
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/6
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned char CP56Time2a_GetFromBuf(const unsigned char *pucInBuf, __CP56Time2a *pstCp56)
|
||||
{
|
||||
if(NULL == pstCp56)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pstCp56->ucLMs = pucInBuf[0];
|
||||
pstCp56->ucHMs = pucInBuf[1];
|
||||
pstCp56->ucMin = pucInBuf[2];
|
||||
pstCp56->ucHour = pucInBuf[3];
|
||||
pstCp56->ucWeek = pucInBuf[4];
|
||||
pstCp56->ucMonth = pucInBuf[5];
|
||||
pstCp56->ucYear = pucInBuf[6];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : IntBytes_Pack2Buf
|
||||
* Description : 按字节数打包Int数据
|
||||
* @param[in] : unsigned char *pucOutBuf
|
||||
* @param[in] : unsigned int uiVal
|
||||
* @param[in] : unsigned char ucSize
|
||||
* @param[out] : None
|
||||
* @Return : 封装字节数量
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/6
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned char IntBytes_Pack2Buf(unsigned char *pucOutBuf, unsigned int uiVal, unsigned char ucSize)
|
||||
{
|
||||
if(0 == ucSize || ucSize > 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(unsigned char i = 0; i < ucSize; i++)
|
||||
{
|
||||
pucOutBuf[i] = uiVal;
|
||||
uiVal >>= 8;
|
||||
}
|
||||
|
||||
return ucSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : IntBytes_GetFromBuf
|
||||
* Description : 按照字节大小从缓冲中获取Int数据
|
||||
* @param[in] : const unsigned char *pucInBuf
|
||||
* @param[in] : unsigned char ucSize
|
||||
* @param[out] : None
|
||||
* @Return :
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/6
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned int IntBytes_GetFromBuf(const unsigned char *pucInBuf, unsigned char ucSize)
|
||||
{
|
||||
unsigned int uiVal = 0;
|
||||
|
||||
if(0 == ucSize || ucSize > 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(unsigned char i = 0; i < ucSize; i++)
|
||||
{
|
||||
uiVal |= ((unsigned int)pucInBuf[i] << (i * 8));
|
||||
}
|
||||
|
||||
return uiVal;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : Float_Pack2Buf
|
||||
* Description : 打包浮点数到缓冲
|
||||
* @param[in] : unsigned char *pucOutBuf
|
||||
* @param[in] : float fVal
|
||||
* @param[out] : None
|
||||
* @Return :
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/12
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned char Float_Pack2Buf(unsigned char *pucOutBuf, float fVal)
|
||||
{
|
||||
memcpy(pucOutBuf, &fVal, 4);
|
||||
return 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : Float_GetFromBuf
|
||||
* Description : 缓冲获取浮点数
|
||||
* @param[in] : const unsigned char *pucInBuf
|
||||
* @param[out] : None
|
||||
* @Return :
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/12
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
float Float_GetFromBuf(const unsigned char *pucInBuf)
|
||||
{
|
||||
float fVal = 0;
|
||||
memcpy(&fVal, pucInBuf, 4);
|
||||
return fVal;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : U16_Pack2Buf
|
||||
* Description : 打包无符号短整型到缓冲
|
||||
* @param[in] : unsigned char *pucOutBuf
|
||||
* @param[in] : unsigned short usVal
|
||||
* @param[out] : None
|
||||
* @Return :
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/12
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned char U16_Pack2Buf(unsigned char *pucOutBuf, unsigned short usVal)
|
||||
{
|
||||
memcpy(pucOutBuf, &usVal, 2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prototype : U16_GetFromBuf
|
||||
* Description : 从缓冲获取无符号短整型
|
||||
* @param[in] : const unsigned char *pucInBuf
|
||||
* @param[out] : None
|
||||
* @Return :
|
||||
*
|
||||
*
|
||||
*
|
||||
* History :
|
||||
* 1.Date : 2023/6/12
|
||||
* Author : wqw
|
||||
* Modification : Created function
|
||||
*
|
||||
*/
|
||||
unsigned short U16_GetFromBuf(const unsigned char *pucInBuf)
|
||||
{
|
||||
unsigned short usVal = 0;
|
||||
memcpy(&usVal, pucInBuf, 2);
|
||||
return usVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************内部函数*******************************/
|
||||
|
|
@ -0,0 +1,347 @@
|
|||
//#include<iostream>
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
#include<math.h>
|
||||
#include<ctype.h>
|
||||
#include "md5.h"
|
||||
|
||||
static void MD5Transform PROTO_LIST((UINT4 [4], unsigned char [64]));
|
||||
static void MD5_memcpy PROTO_LIST((POINTER, POINTER, unsigned int));
|
||||
static void MD5_memset PROTO_LIST((POINTER, int, unsigned int));
|
||||
static void MD5Init PROTO_LIST((MD5_CTX *));
|
||||
static void MD5Update PROTO_LIST((MD5_CTX *, unsigned char *, unsigned int));
|
||||
static void MD5Final PROTO_LIST((unsigned char [16], MD5_CTX *));
|
||||
static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int));
|
||||
static void Decode PROTO_LIST((UINT4 *, unsigned char *, unsigned int));
|
||||
|
||||
static unsigned char PADDING[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static void MD5Init(MD5_CTX *context)
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
static void MD5Update(
|
||||
MD5_CTX *context, /* context */
|
||||
unsigned char *input, /* input block */
|
||||
unsigned int inputLen /* length of input block */
|
||||
)
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
if((context->count[0] += ((UINT4)inputLen << 3))
|
||||
< ((UINT4)inputLen << 3))
|
||||
{
|
||||
context->count[1]++;
|
||||
}
|
||||
|
||||
context->count[1] += ((UINT4)inputLen >> 29);
|
||||
partLen = 64 - index;
|
||||
|
||||
if(inputLen >= partLen)
|
||||
{
|
||||
MD5_memcpy
|
||||
((POINTER)&context->buffer[index], (POINTER)input, partLen);
|
||||
MD5Transform(context->state, context->buffer);
|
||||
|
||||
for(i = partLen; i + 63 < inputLen; i += 64)
|
||||
{
|
||||
MD5Transform(context->state, &input[i]);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
MD5_memcpy
|
||||
((POINTER)&context->buffer[index], (POINTER)&input[i],
|
||||
inputLen - i);
|
||||
}
|
||||
|
||||
static void MD5Final(
|
||||
unsigned char digest[16], /* message digest */
|
||||
MD5_CTX *context /* context */
|
||||
)
|
||||
{
|
||||
unsigned char bits[8] = {0};
|
||||
unsigned int index = 0, padLen = 0;
|
||||
Encode(bits, context->count, 8);
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD5Update(context, PADDING, padLen);
|
||||
MD5Update(context, bits, 8);
|
||||
Encode(digest, context->state, 16);
|
||||
MD5_memset((POINTER)context, 0, sizeof(*context));
|
||||
}
|
||||
|
||||
static void MD5Transform(
|
||||
UINT4 state[4],
|
||||
unsigned char block[64]
|
||||
)
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
Decode(x, block, 64);
|
||||
/* Round 1 */
|
||||
FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
/* Round 2 */
|
||||
GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
/* Round 3 */
|
||||
HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
/* Round 4 */
|
||||
II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
MD5_memset((POINTER)x, 0, sizeof(x));
|
||||
}
|
||||
|
||||
static void Encode(
|
||||
unsigned char *output,
|
||||
UINT4 *input,
|
||||
unsigned int len
|
||||
)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for(i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
static void Decode(
|
||||
UINT4 *output,
|
||||
unsigned char *input,
|
||||
unsigned int len
|
||||
)
|
||||
{
|
||||
unsigned int i = 0, j = 0;
|
||||
|
||||
for(i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4)input[j]) | (((UINT4)input[j + 1]) << 8) |
|
||||
(((UINT4)input[j + 2]) << 16) | (((UINT4)input[j + 3]) << 24);
|
||||
}
|
||||
|
||||
static void MD5_memcpy(
|
||||
POINTER output,
|
||||
POINTER input,
|
||||
unsigned int len
|
||||
)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
output[i] = input[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void MD5_memset(
|
||||
POINTER output,
|
||||
int value,
|
||||
unsigned int len
|
||||
)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
((char *)output)[i] = (char)value;
|
||||
}
|
||||
}
|
||||
|
||||
void StartMD5(MD5_CTX *context)
|
||||
{
|
||||
MD5Init(context);
|
||||
}
|
||||
|
||||
void EncodeMD5(MD5_CTX *context, unsigned char *input, int len)
|
||||
{
|
||||
MD5Update(context, input, len);
|
||||
}
|
||||
|
||||
void GetMD5(MD5_CTX *context, unsigned char *result)
|
||||
{
|
||||
if(result == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MD5Final(result, context);
|
||||
}
|
||||
|
||||
void GetMD5String(MD5_CTX *context, char *result, unsigned char mode)
|
||||
{
|
||||
unsigned char digest[16] = {0};
|
||||
char output1[33] = {0};
|
||||
|
||||
if(result == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MD5Final(digest, context);
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
sprintf(&(output1[2 * i]), "%02x", (unsigned char)digest[i]);
|
||||
sprintf(&(output1[2 * i + 1]), "%02x", (unsigned char)(digest[i] << 4));
|
||||
}
|
||||
|
||||
if(mode == MD5_BIT32)
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
result[i] = output1[i];
|
||||
}
|
||||
else if(mode == MD5_BIT16)
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
result[i] = output1[8 + i];
|
||||
}
|
||||
}
|
||||
|
||||
/* ²âÊÔÓà */
|
||||
#if 0
|
||||
char *MD5String(char *string)
|
||||
{
|
||||
MD5_CTX context = {0};
|
||||
unsigned char digest[16] = {0};
|
||||
char output1[33] = {0};
|
||||
static char output[33] = {""};
|
||||
unsigned int len = strlen(string);
|
||||
int i = 0;
|
||||
MD5Init(&context);
|
||||
MD5Update(&context, (unsigned char *)string, len);
|
||||
MD5Final(digest, &context);
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
sprintf(&(output1[2 * i]), "%02x", (unsigned char)digest[i]);
|
||||
sprintf(&(output1[2 * i + 1]), "%02x", (unsigned char)(digest[i] << 4));
|
||||
}
|
||||
|
||||
for(i = 0; i < 32; i++)
|
||||
{
|
||||
output[i] = output1[i];
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static void StringAddOne(char *orstring)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
int i = 0, n = 0;
|
||||
len = strlen(orstring);
|
||||
n = len - 1;
|
||||
|
||||
for(i = n; i >= 0; i--)
|
||||
{
|
||||
if(orstring[i] == '9')
|
||||
{
|
||||
orstring[i] = 'A';
|
||||
break;
|
||||
}
|
||||
else if(orstring[i] == 'Z')
|
||||
{
|
||||
orstring[i] = 'a';
|
||||
break;
|
||||
}
|
||||
else if(orstring[i] == 'z')
|
||||
{
|
||||
orstring[i] = '0';
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
orstring[i] += 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MD5Check(char *md5string, char *string)
|
||||
{
|
||||
return strcmp(md5string, MD5String(string)) == 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue