stm32f103c8t6输入捕捉模式精细测信号频率

#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
int num,num1;//记录第一次捕获中断和第二次捕捉中断寄存器值
int sum,n=0;//sum:记录所测信号一个周期计数器记了多少个数。n:做第一次和第二次的捕捉中断判断。


 int main(void)
 {
	GPIO_InitTypeDef  GPIO_Structure;	//GPIO初始化		
	TIM_TimeBaseInitTypeDef  TIM_TimeStructure;//时钟初始化
	TIM_ICInitTypeDef TIM_ICTypeDef;//时钟输入捕捉通道初始化
	NVIC_InitTypeDef NVIC_InitStruct;//中断初始化

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能TIM2
	  
	uart_init(9600);//初始化串口,波特率9600
	delay_init();
	My_PWMTIM3_Init(1999,71);//自己写的一个输出pwm波的一个库,引脚PA6输出周期为2000us的脉冲
	TIM_SetCompare1(TIM3,1500);//设置比较值
  
  GPIO_Structure.GPIO_Pin = GPIO_Pin_1;				 
	GPIO_Structure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入,输入捕捉模式需要将具体引脚调为浮空输入 		 
  GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;		
	GPIO_Init(GPIOA, &GPIO_Structure);	

	TIM_TimeStructure.TIM_ClockDivision=TIM_CKD_DIV1;//分频因子
	TIM_TimeStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	TIM_TimeStructure.TIM_Period=0xFFFF;//自动重装载值
	TIM_TimeStructure.TIM_Prescaler=71;//预分频系数
	TIM_TimeBaseInit(TIM2, &TIM_TimeStructure);

	TIM_ICTypeDef.TIM_Channel=TIM_Channel_2;//PA1/T2.2
	TIM_ICTypeDef.TIM_ICPolarity=TIM_ICPolarity_Rising;//上升沿捕捉
	TIM_ICTypeDef.TIM_ICSelection=TIM_ICSelection_DirectTI;//映射一波
	TIM_ICTypeDef.TIM_ICPrescaler=TIM_ICPSC_DIV1;//不分频
	TIM_ICTypeDef.TIM_ICFilter=0x00;//不滤波
	TIM_ICInit(TIM2,&TIM_ICTypeDef);
	
	TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);//开启CC2中断
	NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;    //抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;          //响应优先级
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_Cmd(TIM2,ENABLE); 
 
 while(1)
 { printf("%d  ",sum);//让串口每隔0.5秒打印测得周期值
	 delay_ms(500);}
 }
	
	void TIM2_IRQHandler(void)
	{
	
		if(TIM_GetITStatus(TIM2,TIM_IT_CC2) != RESET&&n==0)//第一个上升沿
		{ num=TIM2->CCR2;//记录第一次捕捉比较寄存器值
		  n++;
     }
		
		if(TIM_GetITStatus(TIM2,TIM_IT_CC2) != RESET&&n==1)//第二个上升沿
		{ num1=TIM2->CCR2;//记录第二次捕捉比较寄存器值
			n=0;//n清零
		if(num-num1>50000)
		sum=65535-num+num1;
		else
		sum=num1-num;}//最后一点判断的关键我会在文章中讲解
	}
		
//
//
//name:Vincent njw    QQ:1504012979       glut	
		

一,硬件19

stm32f103c8t6,ch340模块

二,软件

         具体操作我在代码段有详细的注释,我觉得比较重要的一点是对于单片机时钟的配置思想,也很简单,第一步更改对应引脚模式,第二设定计时器计数模式,第三设定计时器工作模式,第四如果需要中断可以设定中断,并写好对应的中断服务函数。切记!勿忘了在设定定时器模式之后要开启时钟。

         接下来给大家讲为什么在中断函数最后加一个判断的原因,我设定的计数器模式为向上计数模式,最大值是65535。我们可以想象这样一种情况,当计数器记到65534时,此时进行了第一个上升沿的捕捉,往后在过1us,定时器的值会自动清零,假设我们所测的信号周期为20us,那么第二次的上升沿捕捉就是在计数器记到19的位置,此时第二次记录的值减去第一次记录的值显然不等于20us,此时就需要一个判断,把第一次的值减去第二次的值,假如大于50000,那么对于周期较小的信号来说,必然是发生了溢出,此时我们用65535减去第一次的捕捉值加上第二次捕捉值即为信号周期。