📄 angle.c
字号:
}
}
if ((E.ChangeCounter == 0) && (U.ChangeCounter == 0))
{
*TMRC1_SCR = 0x0000; //关闭TC1中断
}
else
{
*TMRC1_SCR &= 0x7fff; //允许再次触发中断
}
}
/*****end of 15us定时器中断,Timer C1*****/
/*****判断E的输入状态是否正确*****/
#pragma interrupt
void JudgeEStat(void)
{
unsigned long TempUL;
unsigned long TempEPeriod;
long TempEPeriodErr;
unsigned int TempFlag;
unsigned long *TempEPeriodBufWritePtr;
if (E.ErrorLastTime >= 2000)
//在E输入状态正常的情况下,如果连续2秒未收到有效E数据,则重新初始化E输入部分
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
E.ErrorLastTime = 0;
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中断
}
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
}
else if (E.BufFullFlag) //只有在E的缓冲区已经存满的时候才进行判断
{
if (E.ErrFlag)
{
//计算发电机极对数
TempEPeriodBufWritePtr = E.PeriodBufWritePtr; //使用临时变量,中断程序有可能更改E.PeriodBufWritePtr
TempEPeriod = *TempEPeriodBufWritePtr;
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
PolePairsNum = TempEPeriod / MAIN_FREQ_PERIOD;
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
TempUL = TempEPeriod - PolePairsNum * MAIN_FREQ_PERIOD;
if (TempUL > MAIN_FREQ_PERIOD/2)
{
PolePairsNum += 1;
}
if (PolePairsNum == 0) //输入异常,直接退出
{
return;
}
E.MinPeriod = (MAIN_FREQ_PERIOD - E_PERIOD_MAX_ERROR) * PolePairsNum;
E.MaxPeriod = (MAIN_FREQ_PERIOD + E_PERIOD_MAX_ERROR) * PolePairsNum;
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
ContiguousEPeriodMaxErr = E_E_ERROR * PolePairsNum;
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
}
E.NormalPeriodNum = 0;
TempEPeriodBufWritePtr = E.PeriodBufWritePtr + 1; //使用临时变量,中断程序有可能更改E.PeriodBufWritePtr
if (TempEPeriodBufWritePtr >= &E.PeriodBuf[COUNTER_QUEUE_SIZE])
{
TempEPeriodBufWritePtr = &E.PeriodBuf[0];
}
if ((TempEPeriodBufWritePtr + 1) >= &E.PeriodBuf[COUNTER_QUEUE_SIZE])
{
E.CalPeriodPtr = &E.PeriodBuf[0];
}
else
{
E.CalPeriodPtr = TempEPeriodBufWritePtr + 1;
}
E.PeriodSum = 0;
for (;;)
{
if ((*E.CalPeriodPtr > E.MinPeriod) && (*E.CalPeriodPtr < E.MaxPeriod))
{
TempEPeriod = *E.CalPeriodPtr;
TempFlag = TRUE;
}
else
{
TempFlag = FALSE;
}
if (++E.CalPeriodPtr >= &E.PeriodBuf[COUNTER_QUEUE_SIZE])
{
E.CalPeriodPtr = &E.PeriodBuf[0];
}
if (E.CalPeriodPtr == TempEPeriodBufWritePtr)
{
break;
}
if (TempFlag)
{
TempEPeriodErr = *E.CalPeriodPtr - TempEPeriod;
if ((TempEPeriodErr > (-ContiguousEPeriodMaxErr)) && (TempEPeriodErr < ContiguousEPeriodMaxErr))
{
E.PeriodSum += TempEPeriod;
E.NormalPeriodNum ++;
}
}
}
if (E.ErrFlag)
{
if (E.NormalPeriodNum >= (COUNTER_QUEUE_SIZE - 2))
//如果原来E输入处于异常状态,则缓冲区中的E周期必须都符合要求,才认为E输入可用
{
E.ErrFlag = FALSE;
E.OldRisingEdgeBufPtr = E.RisingEdgeWritePtr;
}
}
else
{
if (E.NormalPeriodNum <= (COUNTER_QUEUE_SIZE - 4))
//如果原来E输入处于正常状态,则如果在最近18个E的周期中有2个以上不符合要求,认为E输入不可用
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
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中断
}
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
}
}
if (E.ErrFlag == 0)
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
E.AveragePeriod = E.PeriodSum / E.NormalPeriodNum;
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
TempUL = E.PeriodSum - E.AveragePeriod * E.NormalPeriodNum;
if (TempUL > E.NormalPeriodNum / 2)
{
E.AveragePeriod += 1;
}
/*****诊断PolePairsNum错误,应对频率大范围慢变的情况*****/
E.MinPeriod = (MAIN_FREQ_PERIOD - E_PERIOD_MAX_ERROR) * PolePairsNum;
E.MaxPeriod = (MAIN_FREQ_PERIOD + E_PERIOD_MAX_ERROR) * PolePairsNum;
if ((E.AveragePeriod < E.MinPeriod) || (E.AveragePeriod > E.MaxPeriod))
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
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中断
}
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
return;
}
/*****end of 诊断PolePairsNum错误,应对频率大范围慢变的情况*****/
E.MinPeriod = E.AveragePeriod - E_PERIOD_MIN_ERROR * PolePairsNum;
E.MaxPeriod = E.AveragePeriod + E_PERIOD_MIN_ERROR * PolePairsNum;
}
}
}
/*****判断E的输入状态是否正确*****/
/*****判断U的输入状态是否正确*****/
#pragma interrupt
void JudgeUStat(void)
{
unsigned long TempUL;
unsigned long *TempUPeriodBufWritePtr;
if (U.ErrorLastTime >= 2000)
//在U输入状态正常的情况下,如果连续2秒未收到有效U数据,则重新初始化U输入部分
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
U.ErrorLastTime = 0;
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中断
}
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
}
else if (U.BufFullFlag) //只有在U的周期缓冲区已经存满的时候才进行判断
{
if (U.ErrFlag) //U输入异常时允许U周期与工频周期偏差1ms
{
U.MinPeriod = MAIN_FREQ_PERIOD - U_PERIOD_MAX_ERROR;
U.MaxPeriod = MAIN_FREQ_PERIOD + U_PERIOD_MAX_ERROR;
}
U.NormalPeriodNum = 0;
TempUPeriodBufWritePtr = U.PeriodBufWritePtr + 1; //使用临时变量,中断程序有可能更改U.PeriodBufWritePtr
if (TempUPeriodBufWritePtr >= &U.PeriodBuf[COUNTER_QUEUE_SIZE])
{
TempUPeriodBufWritePtr = &U.PeriodBuf[0];
}
if ((TempUPeriodBufWritePtr + 1) >= &U.PeriodBuf[COUNTER_QUEUE_SIZE])
{
U.CalPeriodPtr = &U.PeriodBuf[0];
}
else
{
U.CalPeriodPtr = TempUPeriodBufWritePtr + 1;
}
U.PeriodSum = 0;
for (;;)
{
if ((*U.CalPeriodPtr > U.MinPeriod) && (*U.CalPeriodPtr < U.MaxPeriod))
{
U.PeriodSum += *U.CalPeriodPtr;
U.NormalPeriodNum ++;
}
if (++U.CalPeriodPtr >= &U.PeriodBuf[COUNTER_QUEUE_SIZE])
{
U.CalPeriodPtr = &U.PeriodBuf[0];
}
if (U.CalPeriodPtr == TempUPeriodBufWritePtr)
{
break;
}
}
if (U.ErrFlag)
{
if (U.NormalPeriodNum >= (COUNTER_QUEUE_SIZE - 1))
//如果原来U输入处于异常状态,则缓冲区中的U周期必须都符合要求,才认为U输入可用
{
U.ErrFlag = 0;
U.OldRisingEdgeBufPtr = U.RisingEdgeWritePtr;
}
}
else
{
if (U.NormalPeriodNum <= (COUNTER_QUEUE_SIZE - 10))
//如果原来U输入处于正常状态,则如果在最近20个U的周期中只有不到10个正常,认为U输入不可用
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
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中断
}
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
}
}
if ((U.ErrFlag == 0) && (U.NormalPeriodNum >= (COUNTER_QUEUE_SIZE - 3)))
{
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
U.AveragePeriod = U.PeriodSum / U.NormalPeriodNum;
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
TempUL = U.PeriodSum - U.AveragePeriod * U.NormalPeriodNum;
if (TempUL > U.NormalPeriodNum / 2)
{
U.AveragePeriod += 1;
}
U.MinPeriod = U.AveragePeriod - U_PERIOD_MIN_ERROR;
U.MaxPeriod = U.AveragePeriod + U_PERIOD_MIN_ERROR;
}
}
}
/*****判断U的输入状态是否正确*****/
/*****允许捕捉键相脉冲中断*****/
#pragma interrupt
void EnableECapture(void)
{
if ((*TMRA0_SCR & 0x0400) == 0)
{
*TMRA0_SCR &= 0xf7ff; //清除原有中断标志
*TMRA0_SCR |= 0x0400; //开启compare中断
//bit11(IEF) 0 输入信号边沿触发(CAPTURE)标志
//bit10(IEFIE) 1 1——允许输入信号边沿触发中断(捕捉发生时发出中断)
}
}
/*****end of 允许捕捉键相脉冲中断*****/
/*****允许捕捉电压脉冲中断*****/
#pragma interrupt
void EnableUCapture(void)
{
if ((*TMRA2_SCR & 0x0400) == 0)
{
*TMRA2_SCR &= 0xf7ff; //清除原有中断标志
*TMRA2_SCR |= 0x0400; //开启compare中断
//bit11(IEF) 0 输入信号边沿触发(CAPTURE)标志
//bit10(IEFIE) 1 1——允许输入信号边沿触发中断(捕捉发生时发出中断)
}
}
/*****end of 允许捕捉电压脉冲中断*****/
/*****计算内电势绝对角和发电机功角*****/
#pragma interrupt
void CalAngle(void)
{
unsigned long TempMainFreqPeriodCounter; //工频整周期时刻对应的计数值
unsigned long TempEPeriod; //当前E周期对应的计数值
unsigned long TempEOnePolePeriod; //当前E周期对应的计数值,折算到单对极
unsigned long TempERisingEdgeCounter; //E上升沿的计数值
unsigned long *TempERisingEdgeWritePtr; //E上升沿计数值缓冲区的写指针
unsigned long TempURisingEdgeCounter; //U上升沿的计数值
unsigned long *TempURisingEdgeWritePtr; //U上升沿计数值缓冲区的写指针
long RisingEdgeDiffL; //上升沿时刻相差的计数值
unsigned long RisingEdgeDiffUL; //上升沿时刻相差的计数值(UL型)
unsigned int TempUI;
unsigned long TempUL1, TempUL2;
asm (BFSET #0x0300, SR); //禁用所有可屏蔽中断
TempERisingEdgeCounter = *E.RisingEdgeWritePtr;
TempERisingEdgeWritePtr = E.RisingEdgeWritePtr;
TempEPeriod = *E.PeriodBufWritePtr;
TempURisingEdgeCounter = *U.RisingEdgeWritePtr;
TempURisingEdgeWritePtr = U.RisingEdgeWritePtr;
asm (BFCLR #0x0200, SR); //开启可屏蔽中断
EinErrFlag = 1; //标志位全部置错误
UinErrFlag = 1;
EAngleNoEffectFlag = 1;
PowerAngleNoEffectFlag = 1;
RotateSpeedNoEffectFlag = 1;
//for test
*EAbsoluteAngleBufPtr = 0;
*RotateSpeedBufPtr = 0;
*PowerAngleBufPtr = 0;
//end for test
TempMainFreqPeriodCounter = *PeriodCounterQueuePtr++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -