stm32 笔记 PWM输入模式测量脉宽和占空比原理
一、PWM 输入模式测量脉宽
1.1 测量脉宽简介
在测量占空比之前,我们先一步一步来,先让 STM32 可以测量脉宽。
TIM3_CH1(tim3 定时器通道 1)捕获模式测量脉宽步骤如下:
1.输入捕获到 PWM 上升沿触发
2.发送中断,通知用户此时被触发,用户获得当前计数器值
3.计数器清零,然后继续计数...
让 STM32 芯片一直重复这三步即可不断地测量出当前的 PWM 脉宽。
1.2 测量脉宽原理
首先我们可以使用 PWM 的复位 Reset 模式,它复合我们之前所要求的功能。具有捕捉上升沿和计数器复位的能力。
如果我们使用 TIM_CH1,可以产生分别是TI1FP1 与TI1FP2 这一对信号。他们的功能是分别是捕捉上升沿和下降沿。
其原理是:
二者都是来自同一 TI1 输入通道,经过输入滤波和边沿检测器后所产生的具有相同特征的信号,然后映射到不同的输入捕捉通道,本质上还是同一路信号。
TI1FP1,是来自于通道TI1,经过滤波器后将接到捕捉比较通道 IC1;
TI1FP2,是来自于通道TI1,经过滤波器后将接到捕捉比较通道 IC2;
由这张图得知,所谓 IC1 就是上升沿信号,TI1FP1会捕获到。IC2 是下降沿信号,TI1FP2 会捕捉到。
1.3 cubeMX 配置
①和②在上文已经详细介绍,不再赘述
③我们使用内部时钟
④重点来了!我们捕捉的通道是 TIM_CH1 如果我们走红色这条线,即可用后面的 TI1FP1 捕捉到上升沿。使用直接捕获模式(input capture direct mode)即可。如果需要捕获 TI1FP2 的下降沿则需要使用 重映射输入捕获(input capture direct from remap)。
⑤配置分频系数,我的系统时钟是 80mhz,分频 80 则为 1mhz,所以计数速度是 每秒1000000次。
⑥计数器最大值为 65535,所以测量最大的脉宽则为 65536/1000000 = 0.065536 秒。取倒数大约为 15.25hz 所以请不要测量超过这个值的脉宽,否则就会溢出清零,导致测量不准。
⑦默认值,配置为上升沿计数。
1.3 cubeMX 生成的代码解析
/*STM32cubeMX 生成的 TIM3 初始化代码:*/
/* TIM3 init function */
void PWM_TIM3_CHANNEL_1_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *//* USER CODE END TIM3_Init 0 */TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_SlaveConfigTypeDef sSlaveConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_IC_InitTypeDef sConfigIC = {0};/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */htim3.Instance = TIM3; //指定需要配置的定时器htim3.Init.Prescaler = 79; //定时器的预分频系数htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 65535; //定时器计数周期值htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //定时器分频因子htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //计数达到指定值后,定时器是否自动重装载计数值if (HAL_TIM_Base_Init(&htim3) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; //使用STM32单片机内部时钟if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_IC_Init(&htim3) != HAL_OK) //进行初始化{Error_Handler();}sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; //设置定时器模式 复位模式sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; //使用TI1FP1触发sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING; //上升沿触发sSlaveConfig.TriggerFilter = 0;//滤波if (HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;sConfigIC.ICFilter = 0;if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM3_Init 2 *//* USER CODE END TIM3_Init 2 */}
输入GPIO口的配置:
大致是设置复用端口配置、时钟相关配置。比较简单就不全都注释了。
让我困惑的是为什么这个捕获 PWM 的引脚被配置成 GPIO_MODE_AF_PP 复用推挽输出,难道不应该是输入吗?
/*STM32cubeMX 生成的 TIM3 初始化代码:*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_baseHandle->Instance==TIM3){/* USER CODE BEGIN TIM3_MspInit 0 *//* USER CODE END TIM3_MspInit 0 *//* TIM3 clock enable */__HAL_RCC_TIM3_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**TIM3 GPIO ConfigurationPB4 ------> TIM3_CH1*/GPIO_InitStruct.Pin = GPIO_PIN_4;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* TIM3 interrupt Init */HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM3_IRQn);/* USER CODE BEGIN TIM3_MspInit 1 *//* USER CODE END TIM3_MspInit 1 */}
}
1.4 需要我们写的获取值的代码
经过下降沿后会自动触发中断,在回调函数中判断下是 TIM3通道1发出的,就可以调用HAL_TIM_ReadCapturedValue() 取值了。
HAL_TIM_Base_Start(&htim3);
/* 启动定时器通道输入捕获并开启中断 */
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1); void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM3){if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){PWM1_T_Count = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)+1;}}}
二、测量占空比
2.1 测量占空比分析
基于之前测量脉宽的逻辑,如果我们把测量上升沿配置成主模式,测量下降沿配置成从模式。STM32将会是这样的逻辑:
1.在上升沿复位两个计数器
2.下降沿暂停下降沿计数器
3.再次上升沿复位两个计数器
不断重复....
在之前测量脉宽我们使用了 TI1FP1 线路测量上升沿,不过测量下降沿则需要 TI1FP2 辅助,将其信号类似“转发”到 TIM_CH2 线路中 (下图红色线路)。也就是说,当我们在 TIM_CH1 同时捕捉上升沿和下降沿,就会占用 TIM_CH2 线路。
2.2 cubeMX 配置
基于之前的配置,我们需要将①通道2配置为从模式;在②中,将这个配置为下降沿触发。
2.3 需要我们写的代码
节约篇幅不再解释 cubeMX 生成的代码,直接贴出我们需要写的代码:
//输入捕获中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM3){if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){PWM1_T_Count = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)+1; //捕获脉宽PWM1_Duty = (float)PWM1_D_Count/PWM1_T_Count; //捕获占空比}else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){PWM1_D_Count = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;//捕获下降沿} }}
stm32 笔记 PWM输入模式测量脉宽和占空比原理相关推荐
- c++ 定时器_【话说定时器系列】之十:PWM输入模式测量脉宽及占空比实验
STM32定时器是 ST MCU 内部最基础且常用的外设,实际应用尤为普遍.去年,电堂推出了<STM32 TIMER基础及常规应用介绍>,为大家梳理了 STM32 TIMER 的庞大内容, ...
- STC用PCA测量脉宽_「话说定时器系列」之九:定时器单通道测量脉宽和占空比
STM32定时器是 ST MCU 内部最基础且常用的外设,实际应用尤为普遍.去年,电堂推出了<STM32 TIMER基础及常规应用介绍>,为大家梳理了 STM32 TIMER 的庞大内容, ...
- STC用PCA测量脉宽_【话说定时器系列】之九:定时器单通道测量脉宽和占空比
STM32定时器是 ST MCU 内部最基础且常用的外设,实际应用尤为普遍.去年,电堂推出了<STM32 TIMER基础及常规应用介绍>,为大家梳理了 STM32 TIMER 的庞大内容, ...
- 使用c++ 实现定时触发键盘事件_基于定时器捕获测量脉宽的应用示例
我们知道,利用单片机定时器捕获功能测量脉冲信号宽度及占空比是种很常见的做法.这里以STM32的定时器为例来介绍基于其捕获功能实现对脉宽的测量的思路及过程. 一般来讲,使用STM32定时器的捕获功能来实 ...
- 基于定时器捕获测量脉宽的应用示例
我们知道,利用单片机定时器捕获功能测量脉冲信号宽度及占空比是种很常见的做法.这里以STM32的定时器为例来介绍基于其捕获功能实现对脉宽的测量的思路及过程. 一般来讲,使用STM32定时器的捕获功能来实 ...
- 高级定时器之输入捕获应用(测量脉宽)
高级定时器-输入捕获应用 输入捕获一般应用在两个方面,一个方面是脉冲跳变沿时间测量,另一方面是PWM输入测量. 测量脉宽或者频率 测量频率 当捕获通道TIx上出现上升沿时,发生第一次捕获,计数器C ...
- STM32F407输入捕获应用--PWM 输入模式测量脉冲频率与宽度
STM32F407输入捕获应用--PWM 输入模式测量脉冲频率与宽度 一.测量脉宽或者频率 二.PWM 输入模式 三.软件实现 3.1.硬件准备 3.2代码 3.4 验证 输入捕获一般应用在两个方面, ...
- stm32 输入捕获 测量脉宽
选用通用定时器TIM5的CH1. PA0接一个按键,默认接GND,当按键按下时,IO口被拉高,此时,可利用定时器的输入捕获功能,测量按键按下的这段高电平的时间. 宏定义方便程序升级.移植,举个例子: ...
- STM32CubeMX | 使用STM32定时器的PWM输入模式测量脉冲宽度和周期
STM32CubeMX | 使用STM32定时器的PWM输入模式测量脉冲宽度和周期 目录 STM32CubeMX | 使用STM32定时器的PWM输入模式测量脉冲宽度和周期 1.介绍 2.STM32C ...
最新文章
- ROS 总结(三):Moveit!配置助手
- JDK源码重新编译——支持eclipse调试JDK源码--转载
- Android MVVM封装,MVVMFramework
- php鸡兔同笼试题,数学运算之鸡兔同笼问题
- python字典的键可以是元组吗_python字典的键可以是元组吗
- Xamarin效果第二十篇之GIS中加载三维白模
- Hive报错:Error: FUNCTION 'NUCLEUS_ASCII' already exists. (state=X0Y68,code=30000)
- Keil 文本对不上格
- Android逆向笔记-IDA Pro动态调试Android程序(真机)
- html游戏脚本,网页游戏脚本软件道
- 有关产品项目管理的ISO/IEC/IEEE标准
- 扫描问题 无法识别计算机,我的扫描枪插进去显示无法识别怎么办
- TeXLive升级教程
- debezium报错处理系列七:The database history couldn‘t be recovered. Consider to increase the value for datab
- Android Alarm闹钟
- 求助 关于word安全模式
- 数值计算笔记之数值积分(二)龙贝格算法
- Python 之 格式化输出
- 令人拍案叫绝的15个二维码
- docker学习——bind mounts