IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32实现PWM输出与PWM输入捕获(HAL库) -> 正文阅读

[嵌入式]STM32实现PWM输出与PWM输入捕获(HAL库)

一. 前言

前段时间,由于项目原因需要驱动四线风扇(电脑CPU用的散热风扇大多就是四线风扇),打算做一块风扇的驱动板。风扇通过输入PWM波来控制电机输出,而风扇内置了霍尔传感器,可以输出PWM信号,通过捕获波形信号可以得到信号的占空比、周期、频率等信息,换算后可以得到风扇的转速,实现对风扇的闭环控制。

过程主要使用STM32的定时器实现PWM输出与PWM捕获,项目完成后就把这两个知识整理后写成这篇博客。

二. STM32 定时器

STM32定时器可以分为:基本定时器通用定时器高级定时器,以STM32F1为例:

定时器类型定时器型号定时器总线定时器功能
基本定时器TIM6
TIM7
APB11. 拥有定时中断。
2. 主模式触发DAC的功能。
通用定时器TIM2
TIM3
TIM4
TIM5
APB11. 拥有基本定时器全部功能。
2. 具有内外时钟源选择。
3. 输入捕获。
3. 输出比较。
4. 编码器接口。
5. 主从触发模式等功能。
高级定时器TIM1
TIM8
APB21. 拥有通用定时器全部功能。
2. 具有重复计数器。
3. 死区生成。
4. 互补输出。
5. 刹车输入等功能。

它们之间的关系是:通用定时器具备基本定时器的所有功能并额外增加功能,高级定时器具备通用定时器所有功能并额外增加功能。

2.1 基本定时器

2.1.1 功能与框图

基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。其主要功能包括:
? ● 16位自动重装载累加计数器 。
? ● 16位可编程(可实时修改)预分频器,用于对输入的时钟按系数为1~65536之间的任意数值分频 。
? ● 触发DAC的同步电路 。
? ● 在更新事件(计数器溢出)时产生中断/DMA请求 。

2.1.2 CubeMX配置

以TIM6为例,在STM32CubeMX中通过以下参数设置基本定时器:

2.2 通用定时器

2.2.1 功能与框图

通用定时器主要功能包括:
? ● 16位向上、向下、向上/向下自动装载计数器。
? ● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值。
? ● 4个独立通道:
??- 输入捕获
??- 输出比较
??- PWM生成(边缘或中间对齐模式)
??- 单脉冲模式输出
? ● 使用外部信号控制定时器和定时器互连的同步电路。
? ● 如下事件发生时产生中断/DMA:
??- 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
??- 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
??- 输入捕获
??- 输出比较
? ● 支持针对定位的增量(正交)编码器和霍尔传感器电路。
? ● 触发输入作为外部时钟或者按周期的电流管理。

2.2.2 CubeMX配置

2.3 高级定时器

2.3.1 功能与框图

高级定时器在涵盖通用定时器所有功能的同时,多出如下特性:

? ● 死区时间可编程的互补输出。
? ● 允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器。
? ● 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态。
? ● 刹车信号输入事件发生时产生中断/DMA。

2.3.2 CubeMX配置

笔者用得不多,在此不作介绍。

三. 开发环境

开发环境: Keil 、CubeMX
软件版本: 5.31 、6.2.1
使用芯片: STM32F103C8T6
开发语言: C

四. STM32 PWM输出

PWM的输入输出需要使用通用定时器或者高级定时器。STM32F103C8T6有4个定时器,其中TIM1为高级定时器,TIM2、TIM3、TIM4为通用定时器,没有基本定时器,因此随便选择即可。

这里选择定时器TIM2,打开Channel1 选择功能PWM Generation CH1


配置参数如下:

注意:

PWM频率计算公式:

F = T i m e r C l o c k ( P r e s c a l e r + 1 ) ? ( C o u n t e r P e r i o d + 1 ) F=\frac{TimerClock}{(Prescaler+1)*(CounterPeriod+1)} F=(Prescaler+1)?(CounterPeriod+1)TimerClock????????????(1)

PWM周期计算公式:

T = 1 F = ( P r e s c a l e r + 1 ) ? ( C o u n t e r P e r i o d + 1 ) T i m e r C l o c k T=\frac{1}{F}=\frac{(Prescaler+1)*(CounterPeriod+1)}{TimerClock} T=F1?=TimerClock(Prescaler+1)?(CounterPeriod+1)?????(2)

若有效电平为High,采用PWM模式一时,PWM占空比计算公式:

D u t y = C C R x C o u n t e r P e r i o d + 1 Duty=\frac{CCRx}{{CounterPeriod}+1} Duty=CounterPeriod+1CCRx????????????????????????????????(3)

若有效电平为High,采用PWM模式二时,PWM占空比计算公式:

D u t y = C o u n t e r P e r i o d + 1 ? C C R x C o u n t e r P e r i o d + 1 Duty=\frac{CounterPeriod+1-CCRx}{{CounterPeriod}+1} Duty=CounterPeriod+1CounterPeriod+1?CCRx??????????????????????(4)

若有效电平为Low,则上述(3)、(4)公式变为1-Duty,计数方式(向上向下计数)并不影响占空比的计算公式 。

其中TimerClock为对应定时器的时钟频率;Prescaler为预分频系数;CounterPeriod为重装载值;CCRx为比较寄存器的值,在代码工程中可以使用函数__HAL_TIM_SetCompare()修改CCRx的值从而修改PWM的占空比。

PWM模式一: 在PWM1模式下,无论是向上计数还是向下计数,TIMx_CNT<TIMx_CCR1时通道1为有效电平,有效电平可以在 CH Polarity 参数中设置。

PWM模式二: 在PWM2模式下,无论是向上计数还是向下计数,TIMx_CNT>TIMx_CCR1时通道1为有效电平。

初始脉冲宽度(Pulse): 脉冲宽度即高电平持续的时间,Pluse与CounterPeriod+1的比值即为PWM的初始占空比。

自动预重装载(auto-reload preload): 当使能自动预重装载时,自动重装载寄存器写入新值后,计数器立即产生计数溢出,然后开始新的计数周期;当不使能自动预重装载时,自动重装载寄存器写入新值后,计数器完成当前旧的计数后,再开始新的计数周期。

假设采用如上配置,配置TIM2通道一作为PWM输出,只需在代码工程中调用如下两条函数便可以实现PWM的控制。

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//初始化,开启PWM

__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,1000);//设置比较寄存器CCRx的值,占空比=CCRx/ARRx 此处 CCRx=1000,ARRx=65536

五. STM32 PWM输入捕获

定时器的PWM输入捕获的框图如下,由通用定时器的框图剪裁得到(去掉了一些与输入捕获无关的功能):


PWM输入捕获流程如下:
1. PWM信号由TIMx_CH1进入,依据是上升沿还是是下降沿从而触发TI1FP1或TI1FP2。
2. 当捕捉到第一次上升沿时,触发TI1FP1,计数器复位,计数值CNT清零。
3. 当捕捉到下降沿时,触发TI1FP2,CNT计数值在TIMx_CH2中被记录到TIMx_CCR2寄存器中。
4. 当再次捕捉到上升沿时,触发TI1FP1,CNT计数值在TIMx_CH1中被记录到TIMx_CCR1寄存器中,同时计数器复位,计数值清零。
5. 依据TIMx_CCR1、TIMx_CCR2的值便可以计算PWM的周期、频率、占空比。TIMx_CCR1的值就是周期, T I M x C C R 2 T I M x C C R 1 \frac{TIMxCCR2}{TIMxCCR1} TIMxCCR1TIMxCCR2?的值就是占空比。

关于PWM的输入捕获,有两种CubeMX的配置方式,虽然配置方式不一样但是效果和原理都是完全一致的

方法一:

这是网上大多数帖子的推荐配置,非常麻烦,这里不推荐使用。


方法二(推荐使用):

方法二与方法一原理与效果是一样的,只不过ST官方考虑到PWM输入捕获较为常用,可以一键配置。只需在Combined Channels中选择PWM Input on CH1同时打开定时器中断即可。


配置完成后在代码中完成定时器的中断回调函数,便可计算PWM的占空比、频率、周期。


/**
*  @brief 定时器中断回调函数
*  @note  htim 定时器句柄
*/

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim2)
	{
		if(htim2.Channel == HAL_TIM_ACTIVE_CHANNEL_1)    
		{
			/* 记录TIM2_CCR1的值 */
			PWM_RisingCount = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
			
			if(PWM_RisingCount != 0 && PWM_FallingCount!= 0)
			{
				PWM_Duty        = (float)(PWM_FallingCount / PWM_RisingCount);//占空比
				PWM_Period      = PWM_RisingCount*0.000001f;                  //周期
				PWM_Frequency   = 1/PWM_Period;                               //频率
			}
		}
		else if(htim2.Channel == HAL_TIM_ACTIVE_CHANNEL_2)
		{	
			/* 记录TIM2_CCR2的值 */
			PWM_FallingCount = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);
		}
	}
}

五. 实战项目

前言所说的风速控制板最终效果如下,非常简单,使用TIM1四路PWM输出用于控制四个LED灯,通过呼吸灯的方式指示风扇转速;使用TIM3一路PWM用于控制风扇输出(PWM频率为25KHz)。使用TIM4用于PWM捕获,测出PWM频率后转化风扇转速。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:12:15  更:2022-09-24 21:13:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:43:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码