很多事情下,需要捕获外部传感器的脉宽,频率,周期,从而计数来做一些应用。
这次就来分享下输入捕获
很早之前就听说过这个功能,一直没机会实操,现在,终于开始了。
首先,输入捕获也是用定时器来操作。定时器的功能挺强大的,可以输出一定的波形,又可以作为时基,还可以输入捕获,y1s1,真的太强了。
废话不多说,看看我是怎么操作的吧。
1.我使用PA2引脚产生一个50%的占空比
2.用示波器量,的确是有50%说明,成功
3.用PA1引脚来测上升沿捕获,看是否成功,如果成功,就让一个标志位置一,从而来判断是否捕获到上升沿,那么下面来看代码吧,根据代码来解释。
/*******************************************************************************
* 函 数 名 : TIM2_CH3_PWM_Init
* 函数功能 : TIM2通道3 PWM初始化函数
* 输 入 : per:重装载值
psc:分频系数
* 输 出 : 无
*******************************************************************************/
void TIM2_CH3_PWM_Init(u16 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//改变指定管脚的映射
TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC3Init(TIM2,&TIM_OCInitStructure); //输出比较通道2初始化
TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable); //使能TIMx在 CCR2 上的预装载寄存器
TIM_ARRPreloadConfig(TIM2,ENABLE);//使能预装载寄存器
TIM_Cmd(TIM2,ENABLE); //使能定时器
}
用正点原子的DS100测的还是挺准的
//PA1
void TIM5_CH2_Input_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能TIM5时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//管脚设置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //设置下拉输入模式
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
TIM_TimeBaseInitStructure.TIM_Period=65535; //自动装载值65535,最大能计65ms
TIM_TimeBaseInitStructure.TIM_Prescaler=1; //分频系数72
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);
TIM_ICInitStructure.TIM_Channel=TIM_Channel_2; //通道2
TIM_ICInitStructure.TIM_ICFilter=0x00; //滤波
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕获
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1
TIM_ICInit(TIM5,&TIM_ICInitStructure);
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC2,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;//中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM5,ENABLE); //使能定时器
}
通过datasheet可以知道是TIM5_CH2
再写个中断服务函数就完事了
上面代码的配置,65ms就会产生一次计数溢出的中断标志位,还有一个捕获到上升沿的标志位
程序全速跑的时候(这时候我没有用杜邦线接入PA2(产生50%占空比的引脚)),始终不会进入TIM_IT_CC2这个中断的,这个始终是RESET,当我接入PA2的时候,就会进来中断,说明捕获到了上升沿,实际情况也是如此嘛。没什么问题。
还是挺简单的,后续继续分享,怎么测周期,频率,占空比。步步为营,今天就到此结束啦!