本文主要是介绍STM(X) 输入捕获,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
硬件连接
外部连接一个按键,上下拉输入决定什么沿触发和电平捕捉
软件实现
extern u8 TIM2CH1_CAPTURE_STA; //输入捕获状态
extern u16 TIM2CH1_CAPTURE_VAL; //输入捕获值int main(void){ u32 temp=0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2delay_init(); //延时函数初始化 uart_init(9600); //9600 TIM2_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数 while(1){if(TIM2CH1_CAPTURE_STA&0X80)//成功捕获到了一次高电平{temp=TIM2CH1_CAPTURE_STA&0X3F;printf("溢出次数:%d 次\r\n",temp);temp*=65536; //溢出时间总和temp+=TIM2CH1_CAPTURE_VAL; //溢出时间加上最后一次的时间printf("HIGH:%d us\r\n",temp); //打印TIM2CH1_CAPTURE_STA=0; //置0,开始下一次捕获}}
}
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数//定时器2通道1输入捕获配置TIM_ICInitTypeDef TIM2_ICInitStructure;void TIM2_Cap_Init(u16 arr,u16 psc)
{ GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //引脚设置A0(作为输入) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入GPIO_Init(GPIOA, &GPIO_InitStructure); //结构体赋值GPIO_ResetBits(GPIOA,GPIO_Pin_0); //A0置零//初始化定时器2 TIM2 TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割用于滤波,这里不进行滤波TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //结构体赋值//初始化TIM2输入捕获参数TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //使用定时器2的通道1TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //设置直接映射(映射到本通道,默认)TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //设置多少个事件触发一次,这里设置每次事件都触发TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波TIM_ICInit(TIM2, &TIM2_ICInitStructure);//结果体赋值//中断分组初始化NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断 TIM_Cmd(TIM2,ENABLE ); //使能定时器2}u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
u16 TIM2CH1_CAPTURE_VAL; //捕获到下降沿的时候,定时器的值//STA各位描述
//bit7:捕获完成标识(0x80),也就是捕获到了一个高电平的时间
//bit6:捕获到高电平(0x40)
//bit5-0:定时器溢出次数(0x1F)//定时器5中断服务程序
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++;//没有溢出,定时器溢出次数加1}}}if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET){//发生了捕获事件(捕捉到一个沿),下面说的是遇到沿的时候如何处理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); //清除中断标志位
}
这篇关于STM(X) 输入捕获的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!