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

📄 main.c

📁 一个串口终端解释程序。用于单片机调试串口的超级终端应用。
💻 C
📖 第 1 页 / 共 3 页
字号:
    }
    else if (RealFixFlag && InputPpsComeFlag && PpsInputSyncOutputFlag)
    // PPS同步不正常,但GPS锁星正常且捕获到了新的输入PPS脉冲且当前输入输出PPS同步正常,说明GPS开始转入正常
    {
        for (i=(PPS_ERR_REC_BUF_SIZE-1); i>=1; i--)
        {
            PpsInputOutputErrCnt[i] = PpsInputOutputErrCnt[i-1];
        }
        PpsInputOutputErrCnt[0] = CurrInputPpsCounter - OutputPpsCounter;

        OutputPpsPeriod = AveragePpsPeriod + PpsInputOutputErrCnt[0];   //此次输出的PPS周期在平均值左右
        PpsSyncErrorNum = 8;    //如果后几秒同步失败,能够快速将PpsSyncErrorFlagGPS置位
        PpsSyncErrorFlag = 0;
        ResidueAdd = 0;
    }
    else if (PpsSyncErrorFlag && RealFixFlag && InputPpsComeFlag)
    // GPS较长时间同步错误,当前GPS的PPS输入与输出PPS不同步,说明输出PPS守时可能已有较大偏离
    // GPS锁星正常且捕获到新的输入PPS
    {
        for (i=(PPS_ERR_REC_BUF_SIZE-1); i>=1; i--)
        {
            PpsInputOutputErrCnt[i] = PpsInputOutputErrCnt[i-1];
        }
        PpsInputOutputErrCnt[0] = CurrInputPpsCounter - OutputPpsCounter;

        if (PpsInputOutputErrCnt[0] < (-20000000))
        {
            OutputPpsPeriod = AveragePpsPeriod + PpsInputOutputErrCnt[0];
            OutputPpsPeriod += AveragePpsPeriod;
        }
        else
        {
            OutputPpsPeriod = AveragePpsPeriod + PpsInputOutputErrCnt[0];
        }
        ResidueAdd = 0;
    }
    else    // GPS失锁且未捕获到新的输入PPS
    {
        KeepPpsOutput();    //利用存储的平均值维持PPS输出
    }

    OutputPpsCounter += OutputPpsPeriod;        //设定虚拟PPS上升沿输出时间

    InputPpsComeFlag = 0;
}
/*****end of 判断输入、输出PPS误差,校正输出PPS*****/


/*****判断并返回当前的输入PPS是否与输出PPS同步良好*****/
#pragma interrupt
int IsCurPpsInputSyncOutput(void)
{
    long TempL;

    TempL = CurrInputPpsCounter - OutputPpsCounter;
    if (((-INPUT_OUTPUT_PPS_ERROR) < TempL) && (TempL < INPUT_OUTPUT_PPS_ERROR))    //PPS同步良好
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
/*****end of 判断并返回当前的输入PPS是否与输出PPS同步良好*****/


/*****利用GPS授时信号校准输出PPS*****/
#pragma interrupt
void AdjustPps(void)
{
    unsigned int i;
    long lErrorCntGPS, lErrorCorr;

    for (i=(PPS_ERR_REC_BUF_SIZE-1); i>=1; i--)
    {
        PpsInputOutputErrCnt[i] = PpsInputOutputErrCnt[i-1];
    }
    PpsInputOutputErrCnt[0] = CurrInputPpsCounter - OutputPpsCounter;

    if (PpsPeriodCalRecBufFullFlag)
    {
        OutputPpsPeriod = PpsPeriodCalSum / PPS_PERIOD_REC_BUF_SIZE;
        OutputPpsResidue += PpsPeriodCalSum - OutputPpsPeriod * PPS_PERIOD_REC_BUF_SIZE;
        if (OutputPpsResidue >= PPS_PERIOD_REC_BUF_SIZE)
        {
            OutputPpsPeriod += 1;
            OutputPpsResidue -= PPS_PERIOD_REC_BUF_SIZE;
        }

        asm (BFSET #0x0300, SR);        //禁用所有可屏蔽中断
        lErrorCntGPS = (PpsInputOutputErrCnt[0] * 3 + PpsInputOutputErrCnt[1] * 2 + PpsInputOutputErrCnt[2]) / 6;
        asm (BFCLR #0x0200, SR);        //开启可屏蔽中断

        if (lErrorCntGPS > PPS_ERROR_CNT_LEVEL / 2 || lErrorCntGPS < 5)
        {
            lErrorCorr = NormanizeErrCorr(lErrorCntGPS / 2);
            OutputPpsPeriod += lErrorCorr;
        }
        else
        {
            asm (BFSET #0x0300, SR);        //禁用所有可屏蔽中断
            lErrorCorr = lErrorCntGPS * lErrorCntGPS / PPS_ERROR_CNT_LEVEL;
            asm (BFCLR #0x0200, SR);        //开启可屏蔽中断

            lErrorCorr = (lErrorCntGPS > 0) ? lErrorCorr : (-lErrorCorr);
            lErrorCorr = NormanizeErrCorr(lErrorCorr);
            OutputPpsPeriod = OutputPpsPeriod + lErrorCorr;
        }
    }
    else
    {
        if (((-INPUT_OUTPUT_PPS_ERROR) < PpsInputOutputErrCnt[1]) && (PpsInputOutputErrCnt[1] < INPUT_OUTPUT_PPS_ERROR))
        {
            OutputPpsPeriod = OutputPpsPeriod - PpsInputOutputErrCnt[1] + 2*PpsInputOutputErrCnt[0];
        }
        else
        {
            OutputPpsPeriod += PpsInputOutputErrCnt[0];
        }
    }
    PpsSyncErrorNum = 0;
    ResidueAdd = 0;
  	RecPpsPeriod(CurrInputPpsPeriod);   //记录正常的PPS间隔
  	
  	PpsLedOnFlag = TRUE;	//2007.1 PPS指示灯点亮
}
/*****end of 利用GPS授时信号校准输出PPS*****/


/*****规格化误差校正值*****/
#pragma interrupt
long NormanizeErrCorr(long lErrorCorr)
{
    if (lErrorCorr > 3)
    {
        lErrorCorr = 3;
    }
    else if (lErrorCorr < -3)
    {
        lErrorCorr = -3;
    }
    return lErrorCorr;
}
/*****end of 规格化误差校正值*****/


/*****记录正确的秒脉冲周期****/
#pragma interrupt
void RecPpsPeriod(unsigned long PpsPeriod)
{
    *PpsPeriodRecBufPtr++ = PpsPeriod;
    if (PpsPeriodRecBufPtr >= &PpsPeriodRecBuf[PPS_PERIOD_REC_BUF_SIZE])
    {
        PpsPeriodRecBufPtr = &PpsPeriodRecBuf[0];
        PpsPeriodRecBufFullFlag = TRUE;
    }
}
/*****end of 记录正确的秒脉冲周期****/


/*****利用存储的平均值维持PPS输出*****/
#pragma interrupt
void KeepPpsOutput(void)
{
    OutputPpsPeriod = AveragePpsPeriod;

    ResidueAdd += AveragePpsResidue;    //余数补偿
    if (ResidueAdd >= PPS_PERIOD_REC_BUF_SIZE)
    {
        OutputPpsPeriod += 1;
        ResidueAdd -= PPS_PERIOD_REC_BUF_SIZE;
    }
}
/*****end of 利用存储的平均值维持PPS输出*****/


/*****处理SOC时间*****/
#pragma interrupt
void DealSoc(void)
{
    unsigned long *TempULPtr;
    unsigned long TempUL;
    unsigned int i;
    
	if ((Time == (LastTime+1)) && RealFixFlag)
	{
		SocStableCounter ++;
		if (SocStableCounter > 8)
		{
			SocStableCounter = 8;
		}
	}	
	else
	{
		SocStableCounter = 0;
	}
	LastTime = Time;	
	
    if (SocStableCounter >= 8) //时标稳定可靠
    {                                                      
        Soc = Time + 1;         //Time是解析串口报文得到的时间,表示前一个秒脉冲对应的时刻,Soc是上送报文的GPS时标
        //UploadLeapSecond = LeapSecond;    2007.1 闰秒一旦更改立即上送,不再等待整秒
    }
    else                        //对应串口报文接收中断一些时间的情况
    {	//时间报文不可用,自维持SOC
        if (Soc != 0)          //程序初始化后Soc等于0,只有在接收到有效时标后,Soc累加才有意义
        {
            Soc++;				
        }
        
        NoSocCounter ++;
        if (NoSocCounter >= 20000)    //防止溢出
        {
            NoSocCounter = 20000;
        }
    }
    
    //2007.1
    if (CPU_VERSION_LARGE >= 2)
    {
        if (Soc != 0)
        {
            UploadSoc = Soc - UploadLeapSecond;     //V2.00以上版本对闰秒进行补偿
        }
    }
    else
    {        
        UploadSoc = Soc;
    }

    GpsLockErr = FixType;   //GPS锁星状况
    
    if (NoSocCounter >= 10) //超过10秒没有收到有效SOC时间
    {
        SocErr = 1;         //GPS串口对时丢失超过10秒        
    }
    
    
    //2007.1 增加GPS卫星失锁时间的标识
    if (!RealFixFlag)
    {
    	GpsNotFixCnt++;
    }
    else
    {
    	GpsNotFixCnt = 0;
    }    	
    
    if (GpsNotFixCnt >=60000)
    {
        GpsNotFixCnt = 60000;    //防止溢出
    }
  
    if (GpsNotFixCnt <= 10)
    {
        GpsLockStat = 0;
    }
    else if (GpsNotFixCnt <= 100)
    {
        GpsLockStat = 1;
    }
    else if (GpsNotFixCnt <= 1000)
    {
        GpsLockStat = 2;
    }
    else
    {
        GpsLockStat = 3;
    }
    

    if (++Sci1RecErrTime >= 20)     //连续20秒没有收到正确的GPS时钟报文
    {
        Sci1RecErrTime = 20;        //防止溢出
        Sci1RecErrFlag = TRUE;
        if (!Sci1SendFlag)  //如果当前SCI1未在发送数据,重新初始化串口
        {
            Sci1RecErrTime = 0;
            ClockRecFinishCounter = 0;
            InitSci1RecVariable();  //初始化串口接收缓冲区
            InitSci1TransVariable();
            InitSci1Rec();  //初始化SCI1,通过串口接收GPS时间信息
            if (*SCI1_SCISR & 0x0f00)
            {
                *SCI1_SCISR &= 0xf0ff;
                asm(nop);
                asm(nop);
                InitSci1Rec();  //初始化SCI1,通过串口接收GPS时间信息
            }
        }
    }
    
    /*计算PPS周期平均值*/
    if (PpsOutputFlag && RealFixFlag)   //开始输出PPS且锁星正常
    {
        if ((Soc & 0x0000003f) == 0)    //每64秒计算一次
        {
            TempULPtr = &PpsPeriodRecBuf[0];
            if (PpsPeriodRecBufFullFlag)        //只有当秒脉冲周期缓冲区存满后才开始计算
            {
                TempUL = 0;
                for (i=0; i<PPS_PERIOD_REC_BUF_SIZE; i++)
                {
                    TempUL += *TempULPtr++;
                }
                AveragePpsPeriodBak = TempUL / PPS_PERIOD_REC_BUF_SIZE;
                AveragePpsResidueBak = TempUL - AveragePpsPeriod * PPS_PERIOD_REC_BUF_SIZE;
                
                if ((MinPpsPeriod  < AveragePpsPeriodBak) && (AveragePpsPeriodBak < MaxPpsPeriod))    //秒脉冲周期在限定范围内
                {
                    AveragePpsPeriod = AveragePpsPeriodBak;
                    AveragePpsResidue = AveragePpsResidueBak;
                }
            }
        }
    }
    /*end of 计算PPS周期平均值*/    
}
/*****end of 处理SOC时间*****/


/*****1ms定时器中断,Timer D3*****/
#pragma interrupt
void TimerD3Isr(void)
{
    unsigned int i;
    unsigned int TempUI;
    unsigned long CurrTimerCounter;
    long TempL;

⌨️ 快捷键说明

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