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

📄 main.c

📁 一个串口终端解释程序。用于单片机调试串口的超级终端应用。
💻 C
📖 第 1 页 / 共 3 页
字号:
    //IntFlag |= 0x8000;    //for test!!!

    TempUI = *TMRD0_CNTR;
    CurrTimerCounter = *TMRD1_HOLD;
    CurrTimerCounter <<= 16;
    CurrTimerCounter += TempUI;

    *TMRD3_SCR &= 0x7fff;   //允许再次触发Compare中断
    //在此处清除而不是在程序出口处清除中断申请标志的原因是:如果此次中断程序的处理时间过长,在处理过程中又产生了一次新的中断申请,
    //则中断申请标志会再次置位,完成中断后会保证再次进入TD3中断,1秒内的TD3中断次数仍为1000次

    *IPR = 0x0200;      //只允许6级中断(PLR设置为7的中断)
    asm (BFCLR #$0200,SR);  //允许可屏蔽中断

    if (++CurrTD3IntCounter >= 1000)
    {
        CurrTD3IntCounter = 0;
    }

    RecTd3OverflowCounter(CurrTimerCounter);    //记录TD3溢出时刻,用于测试

    if (CurrTD3IntCounter == 0)     //调整TD3溢出时间与PPS上升沿同步
    {
        //RecOutputPpsCounter(CurrTimerCounter);    //记录输出PPS上升沿计数器值,用于测试
        RecOutputPpsCounter(OutputPpsCounter);  //记录输出PPS上升沿计数器值,用于测试OutputPpsCounter

        TempL = CurrTimerCounter - OutputPpsCounter;
        if ((TempL > -12000) && (TempL < 12000))
        //同步误差在300us以内时,调整1ms中断溢出时间与PPS上升沿同步
        {
            *TMRD3_CMP1 = 40000 - TempL;
        }
        else
        //同步误差大于300us时,重启系统
        {
            asm (BFSET #0x0300, SR);        //禁用所有可屏蔽中断
            for(;;)
            {
                for (i=0; i<0xffff; i++)
                {
                    asm(nop);   //令系统重启
                }
                asm(BFCHG #0x0020, X:$13e1);    //ALERT1指示灯闪烁
            }
        }

        DealSoc();      //DealSoc

        E.OneSecondTrigTimes = 0;
        U.OneSecondTrigTimes = 0;

        if (FirstOutputPpsFlag) //在第2秒起始时刻清除首个PPS输出标志
        {
            FirstOutputPpsFlag = 0;
        }
    }
    else if (CurrTD3IntCounter == 1)    //PPS到来后1ms
    {
        *TMRD3_CMP1 = 40000;    //恢复TD3定时中断计数为标准值
        CalPeriodCounterQueue();    //计算当前一秒内工频整周期时刻对应的计数值
    }
    else if (CurrTD3IntCounter == 3)    //PPS到来后3ms
    {
        if (!FirstOutputPpsFlag)
        {
            AdjustPpsOutput();      //调整虚拟PPS输出时间
        }
    }
    else if (CurrTD3IntCounter == 10)   //PPS到来后10ms
    {
        LedOutput();    //判断装置状态,驱动指示灯
    }
    else if (CurrTD3IntCounter == 30)   //PPS到来后30ms
    {
        if (E.ErrFlag)  //键相脉冲输入不可用
        {
            EnableECapture();   //允许捕捉键相脉冲中断
        }
    }
    else if (CurrTD3IntCounter == 50)   //PPS到来后50ms
    {
        if (U.ErrFlag)  //键相脉冲输入不可用
        {
            EnableUCapture();   //允许捕捉电压脉冲中断
        }
    }
    else if (CurrTD3IntCounter == 350)  //PPS到来后350ms
    {
        //熄灭所有状态正常指示灯
        PULSE_LED_TURN_OFF;
        UIN_LED_TURN_OFF;
        CLOCK_LED_TURN_OFF;
        PPS_LED_TURN_OFF;
    }
    else if (CurrTD3IntCounter == 450)  //PPS到来后450ms
    {
        if (++Sci0RecErrCounter >= 5)   //连续5秒未收到RCM3200的串口应答报文,认为串口通信出错
        {
            Sci0ErrFlag = 1;
        }
        else
        {
            Sci0ErrFlag = 0;
        }
        WriteRcm3200PatrolRpt();    //填写RCM3200串口巡检报文缓冲区
    }
    else if (CurrTD3IntCounter == 979)  //PPS到来后979ms
    {
        JudgeUStat();   //判断U的输入状态是否正确
    }
    else if (CurrTD3IntCounter == 980)  //PPS到来后980ms
    {
        JudgeEStat();   //判断E的输入状态是否正确
    }
    else
    {
        asm (BFSET #0x0300, SR);        //禁用所有可屏蔽中断
        TempUI = CurrTD3IntCounter / 20;
        asm (BFCLR #0x0200, SR);        //开启可屏蔽中断

        i = CurrTD3IntCounter - TempUI * 20;
        if (i == 2) //整周期后2ms时刻进行数据处理工作
        {
            CurrSmpcnt = TempUI * 96;   //均为整周期时刻的smpcnt
            CalAngle();     //计算内电势绝对角和发电机功角
            WriteRcm3200DataRpt();  //填写内电势测量数据报文缓冲区
        }
        else if (i == 10)   //整周期后10ms时刻进行DA输出判断,避开上送串口报文时间
        {
            DaOutputJudgeFlag = TRUE;
        }
    }

    //判断SCI1的接收/发送状态切换时间
    if ((ClockRecFinishCounter > 0) && (ClockRecFinishCounter < 300))   //Sci1在GPS报文接收完毕后300ms内允许切换到发送状态
    {
        ClockRecFinishCounter++;
    }
    if ((Sci1SwitchCounter > 0) && (Sci1SwitchCounter < 20))    //Sci1发送/接收状态切换计数20ms
    {
        Sci1SwitchCounter++;
    }

    //检测DA芯片错误状态
    if (DA_FAULT_DETECT == 0)
    {
        DaErrFlag = 1;
    }
    else
    {
        DaErrFlag = 0;
    }

    if (!E.ErrFlag)
    {
        E.ErrorLastTime++;
    }
    if (!U.ErrFlag)
    {
        U.ErrorLastTime++;
    }

    ButtonFilter();     //对补偿值按钮调节进行去抖处理

    /*for test!!!
    if (IntFlag & 0x7fff)
    {
        asm(nop);
        asm(nop);
        asm(nop);
    }
    IntFlag = 0;    //for test!!!*/

    asm (BFSET #0x0300, SR);    //禁用所有可屏蔽中断
    *IPR  = 0xfe00;  //允许0-6级中断
}
/*****end of 1ms定时器中断,Timer D3*****/


/*****计算当前一秒内工频整周期时刻对应的计数值*****/
#pragma interrupt
void CalPeriodCounterQueue(void)
{
    unsigned long TempUL1, TempUL2;
    unsigned int TempUI1, TempUI2;

    TempUL1 = AveragePpsPeriod;

    asm (BFSET #0x0300, SR);        //禁用所有可屏蔽中断
    TempUL2 = TempUL1 / 50;
    asm (BFCLR #0x0200, SR);        //开启可屏蔽中断

    TempUI1 = TempUL1 - TempUL2 * 50;    
    TempUI2 = 0;
    if (FirstOutputPpsFlag)
    {
        TempUL1 = CurrInputPpsCounter;
    }
    else
    {
        TempUL1 = OutputPpsCounter;
    }
    PeriodCounterQueuePtr = &PeriodCounterQueue[0];
    for (;;)
    {
        *PeriodCounterQueuePtr = TempUL1;
        if (++PeriodCounterQueuePtr >= &PeriodCounterQueue[50])
        {
            break;
        }
        TempUL1 += TempUL2;
        TempUI2 += TempUI1;
        if (TempUI2 >=50)
        {
            TempUL1 += 1;
            TempUI2 -= 50;
        }
    }
    PeriodCounterQueuePtr = &PeriodCounterQueue[0];
}
/*****end of 计算当前一秒内工频整周期时刻对应的计数值*****/


/*****判断装置状态,驱动指示灯*****/
#pragma interrupt
void LedOutput(void)
{
    if ((DetailErrInfo.Word & 0x00ff) || (GpsStat.Word & 0x00ff))	//2007.1
    {
        ALERT1_LED_TURN_ON;
    }
    else
    {
        ALERT1_LED_TURN_OFF;
    }
    if (!EinErrFlag)
    {
        PULSE_LED_TURN_ON;
    }
    if (!UinErrFlag)
    {
        UIN_LED_TURN_ON;
    }
    
    if (PpsLedOnFlag)	//2007.1 当前秒同步正常PPS指示灯才点亮
    //if (PpsSyncStat == 0)	//同步异常时间不超过10秒,PPS指示灯就闪烁
    {
        PPS_LED_TURN_ON;
        PpsLedOnFlag = FALSE;
    }
    
    if (!Sci1RecErrFlag && !SocErr && RealFixFlag)	//2007.1
    {
        CLOCK_LED_TURN_ON;
    }
}
/*****end of 判断装置状态,驱动指示灯*****/


/*****初始化内部WATCHDOG*****/
void InitIntWatchdog(void)
{
    *COPTO  = 0x0061;   //20ms
    //xxxx  保留 bit15-12
    // 计算公式为:周期=16384 *( CT[11:0]+1 ) / clock cycle
    *COPCTL = 0x0002; // 0000 0000 0000 1111
    //xxxxxxxxxxxx  保留 bit15-4
    //bit3 1 在停止模式COP依然工作
    //bit2 1 在等待模式COP依然工作
    //bit1 1 使COP工作
    //bit0 1 COPCTL, COPTO为只读
}
/*****end of 初始化内部WATCHDOG*****/


/*****清除内部WATCHDOG*****/
void ClearIntWatchdog(void)
{
    *COPSRV = 0xaaaa;   //清DSP内部WATCHDOG
    *COPSRV = 0x5555;
}
/*****end of 清除WATCHDOG*****/


/*****清除外部WATCHDOG*****/
void ClearExtWatchdog(void)
{
    asm(BFCHG   #0x0008,X:$13c1);   //清外部WATCHDOG
}
/*****end of 清除WATCHDOG*****/


/*****记录输入PPS上升沿计数器值,用于测试*****/
#pragma interrupt
void RecInputPpsCounter(unsigned long RecCounter)
{
    *InputPpsCounterRecBufPtr++ = RecCounter;
    if (InputPpsCounterRecBufPtr >= &InputPpsCounterRecBuf[32])
    {
        InputPpsCounterRecBufPtr = &InputPpsCounterRecBuf[0];
    }
}
/*****end of 记录输入PPS上升沿计数器值,用于测试*****/


/*****记录输出PPS上升沿计数器值,用于测试*****/
#pragma interrupt
void RecOutputPpsCounter(unsigned long RecCounter)
{
    *OutputPpsCounterRecBufPtr++ = RecCounter;
    if (OutputPpsCounterRecBufPtr >= &OutputPpsCounterRecBuf[32])
    {
        OutputPpsCounterRecBufPtr = &OutputPpsCounterRecBuf[0];
    }
}
/*****end of 记录输出PPS上升沿计数器值,用于测试*****/


/*****记录TD3溢出时刻,用于测试*****/
#pragma interrupt
void RecTd3OverflowCounter(unsigned long RecCounter)
{
    *Td3OverflowCounterRecBufPtr++ = RecCounter;
    if (Td3OverflowCounterRecBufPtr >= &Td3OverflowCounterRecBuf[32])
    {
        Td3OverflowCounterRecBufPtr = &Td3OverflowCounterRecBuf[0];
    }
}
/*****end of 记录输出PPS上升沿计数器值,用于测试*****/

⌨️ 快捷键说明

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