📄 dnpsec.c
字号:
#include "includes.h"
//OS_FLAG_GRP *DnpFlag;
OS_FLAGS value;
extern struct DBConfig *DBCfgs;
extern struct SysPort *pp1;
extern struct SysPort *pp2;
UCHAR cur_frame[PORTNUM]; /*发送帧队列当前帧和帧总数,考虑长包发送*/
UCHAR max_frame[PORTNUM];
UCHAR mFCB[PORTNUM]; /*避免副方接收重复帧(链路层)*/
UCHAR sFCB[PORTNUM];
BOOL DL_reset[PORTNUM]; /*本机复位标志*/
UCHAR THcount[PORTNUM];
UCHAR Sequence[PORTNUM]; /*应用层段号*/
USHORT m_wIIN[PORTNUM];
//USHORT iinMask[PORTNUM]; /*IIN屏蔽字*/
UCHAR bsending[PORTNUM]; /*正传送的数据类型, 用于应用层确认*/
struct DnpPadPara* DnpSecPadPara[PORTNUM];
struct DBInfo DnpSoeinfo[PORTNUM],DnpCosinfo[PORTNUM];
stIFrame *DnpCom1,*DnpCom2;
stIFrame *dliCom1[9],*dliCom2[9];
stOFrame *dloCom1[9],*dloCom2[9];
stOFrame *ploCom1,*ploCom2;
stIPacket *aliCom1,*aliCom2;
stOPacket *aloCom1,*aloCom2;
SoeReadPoint *SoeReadCom1,*SoeReadCom2;
VarYcValue *VarYcValueStruct[PORTNUM];
INT16U *YCDValue[PORTNUM];
BOOL ValueFlag[PORTNUM];
INT8U *YC_Value[PORTNUM];
INT8U *YX_Value[PORTNUM];
extern INT8U SwitchCounter, SwitchCounter2;
BOOL TimeFlag = FALSE; //非广播对钟
BOOL InitDnpSecLink(INT8U Port, struct PortAppInfo* PortCfg)
{
INT8U i;
INT16U tmp;
struct PSecDnpPad *pPad;
i = Port - 1;
pPad = (struct PSecDnpPad*)(PortCfg->pPad);
if (pPad != NULL)
{
tmp = pPad->PBase.CmdControl;
if(tmp&DnpSecEnableYk)
DnpSecPadPara[i]->EnYk = TRUE;
else
DnpSecPadPara[i]->EnYk = FALSE;
if(tmp&DnpSecEnableClock)
DnpSecPadPara[i]->EnClock = TRUE;
else
DnpSecPadPara[i]->EnClock = FALSE;
if(tmp&DnpSecEnableAllData)
DnpSecPadPara[i]->EnAllData = TRUE;
else
DnpSecPadPara[i]->EnAllData = FALSE;
if(tmp&DnpSecEnableDD)
DnpSecPadPara[i]->EnDD = TRUE;
else
DnpSecPadPara[i]->EnDD = FALSE;
DnpSecPadPara[i]->AIDeadValue = pPad->PBase.AIDeadValue;
DnpSecPadPara[i]->AllData = pPad->PBase.Timer.AllData;
DnpSecPadPara[i]->DdTime = pPad->PBase.Timer.Counter;
DnpSecPadPara[i]->DlDelay = pPad->PBase.Timer.CtrlTimeOut;
DnpSecPadPara[i]->ScanData2 = pPad->PBase.Timer.ScanData2;
DnpSecPadPara[i]->AlDelay = pPad->PBase.Timer.TimeoutValue1;
DnpSecPadPara[i]->Class1Data = pPad->Class1Data;
DnpSecPadPara[i]->Class2Data = pPad->Class2Data;
DnpSecPadPara[i]->Class3Data = pPad->Class3Data;
}
else
{
DnpSecPadPara[i]->EnYk = DnpYkEn;
DnpSecPadPara[i]->EnClock = DnpClockEn;
DnpSecPadPara[i]->EnAllData = DnpAllDataEn;
DnpSecPadPara[i]->EnDD = DnpDdEn;
DnpSecPadPara[i]->AIDeadValue = DnpAIDeadValue;
DnpSecPadPara[i]->AllData = DnpAllData;
DnpSecPadPara[i]->DdTime = DnpDdTime;
DnpSecPadPara[i]->DlDelay = DnpDlDelay;
DnpSecPadPara[i]->ScanData2 = DnpScanData2;
DnpSecPadPara[i]->AlDelay = DnpAlDelay;
DnpSecPadPara[i]->Class1Data = DnpClass1Data;
DnpSecPadPara[i]->Class2Data = DnpClass2Data;
DnpSecPadPara[i]->Class3Data = DnpClass3Data;
}
return TRUE;
}
void DnpSecTask(struct SysPort *info, struct PortAppInfo* PortCfg)
{
INT8U i,err, tick;
INT16U events,j;
BOOL flag;
void *msg;
struct DBInfo Rinfo,YCDinfo;
INT16U *YCFullValue[PORTNUM];
tick = 0;
if(info->PortID == PORT1)
{
pp1 = info;
DnpCom1 = malloc(sizeof(stIFrame));
dliCom1[0] = malloc(sizeof(stIFrame)*9);
dloCom1[0] = malloc(sizeof(stOFrame)*9);
ploCom1 = malloc(sizeof(stOFrame));
aliCom1 = malloc(sizeof(stIFrame));
aloCom1 = malloc(sizeof(stIFrame));
SoeReadCom1 = malloc(sizeof(stIFrame));
Rinfo.Num = pp1->DBCfgs->YCNum; //用于变化遥测
VarYcValueStruct[0] = (VarYcValue*)malloc(sizeof(VarYcValue)*Rinfo.Num);
memset((char*)VarYcValueStruct[0],0,sizeof(VarYcValue)*Rinfo.Num);
YCFullValue[0] = malloc(Rinfo.Num*sizeof(INT16U));
memset((INT8U*)YCFullValue[0],0,sizeof(INT16U)*Rinfo.Num);
YCDValue[0] = malloc(Rinfo.Num*sizeof(INT16U));
memset((INT8U*)YCDValue[0],0,sizeof(INT16U)*Rinfo.Num);
YCDinfo.Type = YCFULLVAULE;
YCDinfo.Start = 0;
YCDinfo.SuperID = pp1->DBCfgs->DevID;
YCDinfo.DevID = pp1->DBCfgs->DevID;
YCDinfo.Num = pp1->DBCfgs->YCNum;
YC_Value[0] = malloc(sizeof(INT16U)*YCDinfo.Num);
memset((INT8U*)YC_Value[0],0,sizeof(INT16U)*YCDinfo.Num);
YX_Value[0] = malloc(pp1->DBCfgs->YXNum);
memset((INT8U*)YX_Value[0],0,pp1->DBCfgs->YXNum);
DBRead((INT8U*)YCFullValue[0], &YCDinfo);
}
else if(info->PortID == PORT2)
{
pp2 = info;
DnpCom2 = malloc(sizeof(stIFrame));
dliCom2[0] = malloc(sizeof(stIFrame)*9);
dloCom2[0] = malloc(sizeof(stOFrame)*9);
ploCom2 = malloc(sizeof(stOFrame));
aliCom2 = malloc(sizeof(stIFrame));
aloCom2 = malloc(sizeof(stIFrame));
SoeReadCom2 = malloc(sizeof(stIFrame));
Rinfo.Num = pp2->DBCfgs->YCNum; //用于变化遥测
VarYcValueStruct[1] = (VarYcValue*)malloc(sizeof(VarYcValue)*Rinfo.Num);
memset((char*)VarYcValueStruct[1],0,sizeof(VarYcValue)*Rinfo.Num);
YCFullValue[1] = malloc(Rinfo.Num*sizeof(INT16U));
memset((INT8U*)YCFullValue[1],0,sizeof(INT16U)*Rinfo.Num);
YCDValue[1] = malloc(Rinfo.Num*sizeof(INT16U));
memset((INT8U*)YCDValue[1],0,sizeof(INT16U)*Rinfo.Num);
YCDinfo.Type = YCFULLVAULE;
YCDinfo.Start = 0;
YCDinfo.SuperID = pp2->DBCfgs->DevID;
YCDinfo.DevID = pp2->DBCfgs->DevID;
YCDinfo.Num = pp2->DBCfgs->YCNum;
YC_Value[1] = malloc(sizeof(INT16U)*YCDinfo.Num);
memset((INT8U*)YC_Value[1],0,sizeof(INT16U)*YCDinfo.Num);
YX_Value[1] = malloc(pp2->DBCfgs->YXNum);
memset((INT8U*)YX_Value[1],0,pp2->DBCfgs->YXNum);
DBRead((INT8U*)YCFullValue[1], &YCDinfo);
}
i = info->PortID;
if (i > PORT2)
return ;
else
i -= 1;
DnpSecPadPara[i] = (void*) malloc (sizeof (struct DnpPadPara));
if(DnpSecPadPara[i] == NULL)
return ;
flag = InitDnpSecLink(i+1, PortCfg);
if(info->PortID == PORT1)
{
for(j=0;j<Rinfo.Num;j++)
{
*(YCDValue[0]+j) = *(YCFullValue[0]+j)*DnpSecPadPara[0]->AIDeadValue/1000;
}
free (YCFullValue[0]);
}
else if(info->PortID == PORT2)
{
for(j=0;j<Rinfo.Num;j++)
{
*(YCDValue[1]+j) = *(YCFullValue[1]+j)*DnpSecPadPara[1]->AIDeadValue/1000;
}
free (YCFullValue[1]);
}
for(j = 0;j < PORTNUM; j++)
{
cur_frame[j] = 0; /*发送帧队列当前帧和帧总数,考虑长包发送*/
max_frame[j] = 0;
mFCB[j] = 0; /*避免副方接收重复帧(链路层)*/
sFCB[j] = 0;
DL_reset[j] = 0; /*本机复位标志*/
THcount[j] = 0;
Sequence[j] = 0; /*应用层段号*/
m_wIIN[j] = 0;
bsending[j] = 0; /*正传送的数据类型, 用于应用层确认*/
}
while(1)
{
events = OSFlagPend(info->Event,RxdFrame+Dnp_Al_Ready+Dnp_Dl_Ready+FBOOP+FCOS+FSOE,OS_FLAG_WAIT_SET_ANY+OS_FLAG_CONSUME,0,&err);
if(events&FBOOP)
{
msg = OSQPend(info->CommQ, 0, &err);
if (err == OS_NO_ERR)
{
//AppSend(m_wIIN[i], AL_OG_YK, 22, (INT8U)info->PortID);
YkRespond(info, (struct DBBOOPInfo*)msg, (INT8U)info->PortID);
}
}
if(events&FSOE)
{
m_wIIN[i] |= AL_IIN_CLASS2;
}
if(events&FCOS)
{
m_wIIN[i] |= AL_IIN_CLASS1;
}
if(events&RxdFrame)
{
//规约切换
if (RReadx(info->DBCfgs->Address, info->PortID))
{
SwitchCounter++;
if (SwitchCounter >= 2)
{
SwitchCounter = 0;
SwitchCounter2 = 1;
}
}
if (SwitchCounter2)
{
if (SwitchCounter2++ > 10)
{
SwitchCounter2 = 0;
KillProg(RESET_DD, RESET_CLR, TRUE);
}
}
DnpOnRx((INT8U)info->PortID);
tick++;
if (tick >= 10)
{
tick = 0;
OnTick1s((INT8U)info->PortID);
}
}
if(events&Dnp_Al_Ready)
{
Send((INT8U)info->PortID);
}
if(events&Dnp_Dl_Ready)
{
ComFrame(info->PortID);
OnApp((INT8U)info->PortID);
}
}
}
/*------------------------------------------------------------------------
Procedure: DnpOnRx()
Purpose: 处理物理层准备好的数据,
Input:
Output:
Errors:
------------------------------------------------------------------------*/
int DnpOnRx(INT8U port)
{
stIFrame *p=NULL;
stIFrame *dli = NULL;
stOFrame *dlo = NULL;
stOFrame *plo = NULL;
stIPacket *ali = NULL;
stOPacket *alo = NULL;
if(port == COM1)
{
p= DnpCom1;
dli = dliCom1[0];
dlo = dloCom1[0];
plo = ploCom1;
ali = aliCom1;
alo = aloCom1;
}
else if(port == COM2)
{
p= DnpCom2;
dli = dliCom2[0];
dlo = dloCom2[0];
plo = ploCom2;
ali = aliCom2;
alo = aloCom2;
}
if(DnpFrame(port) < 0) return -1;
if (DlCheckSum(port) == 0) {
if ( (p->buf[3]&PRM_YES) == PRM_YES)
DL_Slave(port); /*作为副方站接收原方站报文*/
else
DL_Master(port); /*作为原方站接收副方站回答*/
return 0;
}
else return -2;
}
/*------------------------------------------------------------------------
Procedure: ComFrame
Purpose: 把接收的帧序列组合成数据包供应用层使用.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
int ComFrame(INT8U port)
{
UCHAR k, j, i, block, rem16;
stIFrame *p=NULL;
stIFrame *dli = NULL;
stOFrame *dlo = NULL;
stOFrame *plo = NULL;
stIPacket *ali = NULL;
stOPacket *alo = NULL;
if(port == COM1)
{
p= DnpCom1;
dli = dliCom1[0];
dlo = dloCom1[0];
plo = ploCom1;
ali = aliCom1;
alo = aloCom1;
}
else if(port == COM2)
{
p= DnpCom2;
dli = dliCom2[0];
dlo = dloCom2[0];
plo = ploCom2;
ali = aliCom2;
alo = aloCom2;
}
ali->count = 0;
ali->source = MERGE(dli[0].buf[7], dli[0].buf[6]);
ali->rec_time = dli[0].rec_time;
for(k=0; k<9; k++)
if(dli[k].ready) {
block = (dli[k].buf[2]-5)/16; rem16 = (dli[k].buf[2]-5)%16;
if(block == 0) {
for (i=0; i<rem16-1; i++)
ali->buf[ali->count+i] = dli[k].buf[11+i];
ali->count += rem16-1;
}
else {
for (i=0; i<15; i++)
ali->buf[ali->count+i] = dli[k].buf[11+i];
ali->count += 15;
for (j=1; j<block; j++) {
for (i=0; i<16; i++)
ali->buf[ali->count+i] = dli[k].buf[10+j*18+i];
ali->count += 16;
}
for(i=0; i<rem16; i++)
ali->buf[ali->count+i] = dli[k].buf[10+block*18+i];
ali->count +=rem16;
}
}
else break;
for(k=0; k<9; k++) dli[k].ready = FALSE;
ali->ready = TRUE;
return 0;
}
/*------------------------------------------------------------------------
Procedure: Send
Purpose: 发送应用层准备好的数据,
Input:
Output:
Errors:
------------------------------------------------------------------------*/
int Send(INT8U port)
{
stIFrame *p=NULL;
stIFrame *dli = NULL;
stOFrame *dlo = NULL;
stOFrame *plo = NULL;
stIPacket *ali = NULL;
stOPacket *alo = NULL;
if(port == COM1)
{
p = DnpCom1;
dli = dliCom1[0];
dlo = dloCom1[0];
plo = ploCom1;
ali = aliCom1;
alo = aloCom1;
}
else if(port == COM2)
{
p = DnpCom2;
dli = dliCom2[0];
dlo = dloCom2[0];
plo = ploCom2;
ali = aliCom2;
alo = aloCom2;
}
SplitPacket(port); /*OutPacket分割为OutFrame*/
cur_frame[port-1] = 0;
FillBuffer(Dnp_Al_Ready,port);
WriteX((INT8U*)plo->buf, plo->count,port); /*DlStartSend();*/
return 0;
}
/*------------------------------------------------------------------------
Procedure: CDNP::SplitPacket ID:1
Purpose: 将应用层的数据包分割为FT3帧序列.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void SplitPacket(INT8U port)
{
UCHAR k, i, j; USHORT CRC16;
UCHAR rem249, frame, TH[9], block, rem16, count[9],tempFCB;
stIFrame *p=NULL;
stIFrame *dli = NULL;
stOFrame *dlo = NULL;
stOFrame *plo = NULL;
stIPacket *ali = NULL;
stOPacket *alo = NULL;
if(port == COM1)
{
p = DnpCom1;
dli = dliCom1[0];
dlo = dloCom1[0];
plo = ploCom1;
ali = aliCom1;
alo = aloCom1;
}
else if(port == COM2)
{
p = DnpCom2;
dli = dliCom2[0];
dlo = dloCom2[0];
plo = ploCom2;
ali = aliCom2;
alo = aloCom2;
}
rem249 = ((alo->count)%249);
if(rem249 == 0) frame = alo->count/249;
else frame = alo->count/249 +1;
if(frame > 9) return;
if (frame == 1) TH[0]=0xC0; /*伪传输层控制字节(TH)*/
else {
TH[0]=0x40;
for(i=1; i<frame-1; i++) TH[i]=i;
TH[frame-1]=0x80+frame-1; }
/*记录每帧长度, 以便循环处理*/
if(rem249 != 0){ /*added on 2001.03.01*/
for(k=0; k<frame-1; k++) count[k] = 250;
count[frame-1] = rem249 + 1;
}
else {
for(k=0; k<frame; k++) count[k] = 250;
}
tempFCB = 0x20;
for(k=0; k<frame; k++){ /*实现链路层功能, 为每一帧构造FT3头和CRC校验*/
/*检查dlo[k]是否空闲???*/
dlo[k].buf[0] = 0x05; dlo[k].buf[1] = 0x64;
dlo[k].buf[2] = 5 + count[k];
switch (alo->service) { /*根据服务要求确定帧类型*/
case DL_SEND_CF:
dlo[k].buf[3] = DIR_OUT + PRM_YES + tempFCB+ FCV_YES + FUNC_DATA_ACK;
if(tempFCB==0x20) tempFCB=0;/*循环翻转FCB*/
else tempFCB=0x20;
break;
case DL_SEND_NOCF:
dlo[k].buf[3] = DIR_OUT + PRM_YES + FUNC_DATA_NACK;
break;
case DL_FAST_CF: break;
case DL_FAST_NOCF: break;
default: break;
}
dlo[k].buf[4] = LOW(alo->dest); dlo[k].buf[5] = HIGH(alo->dest);
if(port == PORT1)
{
dlo[k].buf[6] = LOW(pp1->DBCfgs->Address);
dlo[k].buf[7] = HIGH(pp1->DBCfgs->Address);
}
else
{
dlo[k].buf[6] = LOW(pp2->DBCfgs->Address);
dlo[k].buf[7] = HIGH(pp2->DBCfgs->Address);
}
CRC16 = dnpcrc((INT8U*)&dlo[k].buf[0], 8);
dlo[k].buf[8] = LOW(CRC16); dlo[k].buf[9] = HIGH(CRC16);
/*FT3头构造完成*/
block = count[k]/16; rem16 = count[k]%16;
dlo[k].buf[10] = TH[k]; /*伪传输层头*//*open on 2001.03.01*/
if(block == 0/*&& rem16>1*/) {
//dlo[k].buf[10] = TH[k]; /*2000.09.26*/
for(j=0; j<rem16-1; j++) /*-1:伪传输字节*/
dlo[k].buf[11+j] = alo->buf[j+249*k];
CRC16 = dnpcrc((INT8U*)&dlo[k].buf[10], rem16);
dlo[k].buf[10+rem16] = LOW(CRC16);
dlo[k].buf[10+rem16+1] = HIGH(CRC16);
}
else {
for(j=0; j<15; j++) dlo[k].buf[11+j] = alo->buf[j+249*k];
CRC16 = dnpcrc((INT8U*)&dlo[k].buf[10], 16);
dlo[k].buf[10+16] = LOW(CRC16);
dlo[k].buf[10+17] = HIGH(CRC16);
for(i=0; i<block-1; i++) {
for(j=0; j<16; j++)
dlo[k].buf[28+i*18+j] = alo->buf[15+i*16+j+249*k];
CRC16 = dnpcrc((INT8U*)&dlo[k].buf[28+i*18], 16);
dlo[k].buf[28+i*18+16] = LOW(CRC16);
dlo[k].buf[28+i*18+17] = HIGH(CRC16);
}
if(rem16>0){ /*2000.09.26*/
for(j=0; j<rem16; j++)
dlo[k].buf[10+block*18+j] = alo->buf[15+(block-1)*16+j+249*k];
CRC16 = dnpcrc((INT8U*)&(dlo[k].buf[10+block*18]), rem16);
dlo[k].buf[10+block*18+rem16] = LOW(CRC16);
dlo[k].buf[10+block*18+rem16+1] = HIGH(CRC16);
}
} /*CRC校验完成*/
/*2000.09.26*/
if(rem16>0) dlo[k].count = 10+block*18+rem16+2;
else dlo[k].count = 10+block*18;
dlo[k].ready = TRUE;
} /*for(k=0; k<=frame; k++)*/
max_frame[port-1] = frame; alo->ready = FALSE;
}
/*------------------------------------------------------------------------
Procedure: FillBuffer
Purpose: dli[]->p->???
Input:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -