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

📄 base.c

📁 电力系统中的保护装置全部代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////////////
//  程序名: BaseInitial.c                                                          //
//  包含系统运行前进行的初始化函数                                                 //
/////////////////////////////////////////////////////////////////////////////////////
#include    "math.h"
#include    "BaseVariable.h"

#define     EEPPAGELENGTH   128             //EEP一个扇区的长度

RUN_USET    uSubAddress;                    //通信地址,自检任务写
RUN_USET    uPassword;                      //口令,自检任务写
RUN_USET    uPTRate;                        //PT变比,自检任务写
RUN_USET    uCTRate;                        //CT变比,自检任务写
RUN_USET    uSetZone;                       //地址区号,自检任务写

UNSIGNED    uSaveBuffer[1024];              //保存数据缓冲区,自检任务写
UNSIGNED    EEP_ErrorFlag;                  //EEP出错标志,自检任务写
UNSIGNED    uRunnigFlag;                    //运行标志,初始化写
UNSIGNED    uSaveSetZone;                   //将修改后的定值固化到该区,显示任务写
UNSIGNED    EEPPage[EEPPAGELENGTH];         //拷贝出EEP一个扇区的内容并修改,然后写回EEP,自检任务写
UNSIGNED    Uabcnt,Ubccnt,Ucacnt;           //线电压有压计数

REPORT      ReportRAM[REPORTRAM];           //RAM中报文队列,多个任务写*****
REPORT      *pReportIN = ReportRAM;         //指向RAM中报文队列的指针,自检任务写
REPORT      *pReportSave = ReportRAM;       //指向RAM中报文队列的指针,自检任务写
REPORT      *pReportDISP = ReportRAM;       //指向RAM中报文队列的指针,显示任务写
REPORT      *pReportRVT = ReportRAM;        //指向RAM中报文队列的指针,多个任务写
IQDSTRU     IQD;                            //电流突变量启动相关单元,保护任务写
float       *CalculatePtr;                  //本次计算时的采样指针,保护任务写
EEP_REPORT  *pEEP_REPORT;                   //指向EEP报告区的指针,自检任务写
UNSIGNED    uReportNum;                     //报告数,自检任务写

UNSIGNED    *pDIN1PORT = (UNSIGNED *)DIN1PORT, *pDIN2PORT = (UNSIGNED *)DIN2PORT;             // I/O地址
UNSIGNED    *pLCD1PORT = (UNSIGNED *)LCD1PORT, *pDOPORT = (UNSIGNED *)DOPORT;                 // I/O地址
UNSIGNED    *pCTRLPORT = (UNSIGNED *)CTRLPORT, *pKEYPORT = (UNSIGNED *)KEYPORT;               // I/O地址
unsigned char *Com_Port1 = (unsigned char *)COM1PORT, *Com_Port2 = (unsigned char *)COM2PORT; // I/O地址
unsigned char *Com_Port3 = (unsigned char *)COM3PORT, *Com_Port4 = (unsigned char *)COM4PORT; // I/O地址
UNSIGNED    *pADPORT = (UNSIGNED *)ADPORT, *pDIN3PORT = (UNSIGNED *)DIN3PORT;                 // I/O地址
 
extern UNSIGNED CT_backup,PT_backup;                  //CT变比,PT变比,显示任务写
extern UNSIGNED CtrlOutBuf;                           //控制口输出缓存
extern EEP_SET  uAmendCoeff[CHL_Number];              //模入修正系数,自检任务写
extern EEP_SET  uAmendAngle[CHL_Number];              //模入修正角度,自检任务写

#pragma     DATA_SECTION(uSubAddressEEP,".NVRAM1");   //保存在EEP中的通信地址,自检任务写
#pragma     DATA_SECTION(uPasswordEEP,".NVRAM1");     //保存在EEP中的口令,自检任务写
#pragma     DATA_SECTION(uSetZoneEEP,".NVRAM1");      //保存在EEP中的定值区号,自检任务写
#pragma     DATA_SECTION(uPTRateEEP,".NVRAM1");       //保存在EEP中的PT变比,自检任务写
#pragma     DATA_SECTION(uCTRateEEP,".NVRAM1");       //保存在EEP中的CT变比,自检任务写
#pragma     DATA_SECTION(uJumperEEP,".NVRAM1");       //保存在EEP中的压板,自检任务写
#pragma     DATA_SECTION(uSettingEEP,".NVRAM2");      //保存在EEP中的定值,自检任务写
#pragma     DATA_SECTION(uReportEEP,".NVRAM3");       //保存在EEP中的报告,自检任务写
EEP_SET     uSubAddressEEP,uPasswordEEP,uSetZoneEEP;
EEP_SET     uPTRateEEP,uCTRateEEP;
UNSIGNED    uJumperEEP[20];
UNSIGNED    uSettingEEP[SETTINGNUM][256];
EEP_REPORT  uReportEEP[EEP_REPORTNUM];

VOID        StartSaveToEEP(VOID);                     //启动保存数据,自检任务用
VOID        SaveToEEP(UNSIGNED);                      //将数据保存到EEP,自检任务用
UNSIGNED    LoadUSET(UNSIGNED *pSRC, UNSIGNED *pDST); //从EEP中装入整数,初始化用
VOID        SaveUSET(UNSIGNED *pSRC, UNSIGNED *pDST); //往EEP中保存整数,自检任务用
VOID        WriteEEP(UNSIGNED*, UNSIGNED*, UNSIGNED); //往EEP中保存指定字节长度的数据,自检任务用
VOID        DMAWriteEEP(UNSIGNED*);                   //启动DMA写数据,自检任务用
VOID        Revert(VOID);                             //复归信号,自检任务用
UNSIGNED    ProtectDeclare(VOID);                     //判断是否运行保护,保护任务用
VOID        Base_Varible_Initialize(VOID);            //基本变量初始化,初始化用

/***********************************************************************************/
/*  基础变量初始化                                                                 */
/*  使用范围:初始化用                                                              */
/***********************************************************************************/
VOID Base_Varible_Initialize(VOID)
{     
    UNSIGNED l,ByteData[4*PULSENUM];
    register UNSIGNED    i,j,k,*pByte,*pWord;
    register PROTECT     *protect;
    register SETTING     *pSets;
    register EEP_REPORT  *pEEP1;
    register DISTRU      *pDI = DIChn;
    register CHECK       *check;
        
    Switchin_buf = (*pDIN1PORT & 0xFFFF) | ((*pDIN2PORT & 0xFFFF) << 16);  //开入稳态值初始化
    SoftTime.DI[0] = Switchin_buf;                                         //开入暂态值初始化
    for (i = 0, j = 1; i < DI_Number; i++, j <<= 1)                        //开入结构体状态位初始化
    {
        if (!(Switchin_buf & j)) pDI->state = 1;
        pDI++;
    }
     
    *pDOPORT = Switchout_buf;            //开出初始化
    *pCTRLPORT = CtrlOutBuf;             //控制口初始化

    //脉冲计数初始化
    DS1302BurstRead(0xff, ByteData, 4*PULSENUM);   //从DS1302中读出脉冲数
    pByte = ByteData;
    pWord = PulseCounter;
    for (i = 0; i < PULSENUM; i++)                 //将8位数组合为32位数
    {
        *pWord++ = (*pByte++ & 0xff) | (*pByte++ & 0xff) << 8 | (*pByte++ & 0xff) << 16
                    | (*pByte++ & 0xff) << 24;     
    }
    
    //报告存储地址初始化:序号为0xffff,或序号最小者。
    pEEP1 = uReportEEP;              //指向报告存储首地址
    j = 0xffff;                      //序号设为最大
    for (i = 0; i < EEP_REPORTNUM; i++) //逐个检查报告区
    {
        k = ((pEEP1->uReportEEPNumH & 0xff) << 8) | (pEEP1->uReportEEPNumL & 0xff);
        
        if (k == 0xffff)             //序号为0xffff,说明该区为空,可以使用
        {
            pEEP_REPORT = pEEP1;     //pEEP_REPORT指向可使用区
            break;
        }
        
        if (j > k)                   //找到最小序号的区
        {
            j = k;
            pEEP_REPORT = pEEP1;     //pEEP_REPORT指向最小序号的区即最老的区
        }
        
        pEEP1++;
    }
    
    pEEP1 = pEEP_REPORT;             //根据上一区的序号定本区的序号
    if (--pEEP1 < uReportEEP) pEEP1 = &uReportEEP[EEP_REPORTNUM - 1];               //pEEP1指向上一区
    k = ((pEEP1->uReportEEPNumH & 0xff) << 8) | (pEEP1->uReportEEPNumL & 0xff);     //读上一区序号
    uReportNum = (k == 0xffff ? 0 : k);                                             //k=0xffff,则序号为零,否则为上一次序号
    
    //设置初始化
    subAddress_backup = LoadUSET((UNSIGNED *)&uSubAddressEEP,(UNSIGNED *)&uSubAddress);
    password_backup = LoadUSET((UNSIGNED *)&uPasswordEEP,(UNSIGNED *)&uPassword);
    iLONC_SetZoneNum = LoadUSET((UNSIGNED *)&uSetZoneEEP,(UNSIGNED *)&uSetZone);
    CT_backup = LoadUSET((UNSIGNED *)&uCTRateEEP,(UNSIGNED *)&uCTRate);
    PT_backup = LoadUSET((UNSIGNED *)&uPTRateEEP,(UNSIGNED *)&uPTRate);
    
    pByte = uJumperEEP;                      //指向存储压板EEP的指针
    protect = PRO_Created_Protect_List;  
    for (i = 0; i < PRO_Total_Protect; i++, protect = protect->pro_link_next)
    {
        (protect->pro_jumper)->jum_status = *pByte++ & 0xff;
    }

    for (j = 0; j < SETTINGNUM; j++)         //将全部定值区内的定值读到保护结构体
    {
        pByte = uSettingEEP[j];              //指向EEP中第j区定值的指针
        protect = PRO_Created_Protect_List;  //保护列表指针
        for (i = 0; i < PRO_Total_Protect; i++, protect = protect->pro_link_next)
        {
            pSets = protect->pro_setting;
            for (k = 0; k < protect->pro_setting_number; k++)
            {
                l = *pByte++ & 0xff;
                l |= (*pByte++ & 0xff) << 8;
                l |= (*pByte++ & 0xff) << 16;
                l |= (*pByte++ & 0xff) << 24;
                pSets->set_value_zone[j] = *((float *)&l);
                pSets++;
            }
        }
    }
    
    check = CHK_Created_Check_List;          //将全部设置自检一遍
    for (i = 0; i < CHK_Total_Check; i++, check = check->chk_link_next)
    (*(check->chk_routine_handler))(check);
    uRunnigFlag = 1;
}

/***********************************************************************************/
/*  判断是否运行保护程序: 1运行,0不运行                                            */ 
/*  如果装置出错:返回0                                                             */ 
/*  保护已经启动,且已经经过一个周波,返回1                                          */ 
/*  使用范围:保护任务用                                                            */ 
/***********************************************************************************/
UNSIGNED    ProtectDeclare(VOID)
{
    register UNSIGNED i,j;
    register PROTECT  *protect;

    CalculatePtr = Sample_Ptr;
    if (IQD.QDB)                              //是否启动
    {       
        if (IQD.WaitFlag)                     //WaitFlag为1,说明电流突变量启动,且启动时间不满一周
        { 
            i = Sample_Ptr - IQD.IqdPtr;      //启动后经过的采样点数
            if (i >= AD_OneDataSize - 1)
                i += AD_OneDataSize - 1;
            if (i >= Sample_Point)            //是否已启动一个周波
            {
                Uabcnt = 10;
                Ubccnt = 10;
                Ucacnt = 10;
                IQD.WaitFlag = 0;             //启动时间满一周,WaitFlag清0
                return(1);                    //返回1,运行保护程序
            }
            else
            {
                return (0);                   //返回0,不运行保护程序
            }
        }
        else                                  //WaitFlag为0,说明电流突变量启动,且正在运行保护程序
        {
            if (!DOChn[QDJ].state && (TMD_System_Clock - IQD.Iqdsj) > 100)
                IQD.QDB = 0;                  //电流突变量启动后,启动继电器未动,说明保护未启动,清QDB
            return(1);
        }
    }  
    else                                      //QDB为0,返回1,运行保护程序,相当于稳态启动判别
    {
        return(1);
    }
}

/**********************************************************/
/*     Fill_Report(REPORT *ptr)                           */  
/*         将报告填入RAM区                                */
/*         使用范围:多个任务用                            */
/**********************************************************/
VOID Fill_Report(REPORT *ptr)
{
    UNSIGNED j;
    register UNSIGNED    *p,i;
    register UNSIGNED    *p1 = (UNSIGNED *)ptr;
    register OPTION      old_preempt;

    old_preempt = NU_Change_Preemption(NU_NO_PREEMPT);    //不再切换任务,避免被其他任务打断,造成误动
    
    p = (UNSIGNED *)pReportIN;

    if (++pReportIN > &ReportRAM[REPORTRAM - 1]) pReportIN = ReportRAM;  //指向下一区,并判数组越界
   
    for (i = 0; i < sizeof(REPORT); i++) *p++ = *p1++;

    NU_Change_Preemption(old_preempt);                    //可以切换任务

    j = SAVE_REPORT;
    NU_Send_To_Queue(&SaveQueue,&j,1,NU_SUSPEND);
}

/**********************************************************/
/*     JUMPER_Change(JUMPER *ptr)                         */  
/*         填压板改变报告                                 */
/*         使用范围:多个任务用                            */
/**********************************************************/
VOID JUMPER_Change(JUMPER *pJUMPER)
{
    static REPORT   JumperReport;

    register REPORT    *pJumperReport;
    register SOE       *pSOE;
    register CHAR      *pCHAR1,*pCHAR2;
    register JUMPER    *ptr = pJUMPER;
    register UNSIGNED  i;
    register OPTION    old_preempt;

    old_preempt = NU_Change_Preemption(NU_NO_PREEMPT);    //不再切换任务,避免被其他任务打断,造成误动
    
    pJumperReport = &JumperReport;                        //指向压板报告
    pSOE = &pJumperReport->pro_report_soe;
                             
    pCHAR1 = ptr->pjum_name;                              //拷贝名称
    pCHAR2 = pSOE->SOE_name;
    for (i = 0; i < JUMPER_NAME; i++)
    {
        if (*pCHAR1 != '\0')
            *pCHAR2++ = *pCHAR1++;
        else
            break;
    }
    
    if (ptr->jum_status == 1)
    {
        pCHAR1 = "投入";
    }
    else

⌨️ 快捷键说明

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