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

📄 angle.c

📁 一个串口终端解释程序。用于单片机调试串口的超级终端应用。
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
    }

    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 + -