用P1.2,P1.3两个捕获口进行捕获,遇到下面两个问题,请大家帮忙看看。
一个是内部上拉,一个是软件消抖,后面用外不上拉和硬件消抖的方法解决了,但是我还是想把这个问题弄清楚。
1、使用内部上拉不起效
我认为正确的设置方法如下:
P1SEL |= BIT2+BIT3; //P1SEL.2=2,P1SEL.3=1
P1DIR &= ~(BIT2+BIT3); //P1DIR.2=0,P1DIR.3=0 P1.2,P1.3设置为捕获功能
P1OUT |= BIT2+BIT3; //设置为上拉
P1REN |= BIT2+BIT3; //上拉电阻使能
但是按照这个设置以后上拉不起作用。
如果把IO口设置为普通IO,上拉起效。
定时器A的设置也应该是正确的。
2、利用定时器进行软件消抖,不起效。
思路如下:
进入TimerA的捕获中断后首先关闭捕获中断,并开启TimerB主计数器中断,让TimerB开始计数(1ms中断一次),然后读取TACCR1或TACCR2的值,并保存到缓存(不进行其他处理,占用时间应该很短)。在TimerB主计数器中断中计数,当计数值大于一定值(譬如10)后,开启TimerA捕获中断,允许捕获中断。从而达到消抖的目的。
问题描述:
1、干簧管的抖动:干簧管在闭合的瞬间100us时间内有抖动。
2、430捕获的信号出现在一次捕获之后几个us内再产生一个捕获的情况。即两次捕获事件的发生仅相差几个us,然后才是下一个正常的捕获信号。
大致程序代码如下:
/*===================================================================*/
//名称:TimerA初始化
//功能:主机数器1S中定时,捕获通道1,捕获通道2为捕获
//参数:
//返回值:
//说明:
/*===================================================================*/
void Init_TimerA(void)
{
TACTL = TASSEL_1 + ID_0 + MC_1; //ACLK DIV_1 up_mode interrupt_enable
TACCR0 = 32768;
//使用捕获通道1
//TACCTL1 = 0;
TACCTL1 |= CM_2 + CCIS_0 + SCS + CAP;
// Capture_following_rising_edge CCI0A Synchronous_capture Compare_mode
//使用捕获通道2
TACCTL2 |= CM_2 + CCIS_0 + SCS + CAP;
//TACTL |= TAIE; //主计数器计数中断使能
}
/*===================================================================*/
//名称:TimerA中断1
//功能:1s中断时时间值加32768,捕获通道1、2中断时,记录时间值
//参数:
//返回值:
//说明:
/*===================================================================*/
#pragma vector=TIMERA1_VECTOR //定时器A的住计数器溢出中断的标准写法
__interrupt void Timer_A (void)
{
unsigned long fraction_1;
unsigned long fraction_2;
switch(TAIV)
{
case 10: //时钟溢出中断
{
ms_sec_since_power_up=ms_sec_since_power_up+32768;
TACTL &= ~TAIFG;
//asm("NOP");
}break;
case 2: //捕获模块1中断
{
TACCTL1 &= ~CCIE; //关中断
deb_req1 = 1; //请求消抖
fraction_1 = ms_sec_since_power_up + TACCR1; // 1 is 1/32768 second
Put_Speed_Pulse(fraction_1);
TACCTL1 &= ~CCIFG; //清中断标志位
}break;
case 4: //捕获/比较模块2中断
{
TACCTL2 &= ~CCIE;
deb_req2 = 1; //请求消抖
fraction_2 = ms_sec_since_power_up + TACCR2;
Put_Cadence_Pulse(fraction_2);
TACCTL2 &= ~CCIFG;
}break;
default:break;
}
}
/*===================================================================*/
//名称:TimerB初始化
//功能:产生1ms中断
//参数:
//返回值:
//说明:
/*===================================================================*/
void Init_TimerB(void)
{
//TBCLGRP CNTLx TBSSELx IDx MCx TBCLR TBIE
TBCTL = TBCLGRP_0 + 0 + TBSSEL_1 + ID_0 + MC_1 + 0 + 0;
TBCCR0 = 33;
//TBCCR0 = 327;
//TBCTL |= TBIE; //主计数器计数中断使能
}
/*===================================================================*/
//名称:TimerB中断1
//功能:消抖,一定时间后开启TimerA捕获中断
//参数:
//返回值:
//说明:
/*===================================================================*/
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B (void)
{
static unsigned char deb_time1 = 0;
static unsigned char deb_time2 = 0;
switch ( TBIV )
{
case 14:
{
if ( deb_req1 == 1 ) //捕获模块1请求消抖
{
deb_time1 ++;
if ( deb_time1 >= 10 )
{
deb_time1 = 0;
deb_req1 = 0;
TACCTL1 |= CCIE; //恢复捕获模块1中断
}
}
if ( deb_req2 == 1 ) //捕获模块2请求消抖
{
deb_time2 ++;
if ( deb_time2 >= 10 )
{
deb_time2 = 0;
deb_req2 = 0;
TACCTL2 |= CCIE; //恢复捕获模块2中断
}
}
}break;
default :break;
}
} |