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

📄 main.c

📁 一个串口终端解释程序。用于单片机调试串口的超级终端应用。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------*
* Copyright (c) 2005,北京四方同创保护与控制设备有限公司稳控事业部
* All rights reserved.
*
* 文件名称:main.c
* 摘    要:内电势测量装置DSP56F807主程序
*           采用CSS-200/1规约V1.02版
* 当前版本:2.00
* 作    者:胡炯
* 完成日期:2007.1
*-----------------------------------------------------------------------*/

#define MAIN_DEFINE
#include "56807.h"
#include "CSFU107.h"

/*****函数原型定义*****/
void PpsCaptureIsr(void);       //PPS中断子程序,Timer D0
void StartWork(void);           //开始正常工作流程

void AdjustPpsOutput(void);     //判断输入、输出PPS误差,校正输出PPS
int IsCurPpsInputSyncOutput(void);  //判断并返回当前的输入PPS是否与输出PPS同步良好
void AdjustPps(void);           //利用GPS授时信号校准输出PPS
long NormanizeErrCorr(long lErrorCorr);     ///规格化误差校正值
void RecPpsPeriod(unsigned long PpsPeriod); //记录正确的秒脉冲周期
void KeepPpsOutput(void);       //利用存储的平均值维持PPS输出

void DealSoc(void);         //更新SOC时间

void TimerD3Isr(void);      //1ms定时器中断,Timer D3

void CalPeriodCounterQueue(void);   //计算当前一秒内工频整周期时刻对应的计数值
void LedOutput(void);       //判断装置状态,驱动指示灯

void InitIntWatchdog(void);         //初始化内部WATCHDOG
void ClearExtWatchdog(void);        //清除外部WATCHDOG
void ClearIntWatchdog(void);        //清除内部WATCHDOG

extern void Init(void);                 //软硬件初始化子程序
extern void InitSci1TransVariable(void);    //初始化与SCI1发送相关的变量(向数据表发送数据)
extern void InitSci1RecVariable(void);      //初始化与SCI1接收相关的变量(接收GPS时钟信号)
extern void InitSci1Rec(void);          //初始化SCI1的接收(接收GPS时钟信号)
extern void InitPulseCapture(void); //允许捕捉键相脉冲和A相电压脉冲中断
extern void CalSoc(void);                   //利用接收的串口报文计算SOC
extern void SendDataToRcm3200(void);    //向RCM3200发送报文
extern void SendDataToMeter(void);      //向数显表发送报文
extern void WriteRcm3200DataRpt(void);      //填写RCM3200报文缓冲区
extern void WriteRcm3200PatrolRpt(void);    //填写RCM3200串口巡检报文缓冲区

extern void ControlDa(void);        //控制DA输出

extern void WriteDatatoFlash(void);     //将配置信息写入flash

extern void JudgeEStat(void);       //判断E的输入状态是否正确
extern void JudgeUStat(void);       //判断U的输入状态是否正确
extern void EnableECapture(void);   //允许捕捉键相脉冲中断
extern void EnableUCapture(void);   //允许捕捉电压脉冲中断
extern void CalAngle(void);     //计算内电势绝对角和发电机功角
extern void ButtonFilter(void); //对补偿值按钮调节进行去抖处理

void RecInputPpsCounter(unsigned long RecCounter);      //记录输入PPS上升沿计数器值,用于测试
void RecOutputPpsCounter(unsigned long RecCounter);     //记录输出PPS上升沿计数器值,用于测试
void RecTd3OverflowCounter(unsigned long RecCounter);   //记录TD3溢出时刻,用于测试

/*****end of 函数原型定义*****/


/*****主函数main*****/
void main(void)
{

start:
    Init();

    DEBUG1_LED_TURN_OFF;
    DEBUG2_LED_TURN_OFF;
    ALERT1_LED_TURN_ON;
    InitIntWatchdog();

    /*****程序主循环*****/
    while (1)
    {
        ClearIntWatchdog(); //清除内部WATCHDOG
        ClearExtWatchdog(); //清除外部WATCHDOG

        SendDataToRcm3200();    //向RCM3200发送报文
        SendDataToMeter();      //向数显表发送报文
        ControlDa();            //控制DA输出

        if (WriteFlashStartFlag && !WriteFlashFlag)
        //要求向FLASH中写入数据,且当前未进行FLASH写入操作
        {
            if ((E.WriteFlashCompensateValue != E.CompensateValue)
            || (U.WriteFlashCompensateValue != U.CompensateValue)
            || (WriteFlashRunStat != RunStat))
            //FLASH当前存储数据与新数据不等
            {
                E.WriteFlashCompensateValue = E.CompensateValue;
                U.WriteFlashCompensateValue = U.CompensateValue;
                WriteFlashRunStat = RunStat;
                WriteFlashFlag = 1;
                EraseFlashStep = 1;
            }
            WriteFlashStartFlag = FALSE;
        }
        if (WriteFlashFlag)
        {
            WriteDatatoFlash();
        }

        if (CalSocFlag)
        {
            CalSoc();       //利用接收的串口报文计算SOC
        }
    }
    /*****end of 程序主循环*****/
}
/*****end of 主函数main*****/


/*****TimerD0 中断服务程序*****/
#pragma interrupt
void PpsCaptureIsr(void)    //输入PPS捕获中断
{
    unsigned int TempUI1, TempUI2;
    unsigned long LastInputPpsCounterBak;

    TempUI1 = *TMRD0_CNTR;      //读取当前PPS脉冲上升沿到来时刻的计数值
    CurrInputPpsCounter = *TMRD1_HOLD;
    CurrInputPpsCounter <<= 16;
    TempUI2 = *TMRD0_CAP;
    CurrInputPpsCounter += TempUI2;
    if (TempUI1 < TempUI2)
    {
        CurrInputPpsCounter -= 0x10000;
    }

    CurrInputPpsPeriod = CurrInputPpsCounter - LastInputPpsCounter; //得到当前秒脉冲的周期
    LastInputPpsCounterBak = LastInputPpsCounter;
    LastInputPpsCounter = CurrInputPpsCounter;

//  RecInputPpsCounter(CurrInputPpsCounter);   //记录输入PPS上升沿计数器值,用于测试

    if (!PpsOutputFlag) //还未开始输出PPS的初始化阶段
    {
        if (RealFixFlag == 0)   //如果GPS卫星失锁,认为输入PPS信号无效
        {
            *TMRD0_SCR = *TMRD0_SCR & 0xf7ff;   //允许再次触发中断
            return;
        }

        if ((MinPpsPeriod  < CurrInputPpsPeriod) && (CurrInputPpsPeriod < MaxPpsPeriod))    //当前秒脉冲周期在限定范围内
        {
            PpsPeriodGap = CurrInputPpsPeriod - LastInputPpsPeriod;
            LastInputPpsPeriod = CurrInputPpsPeriod;
            if ((PpsPeriodGap < PPS_PPS_ERROR) && (PpsPeriodGap > (-PPS_PPS_ERROR)))    //当前秒脉冲周期与前一个秒脉冲周期的差值在限定范围内
            {
            	DealSoc(); 
            	
                *PpsPeriodRecBufPtr++ = CurrInputPpsPeriod;     //将符合要求的秒脉冲周期存入缓冲区
                if (++InputPpsStableCounter >= INPUT_PPS_STABLE_THRESHOLD)      //已达到初始化阶段稳定PPS个数
                {
                    if (SocStableCounter >= 8)
                    {
                        StartWork();   //开始正常工作流程
                    }
                    else
                    {
                        PpsPeriodRecBufPtr = &PpsPeriodRecBuf[0];
                        InputPpsStableCounter = 0;
                    }
                }
            }
            else    //如果出现一个有问题的秒脉冲,累计数据即重新开始
            {
                PpsPeriodRecBufPtr = &PpsPeriodRecBuf[0];
                InputPpsStableCounter = 0;
            }
        }
        else        //如果出现一个有问题的秒脉冲,累计数据即重新开始
        {
            PpsPeriodRecBufPtr = &PpsPeriodRecBuf[0];
            InputPpsStableCounter = 0;
        }
    }

    else    //已经开始输出PPS
    {
        if ((MinPpsPeriod  < CurrInputPpsPeriod) && (CurrInputPpsPeriod < MaxPpsPeriod))    //当前秒脉冲周期在限定范围内
        {
            PpsPeriodGap = CurrInputPpsPeriod - LastInputPpsPeriod;
            LastInputPpsPeriod = CurrInputPpsPeriod;
            if ((PpsPeriodGap < PPS_PPS_ERROR) && (PpsPeriodGap > (-PPS_PPS_ERROR)))    //当前秒脉冲周期与前一个秒脉冲周期的差值在限定范围内
            {
                RecInputPpsCounter(CurrInputPpsCounter);   //记录输入PPS上升沿计数器值,用于测试
                InputPpsComeFlag = TRUE;    //标识新的PPS输入到来
            }
        }
    }

    ClearIntWatchdog(); //清除内部WATCHDOG,插拔GPS光纤将频繁进入TD0中断,导致主循环运转时间超过20ms

    *TMRD0_SCR = *TMRD0_SCR & 0xf7ff;   //允许再次触发中断
}
/*****end of TimerD0 中断服务程序*****/


/*****开始正常工作流程*****/
#pragma interrupt
void StartWork(void)
{
    unsigned int i;
    unsigned long *TempULPtr;
    unsigned long TempUL;
    unsigned int TempUI;

    TempUL = 0;
    TempULPtr = &PpsPeriodRecBuf[0];
    //根据初始化阶段得到的数据,计算秒脉冲周期平均值
    for (i=0; i<INPUT_PPS_STABLE_THRESHOLD; i++)
    {
        TempUL += *TempULPtr++;
    }
    AveragePpsPeriod = TempUL / INPUT_PPS_STABLE_THRESHOLD;
    AveragePpsResidue = TempUL - AveragePpsPeriod * INPUT_PPS_STABLE_THRESHOLD;

    MinPpsPeriod = AveragePpsPeriod - RUNNING_MAX_PPS_PERIOD_ERROR;     //允许误差+-20us
    MaxPpsPeriod = AveragePpsPeriod + RUNNING_MAX_PPS_PERIOD_ERROR;

    OutputPpsPeriod = AveragePpsPeriod;     //DSP输出秒脉冲周期的初始值为初始计算的平均秒脉冲周期
    OutputPpsCounter = CurrInputPpsCounter + OutputPpsPeriod;       //设定虚拟PPS上升沿输出时间

    PpsOutputFlag = TRUE;
    FirstOutputPpsFlag = TRUE;

    TempUI = *TMRD0_CNTR;
    TempUL = *TMRD1_HOLD;
    TempUL <<= 16;
    TempUL += TempUI;
    *TMRD3_CMP1 = 40000 - (TempUL - CurrInputPpsCounter) - 0;   //设定1ms溢出中断,保证溢出时间与PPS上升沿同步
    *TMRD3_CTRL = 0x3020;   //开启1ms定时中断
    //bit15-13     001     计数模式 :对第一计数源上升沿计数
    //bit12-9       1000    第一计数源为IPBus=40MHz
    //bit8-7        00      第二计数源为计数器0的输入引脚
    //bit6(ONCE)    0       0——不停计数,1——Compare发生后计数停止
    //bit5(LENGTH)  1       0——计数到溢出,1——Compare发生后初始化计数值
    //bit4(DIR)     0       0——向上计数,1——向下计数
    //bit3(Co Init) 0       0——不允许此模块内的其他计数器强制初始化本计数器
    //bit2-0        000     输出模式

    InitPulseCapture();     //允许捕捉键相脉冲和A相电压脉冲中断
}
/*****end of 开始正常工作流程*****/


/*****判断输入、输出PPS误差,校正输出PPS*****/
#pragma interrupt
void AdjustPpsOutput(void)
{
    unsigned int i;

    int PpsInputSyncOutputFlag = IsCurPpsInputSyncOutput();

    if (!PpsInputSyncOutputFlag)
    {
        ++PpsSyncErrorNum;
        if (PpsSyncErrorNum >=60000)
        {
            PpsSyncErrorNum = 60000;    //防止溢出
        }
    }

    if (!PpsSyncErrorFlag && (PpsSyncErrorNum == 10))
    {
        PpsSyncErrorFlag = TRUE;
    }

    if (PpsSyncErrorNum <= 10)
    {
        PpsSyncStat = 0;
    }
    else if (PpsSyncErrorNum <= 100)
    {
        PpsSyncStat = 1;
    }
    else if (PpsSyncErrorNum <= 1000)
    {
        PpsSyncStat = 2;
    }
    else
    {
        PpsSyncStat = 3;
    }

    if (!PpsSyncErrorFlag && InputPpsComeFlag && PpsInputSyncOutputFlag)
    //if (RealFixFlag && !PpsSyncErrorFlag && InputPpsComeFlag && PpsInputSyncOutputFlag)
    // PPS同步正常且捕获到了新的输入PPS脉冲
    {
        *PpsPeriodCalRecBufPtr++ = CurrInputPpsPeriod;
        NotOkNumGPS = 0;
    }
    else
    {
        *PpsPeriodCalRecBufPtr++ = OutputPpsPeriod;
        if (++NotOkNumGPS > 10)
        {
            PpsPeriodCalRecBufPtr = &PpsPeriodCalRecBuf[0];
            PpsPeriodCalRecBufFullFlag = FALSE;
            NotOkNumGPS = 10;
        }
    }
    if (PpsPeriodCalRecBufPtr >= &PpsPeriodCalRecBuf[PPS_PERIOD_REC_BUF_SIZE])
    {
        PpsPeriodCalRecBufPtr = &PpsPeriodCalRecBuf[0];
        PpsPeriodCalRecBufFullFlag = TRUE;
    }

    if (PpsPeriodCalRecBufFullFlag)
    {
        PpsPeriodCalSum = 0;
        for (i=0; i<PPS_PERIOD_REC_BUF_SIZE; i++)
        {
            PpsPeriodCalSum += PpsPeriodCalRecBuf[i];
        }
    }

    if (!PpsSyncErrorFlag && InputPpsComeFlag && PpsInputSyncOutputFlag)
    //if (RealFixFlag && !PpsSyncErrorFlag && InputPpsComeFlag && PpsInputSyncOutputFlag)
    //捕获到了新的输入PPS脉冲且当前输入输出PPS同步正常
    {
        AdjustPps();        // 当前GPS的PPS同步良好,用GPS校正PPS输出

⌨️ 快捷键说明

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