📄 dnpsec.c
字号:
Output:
Errors:
------------------------------------------------------------------------*/
void FillBuffer(USHORT code,INT8U port)
{
USHORT i;
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;
}
for(i=0; i<dlo[cur_frame[port-1]].count; i++)
plo->buf[i] = dlo[cur_frame[port-1]].buf[i];
plo->count = dlo[cur_frame[port-1]].count;
plo->ready = TRUE;
if (alo->service == DL_SEND_NOCF) cur_frame[port-1]++;
}
/*------------------------------------------------------------------------
Procedure: DL_Master
Purpose: 作为原方站接收回答.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void DL_Master(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;
}
switch(p->buf[3]&0x0F) {
case FUNC_ACK:
HandleACK(port); break;
case FUNC_NACK:
Request(FUNC_RESET,port); /*子站要求*/
break;
case FUNC_POLL: break;
default: break;
}
p->ready = FALSE;
}
/*------------------------------------------------------------------------
Procedure: Request ID:1
Purpose: 链路层查询副方站辅助函数.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void Request(UCHAR func,INT8U port)
{
USHORT CRC16;
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;
}
plo->buf[0] = 0x05; plo->buf[1] = 0x64; plo->buf[2] = 5;
switch(func) {
case FUNC_RESET:
plo->buf[3] = PRM_YES + FCV_NO + FUNC_RESET;
break;
case FUNC_RESET_USER: break;
case FUNC_TEST: break;
default: break;
}
plo->buf[4] = p->buf[6]; plo->buf[5] = p->buf[7];
if(port == PORT1)
{
plo->buf[6] = LOW(pp1->DBCfgs->Address);
plo->buf[7] = HIGH(pp1->DBCfgs->Address);
}
else
{
plo->buf[6] = LOW(pp2->DBCfgs->Address);
plo->buf[7] = HIGH(pp2->DBCfgs->Address);
}
CRC16 = dnpcrc((INT8U*)&plo->buf[0], 8);
plo->buf[8] = LOW(CRC16); plo->buf[9] = HIGH(CRC16);
plo->count = 10; plo->ready = TRUE;
/*plo->retry_count = 1;*/
WriteX((INT8U*)plo->buf, plo->count,port); /*DlStartSend();*/
}
/*------------------------------------------------------------------------
Procedure: HandleACK
Purpose: 处理副方站的肯定回答帧(FTU作为原方站).
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void HandleACK(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;
}
switch(plo->buf[3]&0x0F) {
case FUNC_RESET:
mFCB[port-1] = 0x20; break;
case FUNC_RESET_USER: break;
case FUNC_TEST: break;
/*只有要求DL_SEND_CF, 才能得到子站的FUNC_DATA_ACK确认*/
case FUNC_DATA_ACK:
if(mFCB[port-1]==0x20) mFCB[port-1]=0; /*循环翻转FCB*/
else mFCB[port-1]=0x20;
break;
default: break;
}
}
/*------------------------------------------------------------------------
Procedure: DL_Slave
Purpose: 作为副方站接收原方站报文.
未复位之前不接收FCV置位的任何SEND_CONFIRM报文;
可以接收SEND_NO_CONFIRM报文
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void DL_Slave(INT8U port)
{
INT8U err;
USHORT i; UCHAR control;
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;
}
control = p->buf[3]; /*链路层控制字*/
switch(control & 0x0F){
case FUNC_RESET: /*需肯定的确认*/
DL_reset[port-1] = TRUE; sFCB[port-1] = 0x20; /*准备接收FCV=1, FCB=1帧*/
alo->ready = FALSE; ali->ready = FALSE;
plo->ready = FALSE; p->ready = FALSE;
cur_frame[port-1] = 0; max_frame[port-1] = 0;
for(i=0; i<9; i++) dlo[i].ready = FALSE;
for(i=0; i<9; i++) dli[i].ready = FALSE;
Reply(FUNC_ACK,port); /*肯定的确认*/
/*Request(FUNC_RESET);???*/
break;
case FUNC_RESET_USER: break;
case FUNC_TEST: break;
case FUNC_DATA_ACK: /*需确认的数据帧*/
if( DL_reset[port-1] && /*FCB相等或FCV为0*/
( (control&0x20)==sFCB[port-1] || (control&0x10)==0 ) ){
Reply(FUNC_ACK,port); /*肯定的确认*/
if(sFCB[port-1]==0x20) sFCB[port-1]=0; /*循环翻转FCB*/
else sFCB[port-1]=0x20;
/*若是该包的第一帧*/
if ((p->buf[10]&0x40)==0x40) THcount[port-1] = 0;
else THcount[port-1]++;
dli[THcount[port-1]].count = p->count;
dli[THcount[port-1]].ready = TRUE;
dli[THcount[port-1]].rec_time = p->rec_time;
for(i=0; i<p->count; i++)
dli[THcount[port-1]].buf[i] = p->buf[i];
/*若是该包的最后一帧*/
if ((p->buf[10]&0x80)==0x80)
{
if(port == COM1)
OSFlagPost(pp1->Event,Dnp_Dl_Ready,OS_FLAG_SET,&err);
if(port == COM2)
OSFlagPost(pp2->Event,Dnp_Dl_Ready,OS_FLAG_SET,&err);
}
}
else Reply(FUNC_NACK,port);
break;
case FUNC_DATA_NACK: /*不需确认的数据帧*/
/*若是该包的第一帧*/
if ( (p->buf[10]&0x40) == 0x40) THcount[port-1] = 0;
else THcount[port-1]++;
dli[THcount[port-1]].count = p->count;
dli[THcount[port-1]].ready = TRUE;
dli[THcount[port-1]].rec_time = p->rec_time;
for(i=0; i<p->count; i++)
dli[THcount[port-1]].buf[i] = p->buf[i];
/* 若是该包的最后一帧 */
if ((p->buf[10]&0x80)==0x80)
{
if(port == COM1)
OSFlagPost(pp1->Event,Dnp_Dl_Ready,OS_FLAG_SET,&err);
if(port == COM2)
OSFlagPost(pp2->Event,Dnp_Dl_Ready,OS_FLAG_SET,&err);
}
break;
case FUNC_POLL: /*需回答链路的状态*/
Reply(FUNC_STATUS,port);
break;
default: break;
} /*switch(control & 0x0F)*/
p->ready = FALSE;
}
/*------------------------------------------------------------------------
Procedure: Reply
Purpose: 回应原方站辅助函数.
Input: func:功能码.
Output:
Errors:
------------------------------------------------------------------------*/
void Reply(UCHAR func,INT8U port)
{
USHORT CRC16;
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;
}
plo->buf[0] = 0x05; plo->buf[1] = 0x64; plo->buf[2] = 5;
switch(func){
case FUNC_ACK:
plo->buf[3] = sFCB[port-1]|FUNC_ACK; break;
case FUNC_NACK:
plo->buf[3] = FUNC_NACK; break;
case FUNC_STATUS:
plo->buf[3] = FUNC_STATUS; break;
default: break;
}
plo->buf[4] = p->buf[6]; plo->buf[5] = p->buf[7];
if(port == PORT1)
{
plo->buf[6] = LOW(pp1->DBCfgs->Address);
plo->buf[7] = HIGH(pp1->DBCfgs->Address);
}
else
{
plo->buf[6] = LOW(pp2->DBCfgs->Address);
plo->buf[7] = HIGH(pp2->DBCfgs->Address);
}
CRC16 = dnpcrc((INT8U*)&plo->buf[0], 8);
plo->buf[8] = LOW(CRC16); plo->buf[9] = HIGH(CRC16);
plo->ready = TRUE; plo->count = 10;
/*plo->retry_count = 0;*/
WriteX((INT8U*)plo->buf, plo->count,port); /*DlStartSend();*/
}
/*------------------------------------------------------------------------
Procedure: DlCheckSum
Purpose: 校验接受帧的CRC码.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
int DlCheckSum(INT8U port)
{
UCHAR i, block, rem16; USHORT CRC16;
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;
}
block = (p->buf[2]-5)/16; /*块数*/
rem16 = (p->buf[2]-5)%16; /*余数*/
/*前10字节*/
CRC16 = dnpcrc((INT8U*)&p->buf[0], 8);
if( (p->buf[8] != LOW(CRC16)) ||
(p->buf[9] != HIGH(CRC16)) ) return -1;
/*整块*/
for(i=0; i<block; i++) {
CRC16 = dnpcrc((INT8U*)&p->buf[10+i*18], 16);
if( (p->buf[10+i*18+16] != LOW(CRC16)) ||
(p->buf[10+i*18+17] != HIGH(CRC16)) ) return -2;
}
/*余数*/
if (rem16 > 0) {
CRC16 = dnpcrc((INT8U*)&p->buf[10+block*18], rem16);
if( (p->buf[10+block*18+rem16] != LOW(CRC16)) ||
(p->buf[10+block*18+rem16+1] != HIGH(CRC16)) ) return -3;
}
return 0;
}
/*------------------------------------------------------------------------
Procedure: DnpFrame
Purpose: DNP物理分帧.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
int DnpFrame(INT8U port)
{
USHORT len, CRC16;
UCHAR rem;
int head, frame_ok, total_len,count,i;
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;
}
memset((INT8U *)p->buf,0,292);
count = Readx((INT8U *)p->buf, 292, port);
head = 0; frame_ok = 0;
while(count-head > 7)
{
if( (p->buf[head+0] != 0x05) || /*开始标志*/
(p->buf[head+1] != 0x64) ||
(p->buf[head+2] < 5)
)
{ /*满足最小长度*/
head++; continue;
}
/*地址判断*/
if(CheckAddr(MERGE(p->buf[head+5],p->buf[head+4]),MERGE(p->buf[head+7],p->buf[head+6]),port) < 0)
{
head++; continue;
}
len = p->buf[head+2];
rem = (len-5)%16;
if(rem == 0) total_len = len+2*((len-5)/16)+5;
else total_len = len+2*((len-5)/16)+5+2;
/*校验前10字节*/
if( (count-head) < 10 )
{
break;
}
CRC16 = dnpcrc((INT8U*)&p->buf[head], 8);
if( (p->buf[head+8] != LOW(CRC16)) ||
(p->buf[head+9] != HIGH(CRC16))
)
{
head++; continue;
}
/*未接受到全部帧*/
if( (count-head) < total_len )
{
break;
}
frame_ok = 1;
break;
}
if(frame_ok == 0)
{
lseek(port,head); /*更新串口缓存区的读指针*/
return -1;
}
else
{
lseek(port,head+total_len); /*更新串口缓存区的读指针*/
if(head != 0) /*移动缓冲区*/
for(i=0; i<total_len; i++)
p->buf[i] = p->buf[i+head];
p->count = total_len;
return 0;
}
}
/*------------------------------------------------------------------------
Procedure: OnApp
Purpose: 应用层处理.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void OnApp(INT8U port)
{
UCHAR AppCtrl;
stIPacket *ali = NULL;
stOPacket *alo = NULL;
if(port == COM1)
{
ali = aliCom1;
alo = aloCom1;
}
else if(port == COM2)
{
ali = aliCom2;
alo = aloCom2;
}
AppCtrl = ali->buf[0];
if ( (AppCtrl&AL_AC_CON) == AL_AC_CON )
RecConfirm(port);
AppRes(port); /*应用层回答*/
}
/*------------------------------------------------------------------------
Procedure: OnTick1s
Purpose: 定时探测变化数据.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void OnTick1s(INT8U port)
{
if(port == COM1)
{
if(AppYcVar(port)<pp1->DBCfgs->YCNum/2)
ValueFlag[port-1] = TRUE;
else
ValueFlag[port-1] = FALSE;
}
else if(port == COM2)
{
if(AppYcVar(port)<pp2->DBCfgs->YCNum/2)
ValueFlag[port-1] = TRUE;
else
ValueFlag[port-1] = FALSE;
}
}
/*------------------------------------------------------------------------
Procedure: RecConfirm
Purpose: 应用层确认函数.
Input:
Output:
Errors:
------------------------------------------------------------------------*/
void RecConfirm(INT8U port)
{
INT8U err;
stIPacket *ali = NULL;
stOPacket *alo = NULL;
if(port == COM1)
{
ali = aliCom1;
alo = aloCom1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -