xf331785508 发表于 2018-9-21 15:27:46

STC15系T0中断计数模式,只有初次正确输出IO电平?[结帖]

本帖最后由 xf331785508 于 2018-9-21 17:30 编辑

如题,用的是STC15W4KS32型号。 系统要求是P3.4接收输入脉冲,并根据串口接收到的参数比例,输出相应的脉冲。
我的配置是 用T4 通过P0.6输出8000Hz方波,飞线接入P3.4,模拟输入的方波, T0配置计数模式,在中断中变更P4.3 P2.1 P3.5的输出电平。
串口1用T2时钟做波特率发生器。以下,附上Timer配置和T0中断服务函数。
请大家帮忙看看问题出在哪儿了?(注:主要的问题是T0的中断函数只有初次上电后的运行是按设计要求正确输出的,之后 就不行了。)

global void gvIF_TimerInit( void )
{
        xdatauint32_tadwFreq;
        xdatauint16_tawTimerReg;

        /*!< Timer0 is configed in counter mode for motor 1 , 2 and 3. */
        AUXR |= (1 << 7);        //!<Timer0 work in 1T mode.
        TMOD &= ~0x0F;                 //!<Clear GATE0 C/T, M1, M0 bit.
        TMOD |= (1 << 2);        //!<Set C/T to switch timer0 to counter mode.

        TL0 = (uint8_t)((TIMER_REG_MAX - 1) & 0xFF);
        TH0 = (uint8_t)((TIMER_REG_MAX - 1) >> 8);
        // INT_CLKO |= 1;                //!<P3.5 as Timer0 output pin.
        TF0 = 0;
        ET0 = 1;                        //!<Enable Timer0 interrupt.
        PT0 = 1;

        /*!< Timer1 is configed in timer mode for scan state of input IO in the period of 10us. */
        adwFreq = 10000;   //!< 10KHz ==> 100us period
        awTimerReg = (uint16_t)(TIMER_REG_MAX - ((MAIN_Fosc >> 1) / adwFreq));
        AUXR |=0x40;                 //!< Timer1 work in 1T mode.
        TMOD &= ~0xF0;
        TL1   = (uint8_t)(awTimerReg & 0xFF);
        TH1   = (uint8_t)(awTimerReg >> 8);

        EA          = 1;                        //!<CPU interruption set enable.
        // ET1   = 1;                        //!<Timer1 interruption set enable.
        // TR1   = 1;                        //!< Timer1 start run.
        TF1   = 0;

        /*!< Timer4 is configed in timer mode for test and as source wave. */
#if        DEBUG_TIMER_CLK_OUTPUT == 1
        adwFreq = 8000;
        awTimerReg = (uint16_t)(TIMER_REG_MAX - ((MAIN_Fosc >> 1) / adwFreq));
        T4T3M |= (3 << 4);
        TL4 = (uint8_t)(awTimerReg & 0xFF);
        TH4 = (uint8_t)(awTimerReg >> 8);
#else
        T4T3M |= (1 << 5);
#endif
//        IE2   |= (1 << 6);        //!<Timer4 interruption set enable.
        T4T3M |= (1 << 7);        //!<Timer4 start run.
       
       
        lbPulsPara = 2;
        lbPulsPara = 3;
        lbPulsPara = 2;
        lbPulsPara = 3;
        lbPulsCyc1    = 1;
        lbPulsCyc2    = 1;
        lbPulsCnt   = 0;
        lbPulsCycCnt= 0;
        lbPulsPeriodFlag = 0;
}


T0的中断服务函数

global void TMR0_IRQHandler(void) interrupt TIMER0_VECTOR
{       
        TR0 = 0;
        if( lbPulsCnt < lbPara )
        {
                P43 = P21 = P35 = 0;
                SBUF = lbPulsCnt;
                lbPulsCnt++;
        }
        else if( lbPulsCnt < lbPara )
        {
                P43 = P21 = P35 = 1;
                SBUF = lbPara;
                lbPulsCnt++;
        }
        else
        {
                SBUF = lbPulsCnt;
                lbPulsCnt = 0;
                lbPulsCycCnt++;
                if( lbPulsCycCnt >= lbPara )
                {                       
                        lbPulsCycCnt = 0;
                        if( !lbPulsPeriodFlag )
                        {
                                lbPulsPeriodFlag = 1;
                                lbPara = lbPulsPara;
                                lbPara = lbPulsPara;
                                lbPara = lbPulsCyc2;
                        }
                        else
                        {
                                lbPulsPeriodFlag = 0;
                                lbPara = lbPulsPara;
                                lbPara = lbPulsPara;
                                lbPara = lbPulsCyc1;
                        }
                }
        }
        TR0 = 1;
        if( CONVEYOR_GPIO != 0 )
        {
                lwPulsTotalNum--;
                if( lwPulsTotalNum == 0 )
                {
                        TR0 = 0;
                        PRESSED_FMOTOR_EN_GPIO = 0;
                        PRESSED_BMOTOR_EN_GPIO = 0;
                }
        }
        P11 = ~P11;
        TF0 = 0;


}


以下为任务调用T0工作的代码,业务逻辑是通过串口接收到脉冲输出的比例参数,并设置到T0的接口层中,在中断中根据参数比例变更IO输出脉冲。

local void lvTask_SMStepAction( void )
{
        local xdata pFun                lpfMotorAction[ ] =
        {
                lvTask_SMParaSet,
                lvTask_SMTransBeltFollow,
                lvTask_SMNone
        };
       
        if( lgStatus == eTaskStatusReady )
        {
                lbMainStep= 0U;
                lbSubStepA= 0U;               
        }
        (*lpfMotorAction)();
}

local void lvTask_SMNone( void )
{
        lgStatus = eTaskStatusIdle;
}

local void lvTask_SMParaSet( void )
{
        if( gbParaUpdateFlag == 1 )
        {
                if( gbPulsPara < 0xAA )
                {
                        gvIF_TimerParasSet( gbPulsPara, gwPulsNum );
                }
                gbParaUpdateFlag = 0;
        }
        lbMainStep = 0;
        eActionStep = eAS_TransFollow;
        lgStatus = eTaskStatusOK;
}


local void lvTask_SMTransBeltFollow( void )
{
        uint8_t xdata abStatus = 0;
        uint8_t xdata abInput= 0;
       
        switch( lbMainStep )
        {
                case 0:
                        if( CONVEYOR_GPIO == 0x00 )        //!< Waitting the run signal of CONVEYOR.
                        {                               
               
                                PULL_MOTOR_EN_GPIO       = 1;
                                PULL_MOTOR_DIR_GPIO      = 1;

                                PRESSED_FMOTOR_EN_GPIO   = 1;
                                PRESSED_FMOTOR_DIR_GPIO= 1;

                                PRESSED_BMOTOR_EN_GPIO   = 1;
                                PRESSED_BMOTOR_DIR_GPIO= 0;
                               
                                ELECTR_IRON_PRESS();
                               
                                TR0 = 1;        //!< Motor start run;
                                lbMainStep = 1;
                                abStatus = 1;
                        }
                        else
                        {
                                lbMainStep = 3;
                        }
                        break;
                case 1:
                        if( CONVEYOR_GPIO == 0x01 )        //!< Waitting the stop signal of CONVEYOR.
                        {
                                TR0 = 0;
                                ELECTR_IRON_RELEASE();
                               
                                PULL_MOTOR_EN_GPIO       = 0;
                               
                                PRESSED_FMOTOR_EN_GPIO   = 1;
                                PRESSED_FMOTOR_DIR_GPIO= 0;

                                PRESSED_BMOTOR_EN_GPIO   = 1;
                                PRESSED_BMOTOR_DIR_GPIO= 1;

                                gvIF_Timer0TimerUpdate(4000, 10000);
                                TR0 = 1;        //!< Motor start run;
                               
                                lbMainStep = 2;
                                abStatus = 1;
                        }                       
                        break;
                case 2:
                        abInput = (P3 >> 2) & 0x03;
                        if( abInput != 3 )
                        {
                                PRESSED_FMOTOR_EN_GPIO   = 1;
                                PRESSED_FMOTOR_DIR_GPIO= 0;

                                PRESSED_BMOTOR_EN_GPIO   = 1;
                                PRESSED_BMOTOR_DIR_GPIO= 1;
                                gvIF_Timer0TimerUpdate(4000, 2000);
                                TR0 = 1;        //!< Motor start run;
                                lbMainStep = 3;                               
                                abStatus = 1;
                        }
                        break;
                case 3:
                        eActionStep = eAS_ParaSet;
                        lbMainStep = 0;
                        break;
                default:
                        break;
        }
       
        lgStatus = ((abStatus == 1) ? eTaskStatusProcess : eTaskStatusAysn);
}


此图为示波器图示,其中,黄色为T0的输入方波,即P3.4输入脉冲,蓝色为P3.5的输出脉冲, 业务逻辑要求,2:1的输入输出比例输出4组后,变更为3:1的比例输出8组后再往复循环进行。

xf331785508 发表于 2018-9-21 17:28:37

结贴:
原因自行找到了。 在T0由计数模式下的工作完成后,会转为定时器模式下工作一段时间,结果在定时器模式配置函数中无意间打开了P3.5作为T0输出频率,即INT_CLKO寄存器位0被置位了,这样造成的结果就是自定义的脉冲被固定脉冲掩盖,所以怎么调都不会有输出,而只在初次上电后能正确运行输出。
总结还是不够仔细认真。
下面附一张脉冲图结帖。图中稀疏一点的脉冲为2:1输出的,循环数为16组, 密集一点的为3:1输出的,循环数为22组。
页: [1]
查看完整版本: STC15系T0中断计数模式,只有初次正确输出IO电平?[结帖]