TIM输入捕获测脉冲的频率

 

 只有上升沿触发。计数值为0到0xfffffff,即429467295.

tim2挂载的apb1的频率为100 000 000

tim.c中添加

uint32_t DIff=0;//差值
uint8_t CaptureIndex=0;//捕获标志位
uint8_t MeasureFlag=0;//测量计算标志位
uint32_t CapVal1=0;//捕获值1
uint32_t CapVal2=0;//捕获值2
/* USER CODE END PV */

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
    if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)//两次判断
    {
        if(CaptureIndex==0)//捕获标志位判断
        {
            CapVal1= HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//读捕获值1
            CaptureIndex=1;//捕获标志位=1
        }
        else if(CaptureIndex==1)//连续读值
        {
            CapVal2= HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
            CaptureIndex=0;//捕获标志位置位
            MeasureFlag=1;//测量标志位置1
            HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1);//关闭中断
        }
        else
        {
            Error_Handler();//错误处理
        }
    }
}
}

main.c中添加

//tim输入捕获
extern uint32_t DIff;//差值
extern uint8_t CaptureIndex;//捕获标志位
extern uint8_t MeasureFlag;//测量计算标志位
extern uint32_t CapVal1;//捕获值1
extern uint32_t CapVal2;//捕获值2
 HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//输入捕获中断开启

while(1)中添加:

 if(MeasureFlag==1)//测量位判断
	  {
	     if(CapVal2>=CapVal1)//注意这里分两种情况
	     {
	         DIff=CapVal2-CapVal1;
	     }
	     else
	     {
	         DIff=((4294967295+1-CapVal1)+CapVal2);//这种情况在捕获值1在一个计数周期的结束,而捕获值2是下个计数周期的开始
	     }
	     Uart_printf(&huart1,"DIFF=%.8f\r\n",DIff/1.0);

	      Uart_printf(&huart1,"Period=%.8fs\r\n",DIff/10000000.0);//这里的100 000 000是tim2经分频后的频率。
	     Uart_printf(&huart1,"Fred=%dHz\r\n",100000000/DIff);
	     Uart_printf(&huart1,"\r\n");
	     MeasureFlag=0;//置位测量标志位
	      HAL_Delay(1000);
	      HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//再次开启下次捕获
	  }

但是由于内部时钟源的精度有限,采的频率会比实际小5%。建议软件处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在STM32标准库中,输入捕获可以用来量外部信号的周期、脉宽等参数,下面是一个简单的例子,以量一个脉冲的时间为例: ```c #include "stm32f10x.h" void TIM2_IRQHandler(void) { static uint32_t start_time = 0; static uint32_t end_time = 0; if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) // 判断是否是输入捕获中断 { if (start_time == 0) // 第一次捕获到上升沿 { start_time = TIM_GetCapture1(TIM2); // 获取计数器的值 TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_ICPolarity_FallingEdge); // 配置为下降沿触发捕获 } else // 第二次捕获到下降沿 { end_time = TIM_GetCapture1(TIM2); // 获取计数器的值 TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_ICPolarity_RisingEdge); // 配置为上升沿触发捕获 uint32_t pulse_width = end_time - start_time; // 计算脉冲宽度 uint32_t frequency = SystemCoreClock / pulse_width; // 计算频率 start_time = 0; // 重置计时器 end_time = 0; // 处理量结果 // ... } TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); // 清除中断标志位 } } int main(void) { // 初始化GPIO、定时器等 // 配置输入捕获 TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInit(TIM2, &TIM_ICInitStructure); // 使能输入捕获中断 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 启动定时器 TIM_Cmd(TIM2, ENABLE); while (1) { // 主程序 // ... } } ``` 这个例子中,我们使用了TIM2的通道1来进行输入捕获,捕获到上升沿和下降沿时,会触发中断,并在中断服务函数中取计数器的值,计算脉冲的宽度和频率。注意,在第一次捕获到上升沿时,需要将捕获模式设置为下降沿触发,以便捕获到完整的脉冲。在第二次捕获到下降沿时,需要将捕获模式设置为上升沿触发,以便下一次捕获。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值