目录
输入捕获?捕获🐝?熊大!俺来了?
no no no!开发板怎么可能去捉蜜蜂呢?开发板只能去捕捉信号。
下面小蛋糕就带大家看一看开发板是怎么捉🐝的!啊不对!是看开发板怎么捉信号的!
输入捕获简介
STM32的输入捕获可以用来测量脉冲宽度,测量时间。例如超声测距模块就需要用到了输入捕获功能,通过测量输入脉冲高电平的脉宽,从而计算测量物体的距离。
输入捕获原理
STM32 的输入捕获,简单的说就是通过检测 TIMx_CHx 上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT) 存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。在完成捕获后再进行有关计算,求出所求的信息。
输入捕获实验内容
在输入捕获实验中,我们用TIM2的通道1(PA0)来做输入捕获,捕获PA0上的高电平的脉宽(用WK_UP按键输入高电平(当该按键按下时为高电平,松开时为低电平)),通过测量高电平持续的脉冲宽度,求出我们按键的时间。
输入捕获实验步骤
1.编写输入捕获的初始化函数
- 使能TIM时钟和PA0时钟;
- 初始化GPIO;
- 初始化TIM2(设置计数频率和自动装载值);
- 初始化输入捕获的相关内容;
- 设置中断优先级分组,初始化中断函数;
- 使能捕获;
- 使能定时器;
2.编写中断服务函数;
3.编写主函数;
输入捕获实验代码及说明
首先我们编写输入捕获的初始化函数
1.1首先,我们使能我们所需要的时钟
在这里,我们用到了定时器2和PA0,所以我们需要使能这两个对应的时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
1.2然后,我们再进行GPIO的初始化(由于初始化之前已经进行了详细的说明这里就不多做说明,有问题可以看前面的文章——《【手拉手 带你准备电赛】解答小课堂——编写初始化函数(初学者极度友好)》)
//定义初始化函数参数结构体
GPIO_InitTypeDef GPIOInitStruct;
//为结构体参数赋值
GPIOInitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIOInitStruct.GPIO_Pin=GPIO_Pin_0;
GPIOInitStruct.GPIO_Speed=GPIO_Speed_50MHz;
//调用GPIO初始化函数
GPIO_Init(GPIOA,&GPIOInitStruct);
1.3然后我们进入TIM2的初始化,这里主要是对自动装载值和计数频率以及其他变量的初始化(这一部分我们在之前的PWM输出实验中有过详细的讲解,大家可以参照一下)。
//定义初始化定时器参数结构体
TIM_TimeBaseInitTypeDef TIMInitStruct;
//为结构体参数赋值
TIMInitStruct.TIM_ClockDivision=TIM_CKD_DIV1; //TDTS = Tck_tim
TIMInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //使用向上计数模式
TIMInitStruct.TIM_Period=arr;
TIMInitStruct.TIM_Prescaler=psc;
//调用初始化函数
TIM_TimeBaseInit(TIM2,&TIMInitStruct);
1.4然后我们初始化输入捕获函数
因为在我们的实验中,我们使用的输入通道是通道一,选择输入端IC1映射到TI1上,所以TIMICInitStruct.TIM_Channel赋值为TIM_Channel_1;由于我们没有使用滤波器,所以TIMICInitStruct.TIM_ICFilter赋值为0x00;因为我们需要进行映射,映射带TI1上,所以TIMICInitStruct.TIM_ICSelection赋值为TIM_ICSelection_DirectTI;我们使用上升沿捕获,捕获高电平,所以TIMICInitStruct.TIM_ICPrescaler赋值为TIM_ICPolarity_Rising。代码如下
//定义初始化参数结构体
TIM_ICInitTypeDef TIMICInitStruct;
//根据我们的需求为结构体赋值
TIMICInitStruct.TIM_Channel=TIM_Channel_1;
TIMICInitStruct.TIM_ICFilter=0x00;
TIMICInitStruct.TIM_ICPolarity=TIM_ICPSC_DIV1;
TIMICInitStruct.TIM_ICPrescaler=TIM_ICPolarity_Rising;
TIMICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;
//调用函数
TIM_ICInit(TIM2,&TIMICInitStruct);
1.5由于我们需要在中断里完成数据处理和捕获设置等关键操作从而实现高电平脉宽统计,所以我们需要设置中断分组(由于前面已经多次讲解过中断分组的有关内容,这里我们便不再进行详细的讲解)。
//定义中断分组参数结构体
NVIC_InitTypeDef NVICInitStruct;
//为结构体变量赋值
NVICInitStruct.NVIC_IRQChannel=TIM2_IRQn;
NVICInitStruct.NVIC_IRQChannelCmd=ENABLE;
NVICInitStruct.NVIC_IRQChannelSubPriority=0;
NVICInitStruct.NVIC_IRQChannelPreemptionPriority=2;
//调用中断初始化函数
NVIC_Init(&NVICInitStruct);
1.6因为我们要捕获的是高电平信号的脉宽,所以,第一次捕获是上升沿,第二次捕获时下降 沿,必须在捕获上升沿之后,设置捕获边沿为下降沿,同时,如果脉宽比较长,那么定时器就会溢出,对溢出必须做处理,否则结果就不准了。这两件事,我们都在中断里面做,所以必须 开启捕获中断和更新中断。
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);
1.7 最后我们使能定时器即可。
TIM_Cmd(TIM2,ENABLE);
2.下面,我们进入中断服务函数的编写
在中断服务函数中我们需要实现:
判断中断类型、完成数据处理和捕获设置、在终端结束时清除中断标志位
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未捕获成功
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
if(TIM2CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高电平持续时间过长,发生溢出现象
{
TIM2CH1_CAPTURE_STA|=0X80;//标记成功捕获一次
TIM2CH1_CAPTURE_VAL=0XFFFF;
}else TIM2CH1_CAPTURE_STA++;
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获1发生捕获
{
if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
}else //还没开始捕获
{
TIM2CH1_CAPTURE_STA=0; //清空
TIM2CH1_CAPTURE_VAL=0;
TIM_SetCounter(TIM2,0);
TIM2CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //已经捕获成功了就清空中断标志位
}
3.最后我们编写我们的主函数
extern u8 TIM2CH1_CAPTURE_STA; //输入捕获状态
extern u16 TIM2CH1_CAPTURE_VAL; //输入捕获值
int main(void)
{
u32 temp=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组为2
uart_init(9600); //设置数据传输速率为9600
TIM_Cap_Init(0XFFFF,72-1);
while(1)
{
delay_ms(10);
TIM_SetCompare1(TIM1,TIM_GetCapture1(TIM1)+1);
if(TIM_GetCapture1(TIM1)==300)TIM_SetCompare1(TIM1,0);
if(TIM2CH1_CAPTURE_STA&0X80)//成功捕获高电平
{
temp=TIM2CH1_CAPTURE_STA&0X3F;
temp*=65536; //溢出时间总和
temp+=TIM2CH1_CAPTURE_VAL;
printf("HIGH:%d us\r\n",temp);
TIM2CH1_CAPTURE_STA=0; //开启下一次捕获实验
}
}
}
到这里我们的捕获实验就完成了,怎么样是不是成就感满满,下面就是我们串口调试助手显示的结果。串口调试助手显示了每次捕捉到的高电平的持续时间。
关于输入捕获实验我们就介绍到这里了,你学废了吗?下篇文章见!