STM32CubeMX教程6 TIM 通用定时器 - 生成PWM波
1、准备材料
开发板(STM32F407G-DISC1)
ST-LINK/V2驱动
STM32CubeMX软件(Version 6.10.0)
keil µVision5 IDE(MDK-Arm)
逻辑分析仪nanoDLA
2、实验目标
使用STM32CubeMX软件配置STM32F407通用定时器生成可变占空比PWM波形,并将其输出到LED灯引脚实现呼吸灯效果
3、实验流程
3.0、前提知识
STM32F407有10个通用定时器,其中TIM2、TIM3、TIM4和TIM5有4个捕获/比较通道,TIM9、TIM12两个定时器有2个捕获/比较通道,剩下的TIM10、TIM11、TIM13和TIM14只有一个捕获/比较通道,只有一个捕获/比较通道的通用定时器在CubeMX配置页面无“Slave Mode”和“Trigger Source”的选项,也不能联合通道,相较于拥有多个捕获/比较通道的定时器较为简单,这10个通用定时器具体特性如下表所示(注释1)
对于通用定时器来说,其每个通道均可以实现①输入捕获、②输出比较、③PWM波生成三种功能,接下来我将分三个实验来分别介绍通用定时器的这三个功能,本小节只介绍通用定时器如何生成PWM波
在“GPIO输出-点亮LED灯”小节我们介绍了如何使用GPIO输出点亮开发板上的LED灯,从而知道了开发板上控制LED灯的四个引脚分别为PD12、PD13、PD14和PD15,这四个引脚刚好可以配置为通用定时器TIM4的四个输出通道,因此接下来我们将配置这四个引脚为通用定时器TIM4的4个通道的PWM输出引脚
3.1、CubeMX相关配置
请先阅读“STM32CubeMX STM32F4 HAL库 工程建立”实验3.4.1小节配置RCC和SYS
3.1.1、时钟树配置
系统时钟树配置与上一实验一致,均设置为STM32F407总线能达到的最高时钟频率,具体如下图所示
3.1.2、外设参数配置
在Pinout & Configuration页面右边芯片引脚预览Pinout view中找到LED灯的四个控制引脚PD12、PD13、PD14和PD15,依次左键单击并配置其功能为TIM4_CHx
然后在页面左侧功能分类栏目中点开Timers栏目,单击栏目下的TIM4,并将其Channel1~4全部配置为PWM Generation CHx
具体配置如下图所示
然后对启用的TIM4定时器的四个通道参数进行设置,下面对重要参数简单介绍
①PSC:该参数为时钟源预分频系数,由于TIM4时钟来源为APB1 Timer clocks (MHz),笔者这里为84MHz,因此经过8399+1=8400分频后的频率为10KHz;
②计数模式:可以选择向上、向下、中心对齐等计数方式;
③ARR:该参数决定了生成PWM的周期,这里设置为199,表示周期为20ms,注意这里周期不能太长(注释2);
④预装载自动重装:设置为Enable后,当修改ARR的值时会在下一个UEV事件生效,否则表示不适用预装载,修改其值会立即生效
⑤PWM模式选择:可以选择模式1/模式2,这两种模式区别为生成的PWM波形不一样,选择PWM模式1且向上计数时,当Pulse值<计数值ARR时此时通道输出有效状态,否则为无效状态,当选择PWM模式2时刚好与模式1相反。如下面两个PWM波形中,上图为采用PWM模式1,通道极性为高电平时产生的PWM波,下图为采用PWM模式2,通道极性为高时产生的PWM波;
⑥Pulse值:即捕获/比较寄存器CRR的值,通过设置该参数可以决定PWM的脉冲宽度,这里设置为0,因为程序中可以动态修改该参数
⑦输出比较预装载:设置为Enable后,当修改Pulse的值时会在下一个UEV事件生效,否则会立即生效
⑧通道极性:设置通道有效状态
如下图所示为具体参数设置
3.1.3、外设中断配置
在Pinout & Configuration页面左边System Core/NVIC中勾选TIM4全局中断,然后选择合适的中断优先级即可
3.2、生成代码
请先阅读“STM32CubeMX STM32F4 HAL库 工程建立”实验3.4.3小节配置Project Manager
单击页面右上角GENERATE CODE生成工程
3.2.1、外设初始化调用流程
在工程代码主函数main()中调用MX_TIM4_Init()函数对定时器TIM4计数器参数及四个 PWM通道参数进行了配置
在该MX_TIM4_Init()函数中调用了HAL_TIM_PWM_Init()对定时器PWM输出进行了初始化
然后在HAL_TIM_PWM_Init()函数中调用了HAL_TIM_PWM_MspInit()函数对TIM4时钟和中断设置/使能
如下图所示为具体的TIM4四通道PWM输出初始化调用流程
3.2.2、外设中断调用流程
勾选了TIM4的全局中断之后,在工程文件stm32f4xx_it.c中生成了TIM4全局中断服务函数TIM4_IRQHandler()
该函数调用了HAL库的定时器中断统一处理函数HAL_TIM_IRQHandler(),最终调用PWM脉宽调制完成回调函数 HAL_TIM_PWM_PulseFinishedCallback(),该函数为虚函数
如下图所示为TIM4四通道PWM输出中断调用流程
3.2.3、添加其他必要代码
在tim.c中重新实现PWM脉宽调制完成回调函数HAL_TIM_PWM_PulseFinishedCallback(),在该回调函数中实现了对四个通道PWM的占空比重新调节的目的,即重新配置参数里的Pulse,实现了从最低占空比逐渐到最大占空比然后再逐渐减少至最低占空比的无限循环,具体代码如下所示
源代码如下
uint16_t pulseWidth=0;
uint8_t dirInc=1;
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance != TIM4)
return;
if(dirInc == 1)
{
pulseWidth ++;
if(pulseWidth >= 195)
{
pulseWidth = 195;
dirInc = 0;
}
}
else
{
pulseWidth --;
if(pulseWidth <= 5)
{
pulseWidth = 5;
dirInc = 1;
}
}
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, pulseWidth);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, pulseWidth);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, pulseWidth);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_4, pulseWidth);
}
最后在主函数中以中断方式启动生成PWM即可,如下所示为启动代码
4、常用函数
/*启动定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
/*停止定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
/*启动PWM输出*/
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
/*停止PWM输出*/
HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
/*以中断方式启动定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
/*以中断方式停止定时器*/
HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim)
/*以中断方式启动PWM输出*/
HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
/*以中断方式停止PWM输出*/
HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
/*PWM输出完毕回调函数*/
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
/*设置PWM占空比函数*/
__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)
5、烧录验证
5.1、具体步骤
“设置TIM4的4个通道为PWM输出 -> 配置TIM4基本参数及4个PWM通道参数 -> NVIC中勾选TIM4全局中断并设置合适中断优先级 -> 在生成的工程tim.c文件中重新实现PWM脉宽调制完成回调函数void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) -> 在回调函数中利用__HAL_TIM_SET_COMPARE(HANDLE, CHANNEL, COMPARE)宏定义设置4个通道PWM的占空比 -> 在主函数中使用HAL_TIM_Base_Start_IT(&htim4)启动定时器TIM4 -> 然后使用HAL_TIM_PWM_Start_IT(&htim4, TIM_CHANNEL_x)函数开启四个通道PWM波的输出”
5.2、实验现象
烧录程序,会发现开发板上电后四个LED灯亮度由最暗到最亮然后从最亮再到最暗循环往复,实现呼吸灯的效果
使用逻辑分析仪监测TIM4的四个通道输出引脚状态,可以看出TIM4的四个通道输出的PWM波型周期均为20ms,并且占空比不断地在发生变化
6、注释详解
注释1:图片来源STM32Cube高效开发教程(基础篇)9.1小节
注释2:这里的周期设置为20ms,也即频率为50Hz,人眼睛对于80Hz以上刷新频率完全没有闪烁感,因此如果你实现LED呼吸灯效果有闪烁情况的话,频率不能设置的太低
更多内容请浏览 OSnotes的CSDN博客
STM32CubeMX教程6 TIM 通用定时器 - 生成PWM波的更多相关文章
- STM32F103定时器输出PWM波控制直流电机
这个暑假没有回家,在学校准备九月份的电子设计竞赛.今天想给大家分享一下STM32高级定时器输出PWM波驱动直流电机的问题.. 要想用定时器输出的PWM控制直流电机,,首先要理解“通道”的概念..一个定 ...
- TIM—高级定时器输出PWM
高级定时器输出PWM 主频144M,生成一个频率为1K,占空比为30%的PWM详细代码参考EVT例程PWM_Output 重要参数说明 TIM_TimeBaseInitStructure.TIM_Pe ...
- stm32cube--通用定时器--产生pwm波
看了通用定时器的资料,发现内容挺多,挺难看懂,现在还是先掌握使用方法,以后再多看几遍吧. ① ② ③生成mdk工程后,在main.c的while(1)前面加上HAL_TIM_PWM_Start(&am ...
- 案例 高级定时器和通用定时器产生pwm的区别 gd32和stm32
- 第32章 TIM—高级定时器—零死角玩转STM32-F429系列
第32章 TIM—高级定时器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
- STM32通用定时器(转载)
STM32的定时器功能很强大,学习起来也很费劲儿. 其实手册讲的还是挺全面的,只是无奈TIMER的功能太复杂,所以显得手册很难懂,我就是通过这样看手册:while(!SUCCESS){看手册-}才搞明 ...
- (五)转载:通用定时器PWM输出
1. TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有 ...
- STM32(7)——通用定时器PWM输出
1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种 ...
- stm32之通用定时器TIM
STM32系列的CPU,有多达8个定时器: 1.其中TMI1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动:它们的时钟有APB2的输出产生: 2.其它6个为普通定时器,时钟由 ...
- 第31章 TIM—基本定时器—零死角玩转STM32-F429系列
第31章 TIM—基本定时器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
随机推荐
- maven缺失ojdbc6解决方法(手动安装ojdbc6)
maven缺失ojdbc6解决方法(手动安装ojdbc6) 1. 首先下载ojdbc6jar包 jar下载地址一(需登录) jar下载地址二(直接下载) 2. 进入到jar包所在文件夹,执行cmd命令 ...
- 熟练掌握并充分利用CSS3的新特性,更新完毕。
1.1 尝试新颖的CSS3特性 首先,我们来看一个具体的案例. https://code.juejin.cn/pen/7277536985772720139 1.2 CSS3新特性简介和浏览 ...
- 【RocketMQ】事务实现原理总结
RocketMQ事务的使用场景 单体架构下的事务 在单体系统的开发过程中,假如某个场景下需要对数据库的多张表进行操作,为了保证数据的一致性,一般会使用事务,将所有的操作全部提交或者在出错的时候全部回滚 ...
- 基于AI模型的验证码安全识别(B站,知乎等)
bilibili 汉字识别顺序验证码 实现基本思路: 先利用Selenium模拟登录,当然在这之前做好请求伪装,get方法使边框最大化,并且将系统的windows窗口缩放比例设置为100%, ...
- html表单与框架
1.以form开头 其中常用的属性有 action="" method="" enctype="" name="" ...
- DevOps|研发效能解决的是企业效率问题
研发效能并不能解决企业效益问题 它不是利润中心,不能给你带来直接收入(研发效能相关工具厂商做咨询.出方案.卖工具除外).想要解决企业效益问题,依赖于企业战略.业务/产品.组织.运营.创新等其他方面. ...
- 关于如何解决visualc++6.0打开文件闪退的一种方式(附带解决输入法无法显示)
这里我把VisualC++6.0安装程序和filetool分享在我的网盘里面了 网盘下载QAQ 链接:https://pan.baidu.com/s/1azSMX_cOKgb64WT7-gTdbQ?p ...
- POSIX 真的不适合对象存储吗?
最近,留意到 MinIO 官方博客的一篇题为"在对象存储上实现 POSIX 访问接口是坏主意"的文章,作者以 S3FS-FUSE 为例分享了通过 POSIX 方式访问 MinIO ...
- k8s Rabbitmq安装部署
安装方式 kubectl apply -f rabbitmq.yaml -n yunda-dev-cache rabbitmq.yaml ##创建PV # 注意更换存储方式 --- apiVersio ...
- SpringBoot数据响应、分层解耦、三层架构
响应数据 @ResponseBody 类型:方法注解.类注解 位置:Controller方法.类上 作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合 ,将会转换为json格式响应 说明:@ ...