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

📄 secdlink.c

📁 详细介绍了arm7-at91r40008,的开发全过程
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "includes.h"
#include "iec101def.h"
#include "iec101wh.h"
#include "secdlink.h"
#include "secapp.h"

extern struct LinkInfo* ComLink[PORTNUM];
extern struct AppInfo* ComApp[PORTNUM];
extern struct SysPort*	ComDb[PORTNUM];

BOOL Init101SecDLink(INT8U Port, struct PortAppInfo* PortCfg)
{
    INT8U i;
    struct PSec101_2002Pad *pPad;

    i = Port - 1;
    pPad = (struct PSec101_2002Pad*)(PortCfg->pPad);
    ComLink[i]->Baudrate = PortCfg->Baudrate;
    if (pPad!=NULL)
    {
        ComLink[i]->TimeOutValue = pPad->PBase.Timer.TimeoutValue1;
        if (ComLink[i]->TimeOutValue<100)
            ComLink[i]->TimeOutValue=100;

        ComLink[i]->DLIdleTime=ComLink[i]->TimeOutValue/100;//线路空闲检测时间不能小于2秒
        if(ComLink[i]->DLIdleTime<2)
            ComLink[i]->DLIdleTime=2;

        if(pPad->PBase.ProtocolControl&BALANCE)
        {
            ComLink[i]->BalanMode=TRUE;
            ComLink[i]->IEC_DIR=0x80;
        }
        else
        {
            ComLink[i]->BalanMode=FALSE;
            ComLink[i]->IEC_DIR=0;
        }

        ComLink[i]->LinkAddrSize=pPad->LINKAddrSize;
        if(ComLink[i]->LinkAddrSize!=1)
            ComLink[i]->LinkAddrSize=2;//zzw
    }
    else
    {
        ComLink[i]->TimeOutValue=100;
        ComLink[i]->BalanMode=FALSE;
        ComLink[i]->LinkAddrSize=2;
    }
        
    ComLink[i]->DLPriStatus=PRIDISABLE;

    ComLink[i]->SourceNo = ComDb[i]->DBCfgs->Address;

    ComLink[i]->FlagData1=FALSE;
    ComLink[i]->TxdStatus=TXDSEND;
    ComLink[i]->RxdStatus=RXDSTART;

    ComLink[i]->FrameHead=0;
    ComLink[i]->TxdHead=0;
    ComLink[i]->TxdTail=0;
    ComLink[i]->RxdHead=0;
    ComLink[i]->RxdTail=0;
    ComLink[i]->RxdLength=0;

    ComLink[i]->StartDL=0xff;
    ComLink[i]->RemoteDLOK=0;
    ComLink[i]->LocalDLOK=0;

    ComLink[i]->LastControl=0xff;

    ComLink[i]->TimeOutTick=ComLink[i]->TimeOutTick_Pri=ComLink[i]->TimeOutTick_Sec=ComLink[i]->TimeOutTickCopy=0;

    if(ComLink[i]->LinkAddrSize==1)
        ComLink[i]->FixFrmLength=5;
    else
        ComLink[i]->FixFrmLength=6;

    return	TRUE;
}

//读MISI数据
void S101RecMISIData(INT8U Port, BOOL Flag)
{
    INT16U i, count;
    
    i = Port - 1;
    if(ComLink[i]->RxdHead < ComLink[i]->RxdTail)    //接收缓冲区中有尚未处理的数据
    {
        if (ComLink[i]->RxdHead!=0)
        {
            memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);//将未处理的数据移到缓冲区头
            ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
            ComLink[i]->RxdHead=0;
        }
    }
    else
        ComLink[i]->RxdHead=ComLink[i]->RxdTail=0;
   // count=0;
    count=Readx((INT8U *)&ComLink[i]->RxdBuf[ComLink[i]->RxdTail], LPDUSIZE, Port);
    lseek(i+1, count);   
    if (count>0)
    {
        ComLink[i]->RxdTail+=count;
        S101_2002SearchFrame(Port);
    }
}

//发送缓冲区中的数据,写MISI接口
BOOL S101_2002SendDataToMISI(INT8U Port)
{
    INT16U SendLen, i, num;
    INT8U err;

    i = Port - 1;
    ComLink[i]->IdleTimeCount = 0;
    
    if (ComLink[i]->TxdStatus==TXDSEND)//新数据发送
    {
        ComLink[i]->TxdHead=0;
        num = ComLink[i]->TxdTail - ComLink[i]->TxdHead;
        SendLen = WriteX((INT8U *)&ComLink[i]->TxdBuf[ComLink[i]->TxdHead], num, Port);
        ComLink[i]->TxdHead += SendLen;
        if (SendLen>0)//数据正常发送(完没完还未判断)
            ComLink[i]->TxdStatus=TXDWAIT;
    }
    else//上次数据未发送完,
        SendLen = WriteX(ComLink[i]->TxdBuf+ComLink[i]->TxdHead, ComLink[i]->TxdTail-ComLink[i]->TxdHead, Port);
       
    ComLink[i]->TxdHead+=SendLen;
    if(ComLink[i]->TxdHead>=ComLink[i]->TxdTail)//该次任务数据已经发完。
    {
        ComLink[i]->TxdStatus=TXDSEND;
        if(ComLink[i]->BalanMode)
            //eventSend(taskIdSelf(),SENDOVER);
            OSFlagPost(ComDb[i]->Event, SENDOVER, OS_FLAG_SET, &err);
        return TRUE;
    }
    else
        return FALSE;
    
}

void SecSendPriDataToMISI(INT8U Port)//
{
    INT8U i;
    
    i = Port-1;
    if (ComLink[i]->TxdStatus==TXDSEND)
        ComLink[i]->TxdTail=0;
    ComLink[i]->FrameHead=ComLink[i]->TxdTail;

    memcpy(ComLink[i]->TxdBuf+ComLink[i]->FrameHead,ComLink[i]->TxdBuf_Pri,ComLink[i]->TxdTail_Pri);
    ComLink[i]->TxdTail+=ComLink[i]->TxdTail_Pri;

    S101_2002SendDataToMISI(Port);
}

void SendSec101_2002DataToMISI(INT8U Port)//
{
    INT8U i;
    
    i=Port-1;
    if (ComLink[i]->TxdStatus==TXDSEND)
        ComLink[i]->TxdTail=0;
    ComLink[i]->FrameHead=ComLink[i]->TxdTail;

    memcpy(ComLink[i]->TxdBuf+ComLink[i]->FrameHead,ComLink[i]->TxdBuf_Sec,ComLink[i]->TxdTail_Sec);
    ComLink[i]->TxdTail+=ComLink[i]->TxdTail_Sec;

    S101_2002SendDataToMISI(Port);
}



void TimeOutFun(INT8U Port, INT8U FailType, INT8U Prm)//超时处理
{
    INT8U i;
    
    i = Port-1;
    if(!ComLink[i]->RetryCount)
        return;
    ComLink[i]->RetryCount--;
    if(ComLink[i]->RetryCount)
    {
        if(Prm)//启动站报文超时未收到应答
        {
            SecSendPriDataToMISI(Port);
            ComLink[i]->TimeOutTick_Pri=ComLink[i]->TimeOutTickCopy;
        }
        else//这里其实运行不到
        {
            SendSec101_2002DataToMISI(Port);
            ComLink[i]->TimeOutTick_Sec=ComLink[i]->TimeOutTickCopy;
        }
        return;
    }
    else//超过重发次数后,重新建立链路,并通知应用层。
    {
        if(ComLink[i]->BalanMode)
        {
            CallDLStatus(Port);
            ComLink[i]->LocalDLOK=0;

            ComApp[i]->DLCommand=DL_LINKDISABLE;
            ComApp[i]->LengthIn=0;
            Sec101_2002AppProc(Port, ComLink[i]->RxdBuf+5+ComLink[i]->LinkAddrSize,ComApp[i]->LengthIn,ComApp[i]->DLCommand,
                                ComLink[i]->TxdBuf+5+ComLink[i]->LinkAddrSize,(INT16U *)&ComApp[i]->LengthOut,(INT16U *)&ComApp[i]->AppCommand);
            S101_2002DLSendProc(Port);
        }
    }
}


//启动链路过程
void CallDLStatus(INT8U Port)
{
    INT8U i;
    
    i=Port-1;
    EditFra10(Port, DLREQSTATUS);
    S101_2002SendDataToMISI(Port);

    ComLink[i]->DLPriStatus=PRIWAITSTATUS;
    ComLink[i]->TimeOutTick_Pri=TimeDelay(Port, 2* ComLink[i]->FixFrmLength);
    ComLink[i]->RetryCount=MAXRETRYNUM;

    if(ComLink[i]->BalanMode)//平衡模式,启动远方链路过程。重新建立链路
    {
        ComLink[i]->StartDL=0xFF;
        ComLink[i]->RemoteDLOK=0;
    }
}

void S101_2002SearchFrame(INT8U Port)
{
    BOOL Stop=FALSE;
    INT8U length,i,err;
    
    i=Port-1;
    while ((ComLink[i]->RxdHead < ComLink[i]->RxdTail)&&(!Stop))
    {
        if(ComLink[i]->RxdStatus==RXDSTART)
        {
            while ((ComLink[i]->RxdBuf[ComLink[i]->RxdHead]!=STARTCODE68)
                    &&(ComLink[i]->RxdBuf[ComLink[i]->RxdHead]!=STARTCODE10)
                    &&(ComLink[i]->RxdHead < ComLink[i]->RxdTail))
            {
                ComLink[i]->RxdHead++;
            }

            if (ComLink[i]->RxdHead<ComLink[i]->RxdTail)//找到启动字符,并将报文与缓冲区对齐。
            {
                ComLink[i]->RxdStatus=RXDHEAD;
                if (ComLink[i]->RxdHead!=0)
                {
                    memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);
                    ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
                    ComLink[i]->RxdHead=0;
                }
            }
        }
        ComLink[i]->RxdLength=ComLink[i]->RxdTail-ComLink[i]->RxdHead;
        if(ComLink[i]->RxdStatus==RXDHEAD)//报文够一帧则
        {
            switch (ComLink[i]->RxdBuf[ComLink[i]->RxdHead])
            {
                case STARTCODE68:
                    if (ComLink[i]->RxdLength>=5+ComLink[i]->LinkAddrSize)//启动字符到链路地址共6字节。
                    {
                        if (!S101_2002ExeDLFun68(Port))//判断是否报文头
                        {
                            ComLink[i]->RxdHead++;
                            ComLink[i]->RxdStatus=RXDSTART;
                        }
                        else
                            ComLink[i]->RxdStatus=RXDCONTINUE;
                    }
                    else
                        Stop=TRUE;
                    break;
                case STARTCODE10:
                    if (ComLink[i]->RxdLength>=4+ComLink[i]->LinkAddrSize)
                    {
                        if (!S101_2002ExeDLFun10(Port))
                        {
                            ComLink[i]->RxdHead++;
                            ComLink[i]->RxdStatus=RXDSTART;
                        }
                        else
                            ComLink[i]->RxdStatus=RXDCONTINUE;
                    }
                    else
                        Stop=TRUE;
                    break;
            }
        }
        if(ComLink[i]->RxdStatus==RXDCONTINUE)
        {
            switch (ComLink[i]->RxdBuf[ComLink[i]->RxdHead])
            {
                case STARTCODE68:
                    length=ComLink[i]->RxdBuf[ComLink[i]->RxdHead+1];
                    if (ComLink[i]->RxdLength>=length+6)//报文收全,进行处理
                    {
                        if ( (ComLink[i]->RxdBuf[ComLink[i]->RxdHead+length+4]==CheckSum(Port, ComLink[i]->RxdBuf+ComLink[i]->RxdHead))//校验正确
                                &&(ComLink[i]->RxdBuf[ComLink[i]->RxdHead+length+4+1]==ENDCODE))//结束码正确
                        {
                            if (ComLink[i]->RxdHead>0)
                            {
                                memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);//报文与缓冲区对齐
                                ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
                                ComLink[i]->RxdHead=0;
                            }
                            ComLink[i]->RxdHead+=(ComLink[i]->RxdBuf[1]+6);//头指针后移到报文后
                            ComLink[i]->RxdStatus=RXDSTART;
                            //Stop=TRUE;

                            S101_2002ExeDLFunCode68(Port);
                            if (ComLink[i]->RxdTail>ComLink[i]->RxdHead)
                                OSFlagPost(ComDb[i]->Event, NEXTFRAME, OS_FLAG_SET, &err);
                        }
                        else
                        {
                            ComLink[i]->RxdHead+=6;
                            ComLink[i]->RxdStatus=RXDSTART;
                        }
                    }
                    else//报文未收全,不处理,继续等待数据。
                        Stop=TRUE;
                    break;
                case STARTCODE10:
                    if (ComLink[i]->RxdHead>0)
                    {
                        memcpy(ComLink[i]->RxdBuf,ComLink[i]->RxdBuf+ComLink[i]->RxdHead,ComLink[i]->RxdTail-ComLink[i]->RxdHead);
                        ComLink[i]->RxdTail-=ComLink[i]->RxdHead;
                        ComLink[i]->RxdHead=0;
                    }
                    ComLink[i]->RxdHead+=4+ComLink[i]->LinkAddrSize;
                    ComLink[i]->RxdStatus=RXDSTART;
                    //Stop=TRUE;
                    S101_2002ExeDLFunCode10(Port);
                    if (ComLink[i]->RxdTail>ComLink[i]->RxdHead)
                        OSFlagPost(ComDb[i]->Event, NEXTFRAME, OS_FLAG_SET, &err);
                    break;
            }
        }
  	}
}

//检测10帧正确性
BOOL S101_2002ExeDLFun10(INT8U Port)
{
    INT8U i;
    INT8U *p;
    INT16U addr=0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -