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