📄 angle.c
字号:
/*-----------------------------------------------------------------------*
* Copyright (c) 2005,北京四方同创保护与控制设备有限公司稳控事业部
* All rights reserved.
*
* 文件名称:Angle.c
* 摘 要:与内电势角度测量相关的功能函数
* 采用CSS-200/1规约V1.02版
* 当前版本:2.00
* 作 者:胡炯
* 完成日期:2006.12
*-----------------------------------------------------------------------*/
#include "56807.h"
#include "CSFU107.h"
void ECaptureIsr(void); //E输入捕获中断子程序,TimerA0
void UCaptureIsr(void); //U输入捕获中断子程序,TimerA2
void TimerC1Isr(void); //15us定时器中断,Timer C1
void JudgeEStat(void); //判断E的输入状态是否正确
void JudgeUStat(void); //判断U的输入状态是否正确
void EnableECapture(void); //允许捕捉键相脉冲中断
void EnableUCapture(void); //允许捕捉电压脉冲中断
void CalAngle(void); //计算内电势绝对角和发电机功角
void AddButtonIsr(void); //补偿值调节按钮中断子程序,GPIO B0
void SubButtonIsr(void); //补偿值调节按钮中断子程序,GPIO D0
void ButtonFilter(void); //对补偿值按钮调节进行去抖处理
/*****E输入捕获中断子程序,TimerA0*****/
#pragma interrupt
void ECaptureIsr(void)
{
unsigned int TempTA0Counter;
unsigned int TempTA0Capture;
unsigned long TempEPeriodBak;
long TempL;
/*if (IntFlag & 0x8000) //for test!!!
{
IntFlag |= 0x0001;
}*/
if (E.ChangeCounter == 0) //当前未在进行去抖判断
{
//if (E.NowState != E_INPUT_STAT) //输入与记录状态不一致,对去除干扰脉冲有好处,但可能引起误判!
{
if (++E.OneSecondTrigTimes >= E.OneSecondTrigTimesLimit) //1秒内启动去抖判断的次数过多
{
E.OneSecondTrigTimes = 0;
E.ErrFlag = TRUE;
E.BufFullFlag = FALSE;
E.RisingEdgeWritePtr = &E.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE-1];
E.PeriodBufWritePtr = &E.PeriodBuf[COUNTER_QUEUE_SIZE-1];
*TMRA0_SCR &= 0xfbff; //关闭TA0中断
if (U.ChangeCounter == 0)
{
*TMRC1_SCR = 0x0000; //关闭TC1中断
}
return;
}
if (E.NowState == 0) //上升沿到来
{
TempTA0Counter = *TMRA0_CNTR;
E.CurrRisingEdgeCounter = *TMRA1_HOLD;
E.CurrRisingEdgeCounter <<= 16;
TempTA0Capture = *TMRA0_CAP;
E.CurrRisingEdgeCounter += TempTA0Capture;
if (TempTA0Counter < TempTA0Capture)
{
E.CurrRisingEdgeCounter -= 0x10000;
}
if (!E.ErrFlag) //当前E输入处于正常态
{
TempEPeriodBak = E.CurrRisingEdgeCounter - E.LastRisingEdgeCounter;
TempL = TempEPeriodBak - LastEPeriod;
if ((TempL < ContiguousEPeriodMaxErr) && (TempL > -ContiguousEPeriodMaxErr))
//当前E周期与上一个E周期的误差在允许范围内
{
ECaptureFlag = 1;
}
else
{
TempL = TempEPeriodBak / 2 - LastEPeriod;
if ((TempL < ContiguousEPeriodMaxErr) && (TempL > -ContiguousEPeriodMaxErr))
//当前E周期的1/2与上个E周期的误差在允许范围内,对应出现了1个错误E脉冲的情况
{
ECaptureFlag = 2;
}
else
{
TempL = TempEPeriodBak / 3 - LastEPeriod;
if ((TempL < ContiguousEPeriodMaxErr) && (TempL > -ContiguousEPeriodMaxErr))
//当前E周期的1/3与上个E周期的误差在允许范围内,对应出现了2个错误E脉冲的情况
{
ECaptureFlag = 3;
}
else
{
TempL = TempEPeriodBak / 4 - LastEPeriod;
if ((TempL < ContiguousEPeriodMaxErr) && (TempL > -ContiguousEPeriodMaxErr))
//当前E周期的1/4与上个E周期的误差在允许范围内,对应出现了3个错误E脉冲的情况
{
ECaptureFlag = 4;
}
else
{
ECaptureFlag = 0;
}
}
}
}
}
else //当前E输入处于非正常态
{
ECaptureFlag = 1;
}
if (ECaptureFlag > 0) //上升沿到来时间符合要求
//进行上升沿判断时,如果当前E输入处于非正常态,则每次去抖判断完成,均认为是真实跳变
//如果当前E输入处于正常态,则当前E周期与上一个E周期相比变化必须小于0.2%(频率变化不超过0.1Hz),
//或当前E周期的1/2与上一个E周期相比变化必须小于0.2%(频率变化不超过0.1Hz),才认为是真实上升沿跳变
{
E.ChangeCounter = 4;
E.IntTimes = 1;
E.FilterLastTime = 0;
*TMRC1_SCR |= 0x4000; //开启TC1中断
}
else //上升沿到来时间不合要求
{
asm(nop);
}
}
else //下降沿到来
{
E.ChangeCounter = 4;
E.IntTimes = 1;
E.FilterLastTime = 0;
*TMRC1_SCR |= 0x4000; //开启TC1中断
}
}
}
else //当前正在进行去抖判断
{
if (++E.IntTimes >= E.IntTimesLimit) //进入中断次数过多,认为E输入存在问题
{
E.ChangeCounter = 0;
E.ErrFlag = TRUE;
E.BufFullFlag = FALSE;
E.RisingEdgeWritePtr = &E.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE-1];
E.PeriodBufWritePtr = &E.PeriodBuf[COUNTER_QUEUE_SIZE-1];
*TMRA0_SCR &= 0xfbff; //关闭TA0中断
if (U.ChangeCounter == 0)
{
*TMRC1_SCR = 0x0000; //关闭TC1中断
}
return;
}
}
*TMRA0_SCR &= 0xf7ff; //允许再次触发中断
}
/*****end of E输入捕获中断子程序,TimerA0*****/
/*****U输入捕获中断子程序,TimerA2*****/
#pragma interrupt
void UCaptureIsr(void)
{
unsigned int TempTA2Counter;
unsigned int TempTA2Capture;
/*if (IntFlag & 0x8000) //for test!!!
{
IntFlag |= 0x0002;
}*/
if (U.ChangeCounter == 0) //当前未在进行去抖判断
{
//if (U.NowState != U_INPUT_STAT) //输入与记录状态不一致,对去除窄干扰脉冲有好处,但可能引起误判!
{
if (++U.OneSecondTrigTimes >= U.OneSecondTrigTimesLimit) //1秒内启动去抖判断的次数过多
{
U.OneSecondTrigTimes = 0;
U.ErrFlag = TRUE;
U.BufFullFlag = FALSE;
U.RisingEdgeWritePtr = &U.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE-1];
U.PeriodBufWritePtr = &U.PeriodBuf[COUNTER_QUEUE_SIZE-1];
*TMRA2_SCR &= 0xfbff; //关闭TA2中断
if (E.ChangeCounter == 0)
{
*TMRC1_SCR = 0x0000; //关闭TC1中断
}
return;
}
U.ChangeCounter = 6;
U.IntTimes = 1;
U.FilterLastTime = 0;
if (U.NowState == 0) //只记录上升沿对应的计数值
{
TempTA2Counter = *TMRA2_CNTR;
U.CurrRisingEdgeCounter = *TMRA3_HOLD;
U.CurrRisingEdgeCounter <<= 16;
TempTA2Capture = *TMRA2_CAP;
U.CurrRisingEdgeCounter += TempTA2Capture;
if (TempTA2Counter < TempTA2Capture)
{
U.CurrRisingEdgeCounter -= 0x10000;
}
}
*TMRC1_SCR |= 0x4000; //开启TC1中断
}
}
else //当前正在进行去抖判断
{
if (++U.IntTimes >= U.IntTimesLimit) //进入中断次数过多,认为U输入存在问题
{
U.ChangeCounter = 0;
U.ErrFlag = TRUE;
U.BufFullFlag = FALSE;
U.RisingEdgeWritePtr = &U.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE-1];
U.PeriodBufWritePtr = &U.PeriodBuf[COUNTER_QUEUE_SIZE-1];
*TMRA2_SCR &= 0xfbff; //关闭TA2中断
if (E.ChangeCounter == 0)
{
*TMRC1_SCR = 0x0000; //关闭TC1中断
}
return;
}
}
*TMRA2_SCR &= 0xf7ff; //允许再次触发中断
}
/*****end of U输入捕获中断子程序,TimerA2*****/
/*****15us定时器中断,Timer C1*****/
#pragma interrupt
void TimerC1Isr(void)
{
unsigned int TempFlag;
/*if (IntFlag & 0x8000) //for test!!!
{
IntFlag |= 0x0004;
}*/
TempFlag = 0;
if (E.ChangeCounter)
{
if (++E.FilterLastTime >= E.MaxDelayTime)
{
E.ChangeCounter = 0;
}
else
{
if (E.NowState != E_INPUT_STAT)
{
if (++E.ChangeCounter >= E.ChangeCounterLimit) //通过去抖判断
{
E.ChangeCounter = 0;
if (E.NowState == 0) //刚通过上升沿的去抖判断
{
E.NowState = 0x0100;
E.ErrorLastTime = 0; //收到有效的E数据
E.RisingEdgeWritePtr++;
E.PeriodBufWritePtr++;
if (E.RisingEdgeWritePtr >= &E.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE])
{
E.RisingEdgeWritePtr = &E.RisingEdgeCounterBuf[0];
E.PeriodBufWritePtr = &E.PeriodBuf[0];
}
*E.RisingEdgeWritePtr = E.CurrRisingEdgeCounter;
if (ECaptureFlag == 2)
{
LastEPeriod = (E.CurrRisingEdgeCounter - E.LastRisingEdgeCounter) / 2;
}
else if (ECaptureFlag == 3)
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
LastEPeriod = (E.CurrRisingEdgeCounter - E.LastRisingEdgeCounter) / 3;
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
}
else if (ECaptureFlag == 4)
{
LastEPeriod = (E.CurrRisingEdgeCounter - E.LastRisingEdgeCounter) / 4;
}
else
{
LastEPeriod = E.CurrRisingEdgeCounter - E.LastRisingEdgeCounter;
}
*E.PeriodBufWritePtr = LastEPeriod;
E.LastRisingEdgeCounter = E.CurrRisingEdgeCounter;
if (E.RisingEdgeWritePtr == &E.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE-1])
{
E.BufFullFlag = TRUE;
}
}
else //刚通过下降沿的去抖判断
{
E.NowState = 0;
}
}
}
else
{
if (E.ChangeCounter > 0)
{
E.ChangeCounter --;
}
}
}
}
if (U.ChangeCounter)
{
if (++U.FilterLastTime >= U.MaxDelayTime)
{
U.ChangeCounter = 0;
}
else
{
if (U.NowState != U_INPUT_STAT)
{
if (++U.ChangeCounter >= U.ChangeCounterLimit) //通过去抖判断
{
U.ChangeCounter = 0;
if (U.NowState == 0) //刚通过上升沿的去抖判断
{
U.NowState = 0x0100;
U.ErrorLastTime = 0; //收到有效的U数据
U.RisingEdgeWritePtr++;
U.PeriodBufWritePtr++;
if (U.RisingEdgeWritePtr >= &U.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE])
{
U.RisingEdgeWritePtr = &U.RisingEdgeCounterBuf[0];
U.PeriodBufWritePtr = &U.PeriodBuf[0];
}
*U.RisingEdgeWritePtr = U.CurrRisingEdgeCounter;
*U.PeriodBufWritePtr = U.CurrRisingEdgeCounter - U.LastRisingEdgeCounter;
U.LastRisingEdgeCounter = U.CurrRisingEdgeCounter;
if (U.RisingEdgeWritePtr == &U.RisingEdgeCounterBuf[COUNTER_QUEUE_SIZE-1])
{
U.BufFullFlag = TRUE;
}
}
else //刚通过下降沿的去抖判断
{
U.NowState = 0;
}
}
}
else
{
if (U.ChangeCounter > 0)
{
U.ChangeCounter --;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -