⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dnpsec.c

📁 详细介绍了arm7-at91r40008,的开发全过程
💻 C
📖 第 1 页 / 共 4 页
字号:
 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 + -