STM32使用M/T法检测单路脉冲

实验目的:刚开始接触关机电机检测领域,准备探索关于定时器在检测单路脉冲中的应用,从而进行转速的检测。
使用芯片:STM32F407
使用平台:STM32Cube IDE

  1. M/T法介绍
    对于M/T法网上的资料很多,因此我只做一些简单的介绍。
  • M法:在规定时间内检测脉冲个数来获得被测速度,适合测量高速速度。
    方法:在Tg时间内,设电机每转一圈发出的脉冲数为P,在Tg(单位为S)时间内测得的总脉冲数是m1,那么转速nM = 60 * m1/ (P * Tg),单位是r/min。
  • T法:测量相邻两个脉冲间的时间,再来反算速度,适合测量低速速度
    方法:已知频率为fc的高频脉冲,开始测速时fc会向一计数器发送脉冲数,当电机产生的相邻的两个脉冲中第一个脉冲出现时,计数器开始接收fc发过来的脉冲,当电机产生的相邻的两个脉冲中第二个脉冲出现时,即电机的一个周期到达时,计数器停止计数,相邻两脉冲之间的计数器读数为m2,已知电机一圈脉冲P个,那么转速nM = 60 * fc/ (P*m2),单位是r/min。
  • M/T法:同时测量检测时间和在此时间内脉冲发生器发出的脉冲个数来测量速度
    方法:已知频率为fc的高频脉冲,在Tg时间内测得的高频脉冲m2个,输入的电机脉冲m1个,已知电机一圈脉冲P个,那么转速nM=60 * m1 * fc/ (P*m2),单位是r/min。
    此外,我们也可以在捕获到电机上升沿脉冲时开启定时时间计数,在定时时间Tg到达后,继续等待一个上升沿脉冲,时间为Td,记录在此时间内的脉冲数,由脉冲数除以时间,就可以得到准确的频率从而计算速度。目前我使用的M/T法采用前一种方法。
    2、定时器设置
  • 200ms定时器设置

首先需要设置好一个用来定时时间的定时器,我使用TIM1,定时200ms。定时器时钟信号是80MHz
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
采用200ms定时。

  • 外部脉冲捕获设置
    使用TIM3_CH1进行外部脉冲输入捕获,定时器设置如下
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    对电机脉冲进行上升沿捕获,通过捕获来判断外部脉冲开始。
  • 对外部脉冲进行计数
    使用TIM4进行脉冲计数,将定时器TIM4的时钟源选用外部脉冲就可以实现脉冲计数功能,设置如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    当捕获到外部脉冲时就准备开始外部脉冲计数。
  • 高频脉冲产生器
    使用TIM5定时器来产生5MHz方波频率
    在这里插入图片描述
    在这里插入图片描述
  • 对高频脉冲进行计数
    使用TIM8进行高频脉冲计数
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    相当于对TIM5产生高频5MHz脉冲进行计数,通过定时器的主从模式就可以实现该功能。
    在这里插入图片描述
    通过该功能表进行选择。
    3、程序代码实现
    主函数中
	  switch (capture_Cnt){
	  	case 0:
			htim3.Instance->CNT = 0;
	  		htim4.Instance->CNT = 0;
	  		htim8.Instance->CNT = 0;
		    TIM3_CNT = MSpeed_capture_Buf[2] = 0;
	  		ExPulse_Input = 0;
	  		TimeSet = 1;
		    T200MS_CNT = ThighFre_CNT = TExPulse_CNT = T200SUS = 0;
		    tt = 0;
	  		__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);//开启上升沿捕获
	  		HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);	//开启TIM3_CH1捕获
			  		__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);//更新中断用于溢出计数
	  		capture_Cnt++;
	  		HAL_TIM_Base_Start_IT(&htim1);  /* 200MS */
	  		break;
	  	case 4://4

			T_SPEED = 60.0 * CAL_capture_Buf[1] * High_Freq / (PULSE_CIRCLE * CAL_HIGHFRE_Buf[1]);//60.0 * HIGHFRE_Buf[1] / (PULSE_CIRCLE * capture_Buf[1]);
//			T_SPEED1 = 60.0 * capture_Buf[1] * High_Freq / (PULSE_CIRCLE * HIGHFRE_Buf[1]);
			capture_Cnt = 0;  
				if(MSpeed_capture_Buf[2] != 0)
				{
					M_SPEED = 1.0 / (((MSpeed_capture_Buf[1] + MSpeed_capture_Buf[2]  * 65535) - MSpeed_capture_Buf[0]) / 80000000.0 * 2);
					if(M_SPEED < 0.5)
					{
					MSpeed_capture_Buf[1] = 0;
					}
					MSpeed_capture_Buf[2] = 0;
				}
				else
				{
					M_SPEED = 1.0 / ((MSpeed_capture_Buf[1] - MSpeed_capture_Buf[0]) / 80000000.0 * 2);
				}
	  	}

在中断中

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(TIM1 == htim->Instance)
    {
//    	HAL_GPIO_TogglePin(D2_LED_GPIO_Port,D2_LED_Pin);
    	T200MS_CNT++;
		if(ExPulse_Input == 0)//200ms内还没捕获到第一个上升沿脉冲周期
		{
	    	T200MS_CNT = 0;
	    	tt++;
	    	if(tt == 10)//200*10 = 2000ms
	    	{

	    	}
		}
		else//200ms内已经捕获到第一个上升沿脉冲周期
		{
	    	if(T200MS_CNT == 1)//1  TimeSet
	    	{
				if(ExPulse_Input == 2)
				{
					HAL_GPIO_WritePin(LED1_GPIO,LED1_GPIO_PIN,GPIO_PIN_SET);
					__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);//开启上升沿捕获
					HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
					__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);
				}
				else
				{
					T200MS_CNT = 1;
					T200SUS++;
				}
	    	}
	    	else if(T200MS_CNT == (TimeSet + 1))//2
	    	{
				{
					T200MS_CNT = 0;
					tt = 0;
					HAL_GPIO_WritePin(LED1_GPIO,LED1_GPIO_PIN,GPIO_PIN_RESET);
				}
	    	}
		}
    }
    if(TIM8 == htim->Instance)
    {
    	ThighFre_CNT++;
    }
    if(TIM4 == htim->Instance)
    {
    	TExPulse_CNT++;
    }
    if(TIM3 == htim->Instance)
    {
    	TIM3_CNT++;
    }  
  
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

	if(TIM3 == htim->Instance)
	{

		switch(capture_Cnt){
			case 1://捕获到第一个上升沿
				ExPulse_Input = 1;
				HAL_GPIO_WritePin(LED2_GPIO,LED2_GPIO_PIN,GPIO_PIN_SET);
				htim3.Instance->CNT = 0;
				htim5.Instance->CNT = 0;
				HAL_TIM_Base_Start(&htim4);//
				HAL_TIM_Base_Start(&htim8);//
//				HAL_TIM_IC_Stop_IT(&htim3,TIM_CHANNEL_1); //停止捕获
				HAL_TIM_Base_Start_IT(&htim8);
				capture_Cnt++;
				MSpeed_capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);//开启下降沿捕获
				break;
			case 2://捕获到第二个上升沿,用来进行低速的测量,目前测试效果不好,可以不用管这一段
				ExPulse_Input = 2;
				MSpeed_capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
				HAL_TIM_IC_Stop_IT(&htim3,TIM_CHANNEL_1); //停止捕获
//				__HAL_TIM_DISABLE_IT(&htim3,TIM_IT_UPDATE);
				capture_Cnt++;
				MSpeed_capture_Buf[2] = TIM3_CNT;

				break;
			case 3://计数时间到时捕获到的最后一个上升沿  2
				ExPulse_Input = 3;
//				capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim16,TIM_CHANNEL_1);//闁兼儳鍢茶ぐ鍥亹閹惧啿顤呴柣銊ュ瀹曠喖鎳㈤敓????????????????????.
				HAL_TIM_IC_Stop_IT(&htim3,TIM_CHANNEL_1); //闁稿绮嶉娑㈠箲閺囷拷?锟界??????????   闁瑰瓨锟????: __HAL_TIM_DISABLE(&htim5);
				HAL_TIM_Base_Stop(&htim4);//閿燂??????????????閸氼垶鐝0鎴炴闁界喖顣堕敓锟??????
				HAL_TIM_Base_Stop(&htim8);//閿燂??????????????閸氼垵绶崗銉ㄥ墻閸愯尪顓搁弫鏉挎珤
				HAL_TIM_Base_Stop(&htim1);
			HAL_TIM_Base_Stop(&htim3);
			HAL_TIM_Base_Stop(&htim5);
				__HAL_TIM_DISABLE_IT(&htim3,TIM_IT_UPDATE);
				HAL_GPIO_WritePin(LED2_GPIO,LED2_GPIO_PIN,GPIO_PIN_RESET);
				capture_Cnt++;
				capture_Buf[1] = htim4.Instance->CNT;//HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);//闁兼儳鍢茶ぐ鍥亹閹惧啿顤呴柣銊ュ瀹曠喖鎳㈤敓????????????????????.
				HIGHFRE_Buf[1] = htim8.Instance->CNT;//HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1);
				if(ThighFre_CNT != 0)
				{
					HIGHFRE_Buf[3] = ((ThighFre_CNT) * 65535 + HIGHFRE_Buf[1]);//*2.5;
					ThighFre_CNT = 0;
					CAL_HIGHFRE_Buf[1] = HIGHFRE_Buf[3];
				}
				else
				{
					HIGHFRE_Buf[3] = HIGHFRE_Buf[1];// * 2.5;
					CAL_HIGHFRE_Buf[1] = HIGHFRE_Buf[1];
				}
				if(TExPulse_CNT != 0)
				{
					capture_Buf[3] = ((TExPulse_CNT) * 65535 + capture_Buf[1]);//*2.5;
					TExPulse_CNT = 0;
					CAL_capture_Buf[1] = capture_Buf[3];
				}
				else
				{
					capture_Buf[3] = capture_Buf[1] ;//* 2.5;
					CAL_capture_Buf[1] = capture_Buf[1];
				}
				break;
		}

	}


}

4、实验数据说明:
假设PULSE_CIRCLE =1就是一圈一个脉冲,T_SPEED 就是最终的测速结果,单位就是r/min。
在这里插入图片描述在这里插入图片描述
在小于0.3HZ/S的频率下,误差较大,其他情况下,误差基本都很小了。
实验结束。
有更好的测试方式欢迎大家提出!

  • 9
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值