STM32定时器输入捕获频率(cube)

STM32用cube配置HAL库进行的pwm输入捕获已经搞定。
stm32中的通用定时器和高级定时器直接可以设定PWM输入模式,pwm输入模式直接会打开两个输入捕获通道,通道1,3是用来捕获频率的,通道2,4是用来捕获空占比的,而且在进入主函数之前需要打开定时器输入捕获通道中断,通过HAL_TIM_ReadCapturedValue可以直接读取两个输入捕获通道中的信息,十分方便,但是在进行频率计算的时候,方法:芯片设定的时钟频率**/(读取到的输入捕获的频率数值+2)**这样可以得到近乎完全正确的数据。

频率捕获计算公式:
// 输入捕获能捕获到的最小的频率为 72M/{ (ARR+1)*(PSC+1) }
#define ADVANCE_TIM_PERIOD (1000-1)
#define ADVANCE_TIM_PSC (720-1)

pwm输出频率计算公式:
// 输出PWM的频率为 72M/{ (ARR+1)*(PSC+1) }
#define GENERAL_TIM_PERIOD (2000-1)
#define GENERAL_TIM_PSC (720-1)

    /* USER CODE BEGIN 2 */
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);//如果不需要占空比和频率数据就只开通道2即可。第一次的数据是不正确的,实际工作中要将第一次的数据丢弃

以下为主函数中的代码
*/ USER CODE END 2 */

/* USER CODE BEGIN WHILE */
while (1)
{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
if (tmp1 == 0)
{
    duty = 0;
    freq = 0;
}
else
{
    duty = tmp2 * 100.0f / tmp1 + 0.5f;
		/*tmp1前后需要各加1,及tmp+2*/
    freq = 72000000.0f / (tmp1+2);
}
		
printf ("freq: %d Hz\tduty: %d %%\r\n", freq, duty);
printf ("tmp1: %d\t%d\r\n", tmp1, tmp2);

// printf (“pos pulse= %lf\r\n”, tmp1 * 1.111111111111111e-8);// 这个1.xe-8就是90M时钟分之一
HAL_Delay(500);
}
/* USER CODE END 3 /*
以下为tim.c中的代码
*/ USER CODE BEGIN 1 */
uint32_t duty = 0;
uint32_t freq = 0;
uint32_t tmp1 = 0, tmp2 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// volatile static uint32_t tmp1 = 0, tmp2 = 0;

if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
    tmp1 = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//周期
}
else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
    tmp2 = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);//占空比
}

}**
配置图片如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
经过实验检验同时打开了三路定时器输入捕获频率和占空比,运行正常,且三个定时器的优先级都是0,0,正常运行,数据都比较准确
据目前知识掌握程度看,定时器回调函数只有一个,所以在对只有一个输入捕获的定时器进行了修改:uint32_t duty = 0,duty2 = 0,duty3 = 0;
uint32_t freq = 0,freq2 = 0;
uint32_t tmp1 = 0, tmp2 = 0,tmp3 = 0,tmp4 = 0,tmp5 = 0,tmp6 = 0;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// volatile static uint32_t tmp1 = 0, tmp2 = 0;

if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
		/*tem1,3分别是定时器2,3的输入捕获周期*/
    tmp1 = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//周期
			tmp3 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1);//周期
			tmp5 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);//周期
}
else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
		/*tem2,4分别是定时器2,3的输入捕获占空比*/
    tmp2 = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);//占空比
			tmp4 = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2);//占空比
			tmp6 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);//占空比
}

}
/读取定时器输入捕获数据/
void Read_Timer_Data(void)
{
if (tmp1 == 0)
{
duty = 0;
}
else
{
duty = tmp2 * 100.0f / tmp1 + 0.5f;
}

if (tmp3 == 0)
{
    duty2 = 0;
}
else
{
    duty2 = tmp4 * 100.0f / tmp3 + 0.5f;
}
	
if (tmp5 == 0)
{
    duty3 = 0;
}
else
{
    duty3 = tmp6 * 100.0f / tmp5 + 0.5f;
}	

}

经过实际检验同一个定时器同时进行PWM输出和PWM输入捕获的时候,不是非常的好用,因此如果以后需要使用编码器电机,推荐使用一个定时器用来输出PWM波,再用四个定时器进行PWM频率的输入捕获,这样的话,虽然说有点浪费定时器资源,但是自认为效率会高不少。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32基本定时器输入捕获功能可以用于测量外部信号的脉冲宽度、周期等参数。下面是使用STM32Cube HAL库进行配置的基本步骤: 1. 初始化定时器:根据所选的定时器,调用`HAL_TIM_Base_MspInit()`函数进行初始化。 2. 配置定时器参数:使用`TIM_HandleTypeDef`结构体配置定时器的基本设置,比如时钟源、预分频系数等。 3. 配置输入捕获参数:使用`TIM_IC_InitTypeDef`结构体配置输入捕获通道的参数,包括捕获极性、预分频系数等。 4. 初始化输入捕获通道:调用`HAL_TIM_IC_Init()`函数初始化输入捕获通道。 5. 启动定时器:调用`HAL_TIM_Base_Start()`函数启动定时器。 6. 获取输入捕获值:使用`HAL_TIM_IC_Start_IT()`函数启动输入捕获中断,并在中断回调函数中读取输入捕获值。 以下是一个示例代码,演示如何配置和使用基本定时器输入捕获功能: ```c #include "stm32f4xx_hal.h" /* 定时器句柄 */ TIM_HandleTypeDef htim2; /* 输入捕获值 */ uint32_t captureValue = 0; /* 定时器中断回调函数 */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { /* 读取输入捕获值 */ captureValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); } } } int main(void) { /* 初始化HAL库 */ HAL_Init(); /* 配置系统时钟 */ SystemClock_Config(); /* 初始化定时器 */ TIM2_Init(); /* 配置输入捕获通道 */ TIM2_IC_Config(); /* 启动定时器 */ HAL_TIM_Base_Start(&htim2); /* 启动输入捕获中断 */ HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); while (1) { /* 在这里可以进行其他操作 */ } } /* 定时器初始化 */ void TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFFFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim2); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig); } /* 输入捕获通道配置 */ void TIM2_IC_Config(void) { TIM_IC_InitTypeDef sConfigIC = {0}; htim2.Channel = HAL_TIM_ACTIVE_CHANNEL_1; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFFFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1); } ``` 上述代码使用了TIM2作为定时器,并配置了通道1进行输入捕获捕获上升沿触发的信号。在输入捕获中断回调函数中,可以读取输入捕获的值,并在主循环中进行其他操作。 请注意,上述代码仅为示例,具体的配置和使用方法需要根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值