STM32 输入捕获

一、什么是输入捕获
定时器的计数器CNT在不停地计数,当选定的输入引脚上出现了设定的 上升沿或下降沿时,把CNT的值记录到CCR中。

二、框图
在这里插入图片描述
三、流程图

引脚输入信号到输入通道TI1
对输入信号进行滤波和边缘检测
1个输入通道可以进入两个捕获通道IC1 IC2
分频器 对输信号分频
当发现设定的边缘时,把计数器CNT的值锁存到CCR中,并产生中断标志,在SR中
滤波需要对进入定时器的频率分频CR1 的CKD1:0
CCMR1的ICxF3:0设定采样频率,CCER的CCxP上升/下降沿
CCMRx的CCxS1:0设定输入到捕获通道的映射关系
CCMRx的ICxPSC设定分频
发生第二次捕获时前一次未读取会产生CCxOF标志

四、程序分析

static void MX_TIM4_Init(void)
{

  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_IC_InitTypeDef sConfigIC;
//-----------------------这一段初始化定时器---------------------------
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 71;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 0xFFFF;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_IC_Init(&htim4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
//--------------------这一段以后再解------------------------------------
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
//-------------------下面中的x为通道号----------------------------------------
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;//下降沿捕获,CCER-->CCxP位
  sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;//定义捕获通道IC3映射在输入通道TI4上
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;//分频为0
  sConfigIC.ICFilter = 0;//滤波为0
  if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;//上升沿
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;//定义IC4映射在TI4上
  if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

初始化完以后,主函数要调用HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_3);来开启通道,置1 DDER–>CC3IE位。

那么定时器4将会发生三类中断,
1、CNT计数到FFFF时,溢出中断
2、上升沿捕获通道4中断
3、下降沿捕获通道3中断
在中断函数中,要处理这三类中断。

五、问题点
1、在中断中,清0 计数器CNT,重新计数,得到上升沿的时间,和下降沿时间,然后计算频率为72M/tmp1,占空比为tmp2/tmp1(假设时钟为72M)

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef * htim)
{
//	static uint8_t TIM4CH34_CAPTURE_STA=0;//标记输入捕获状态
	if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_4)//如果是TIM_IT_CC4中断,上升沿
	{
		__HAL_TIM_SET_COUNTER(htim,0);//清0计数器CNT,从0开始计数
		tmp1=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_4);
	}
	else if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_3)//如果是TIM_IT_CC3中断,下降沿
	{
		tmp2=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
	}
}

这程序计算得不够准,当上升沿捕获中断的时候,进入中断,然后清0计数器,这之间已经跑了几个时钟了。所以tmp1和tmp2都会比实际小一点。还有进入定时器的频率72M/65535=1098 不能测试低于1098的频率,会溢出。

2、改成以下状态机,会更准确

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef * htim)
{
	static uint8_t state=0;//标记输入捕获状态
	static uint16_t CaptureValue1_CH4;
	if(state==0)
	{	
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_4)//如果是TIM_IT_CC4中断,上升沿
		{
			CaptureValue1_CH4 =HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_4);
			state=1;
		}
	}
	else if(state==1)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_3)//如果是TIM_IT_CC3中断,下降沿
		{
			tmp2=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
			if(tmp2>CaptureValue1_CH4)  tmp2=tmp2-CaptureValue1_CH4;
			else  tmp2= (0xFFFF-CaptureValue1_CH4)+tmp2;
			state=2;
		}
	}
	else if(state==2)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_4)//如果是TIM_IT_CC4中断,上升沿
		tmp1=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_4);
		if(tmp1>CaptureValue1_CH4)  tmp1=tmp1-CaptureValue1_CH4;
		else  tmp1= (0xFFFF-CaptureValue1_CH4)+tmp1;
		state=0;
	}
	else  state=0;
}

这个文章写得细https://blog.csdn.net/qq_38410730/article/details/80011330

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值