📄 main.c
字号:
/*-----------------------------------------------------------------------*
* 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 + -