1.基础定时器

基础定时器相关函数
HAL_TIM_Base_Init(TIM_HandleTypeDef *htim); 定时器初始化,设置各种参数和连续定时模式
HAL_TIM_Base_MspInit() 弱函数,在HAL_TIM_Base_Init()里被调用,需重新实现
HAL_TIM_OnePulse_Init() 将定时器配置为单次定时模式,需要先执行HAL_TIM_Base_Init()
HAL_TIM_Base_Start() 以轮询工作方式启动定时器,不会产生中断
HAL_TIM_Base_Stop() 停止轮询工作方式的定时器
HAL_TIM_Base_Start_IT() 以中断工作方式启动定时器,发生UEV事件时产生中断
HAL_TIM_Base_Stop_IT() 停止中断工作方式定时器的
HAL_TIM_Base_Start_DMA() 以DMA工作方式启动定时器
HAL_TIM_Base_Stop_DMA() 停止DMA工作方式的定时器
HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim) 获取基础定时器的当前状态
其他通用操作函数
__HAL_TIM_ENABLE(__HANDLE__) 启 用 某 个 定 时 器 , 就 是 将 定 时 器 控 制 寄 存 器TIMx_CR1的CEN位置1
__HAL_TIM_DISABLE() 禁用某个定时器
__HAL_TIM_GET_COUNTER() 在运行时读取定时器的当前计数值 , 就 是读 取TIMx_CNT寄存器的值
__HAL_TIM_SET_COUNTER() 在运行时设置定时器的计数值,就是设置TIMx_CNT寄存器的值
__HAL_TIM_GET_AUTORELOAD() 在运行时读取自重载寄存器TIMx_ARR的值
__HAL_TIM_SET_AUTORELOAD() 在运行时设置自重载寄存器TIMx_ARR的值,并改变定时的周期
__HAL_TIM_SET_PRESCALER() 在运行时设置与分频系数,就是设置分频寄存器TIMx_PSC的值
4.中断处理
__HAL_TIM_GET_FLAG() 获取某个事件是否触发的标志,就是读取状态寄存器TIMx_SR中相应的中断事件位是否置1
__HAL_TIM_GET_IT_SOURCE() 判断是否是某个事件产生的中断,返回值为SET或RESET
__HAL_TIM_CLEAR_IT() 清除某个事件的中断标志,就是将状态寄存器TIMx_SR中相应的中断事件位是否置0
__HAL_TIM_ENABLE_IT() 启用某个事件的中断,就是将中断使能寄存器TIMx_DIER中相应事件位置1
__HAL_TIM_DISABLE_IT() 禁用某个事件的中断,就是将中断使能寄存器TIMx_DIER中相应事件位置0
HAL_TIM_IRQHandler() 定时器ISR函数里的通用处理函数
HAL_TIM_PeriodElapsedCallback(htim) 弱函数,UEV事件中断的回调函数
5使用示例
有tim6和tim7,使用tim6举例:1.在引脚界面选择引脚对应模式为tim6_ch12.将HCLK设置为100MHz,APB1和APB2时钟50MHz,方便计算3.在Timer界面选择Tim6,勾选Actived启动Tim6,Prescalar预分频值49999,实际分频值为50000,Counter Period计数周期,也就是自动重装载寄存器ARR的值,设置为500,NVIC界面使能TIM6全局中断及UEV事件中断使能,此时Tim6每500ms产生一次硬件中断。要时勾选One Pulse Mode则只中断一次。4.在程序中使用HAL_TIM_Base_Start_IT(&htim6);以中断方式启动TIM6.5.在void TIM6_DAC_IRQHandler(void)中会调用回调函数,所以只需要重写回调函数。6.编写void HAL_TIM_PeriodElapsedCallback(TIM_HandlerTypeDef *htim){if(htim->Instance==TIM6)//或者使用htim==&htim6判断代码部分}

2.HAL_通用定时器TIM
基础定时器6,7挂载总线APB1,高级定时器1,8,通用定时器为其它定时器
时基单元包括3个寄存器:
(1)计数寄存器(CNT),这个寄存器存储计数器当前的计数值,可以在运行时被读取。
(2)预分频寄存器(PSC),寄存器数值范围0至65535,对应于分频系数1至65536。 
(3)自动重载寄存器(ARR),这个寄存器存储的是定时器计数周期。

2.生成PWM波相关HAL函数
HAL_TIM_PWM_Init() 生成PWM波的配置初始化,需先执行
HAL_TIM_Base_Init()进行定时器初始化
HAL_TIM_PWM_ConfigChannel() 配置PWM输出通道
HAL_TIM_PWM_Start() 启动生成PWM波,需要先执行
HAL_TIM_Base_Start()启动定时器
HAL_TIM_PWM_Stop() 停止生成PWM波
HAL_TIM_PWM_Start_IT() 以中断方式启动生成PWM波,需要先执行
HAL_TIM_Base_Start_IT()启动定时器
HAL_TIM_PWM_Stop_IT() 停止生成PWM波
HAL_TIM_PWM_GetState() 返回定时器状态,与HAL_TIM_Base_GetState()功能相同
__HAL_TIM_ENABLE_OCxPRELOAD() 使能CCR寄存器的预装载功能,为CCR设置的新值在下个UEV事件发生时才更新到CCR寄存器
__HAL_TIM_DISABLE_OCxPRELOAD() 禁止CCR寄存器的预装载功能,为CCR设置的新值立刻更新到CCR寄存器
__HAL_TIM_ENABLE_OCxFAST() 启用一个通道的快速模式
__HAL_TIM_DISABLE_OCxFAST() 禁用一个通道的快速模式
HAL_TIM_PWM_PulseFinishedCallback() 当计数器的值等于CCR寄存器的值时产生输出比较事件这是对应的回调函数定时器中断事件类型与回调函数
TIM_IT_CC1:
CC1/2通道输入捕获 HAL_TIM_IC_CaptureCallback(htim)
CC1/2通道输出比较 HAL_TIM_OC_DelayElapsedCallback(htim);HAL_TIM_PWM_PulseFinishedCallback(htim);
TIM_IT_UPDATE 更新事件(UEV) HAL_TIM_PeriodElapsedCallback(htim);
TIM_IT_TRIGGER TRGI触发事件 HAL_TIM_TriggerCallback(htim);
TIM_IT_BREAK 短路输入事件 HAL_TIMEx_BreakCallback(htim);
TIM_IT_COM 换相事件 HAL_TIMEx_CommutCallback(htim);

3.使用步骤(生成PWM波)

1.在引脚界面选择引脚对应模式为tim16_ch12.将HCLK设置为100MHz,APB1和APB2 timer clocks 设置为50MHz(不是外设时钟),方便计算3.在Timer界面选择Tim16,勾选Actived启动Tim16,Channel1设置为PWM Generation CH1;        Prescalar预分频值4999,实际分频值为5000,经过预分频后进入计数器的时钟频率就10 kHz,Counter Period计数周期,也就是自动重装载寄存器ARR的值,设置为200,所以一个计数周期200ms;auto-reload preload,自动重载预装载,即设置TIM14_CR1寄存器中的ARPE位;Pulse,PWM脉冲宽度,就是设置16位的捕获/比较寄存器CCR的值。脉冲宽度的值应该小于计数周期的值,这里设置为50,因为计数器的时钟频率是10kHz,所以脉冲宽度为5ms。CH Polarity,通道极性,就是CCR与CNT比较输出的有效状态,可以设置为高电平(High)或低电平(Low),此时Tim16每200ms产生一次硬件中断。要时勾选One Pulse Mode则只中断一次。NVIC中开启TIM中断,优先级为2;4.在程序中必须调用函数启动定时器,再启动定时器的PWM输出。HAL_TIM_Base_Start_IT(&htim14); //以中断方式启动TIM14HAL_TIM_PWM_Start_IT(&htim14,TIM_CHANNEL_1);//TIM14通道1, 启动生成PWM5.在void TIM6_DAC_IRQHandler(void)中会调用回调函数,所以只需要重写回调函数。6.重新实现回调函数HAL_TIM_PWM_PulseFinishedCallback(),在此回调函数里编写代码改变占空比。{if(htim->Instance==TIM16){__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,PulseWidth);//PulseWidth为变量脉冲宽度,之前CUBEMX设置的是50ms;Frequency=HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_2);//获取CCR当前的值。Frequency =10000/Frequency;CCR=(10000*FreqDiv*Voltage)/Frequency/330;ARR=10000*FreqDiv/Frequency;//如果要动态修改的两个值CCR=(CCR>=1)?CCR:1; ARR=( ARR>=2)?ARR:2;//记得写入前对数据范围进行判断。方式写0进入之后,没有脉冲,不会调用回调函数!!!__HAL_TIM_SetCompare (&htim3,TIM_CHANNEL_2,CCR);__HAL_TIM_SetAutoreload (&htim3,ARR );
/*__HAL_TIM_SetAutoreload(&htim2,ch1);这两个函数可以设置ARR计数器的值;__HAL_TIM_SET_AUTORELOAD(&htim2,ch1);
*/}}

如图4-1

4.TIM输出比较:

步骤:
1.LED对应引脚选择为TIMx_CHy;APB1/2时钟定时器为50MHz;timer中设置工作模式为Ouput Compare CH1;
2.Prescaler分频系数49999。Counter默认UP,即增量计数。Counter Period设置为500,即设置ARR寄存器,翻转周期。
3.Mode为Toggle on match.就是在计数器的值与CCR的值相等时使CH1输出翻转。Pulse脉冲宽度,这里设置为300,即300ms;
4.这样设置后,如果CCR和计数器的值匹配后,就会使CH1的输出翻转,且不管CCR的值为多少,方波的占空比都为50%,脉宽总与ARR的值相等。
5.main函数中加入HAL_TIM_Base_Start(&htim3);HAL_TIM_OC_Start(&htim4,TIM_CHANNEL_1);
6。下载程序:LED 500ms翻转一次

注意:在定时器初始化函数中,会将对应引脚工作模式设置为GPIO_MODE_AF_PP复用推挽输出,而使用LCD_Init()时G431开发板上的PC会设置为OUT_PP推挽输出,导致不正常工作。

5.输入PWM计算脉冲长短(双通道):

原理:输入比较通道CC1捕获上跳沿时,将计数器的值存入寄存器CCR1,同时复位计数器,输入比较通道CC2捕获下降沿时,将计数器的值存入寄存器CCR2,所以寄存器CCR1中的值表示PWM波的周期,CCR2中的值是PWM的脉宽。
步骤:
1.时钟APB1为50MHZ;TIM8时钟源为Internal Clock,引脚PA15设置为TIM8_CH1
2.Conbined Channals选择PWM Inout on Ch1;(CH1和CH2结合起来)
3.Prescaler预分频寄存器值设为4999,所以分频值为10KHz,Counter Period:ARR的值设置为50000,所以TIM8定时器周期应大于输入PWM周期,
4.Polarity Selection :CH1设置为RisingEdge上跳沿捕获,而CH2设置为相反的下降沿捕获,InputFilter设置为0,无需设置滤波,
5.NVIC打开中断,设置优先级
6.HAL_TIM_Base_Start(&htim8);
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_1);启动TIM8_CH1的IC功能
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_2);两个通道都要启动
6.重写回调函数void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{uint16_t IC1_Width=__HAL_TIM_GET_COMPARE(&htim8,TIM_CHANNEL_1);//CH1_CCR寄存器中放的是周期uint16_t IC2_Pulse=__HAL_TIM_GET_COMPARE(&htim8,TIM_CHANNEL_2);//CH2_CCR寄存器中放的是脉宽uint16_t temp=IC1_Width ;//获取了两个寄存器的值,分别代表周期和脉冲宽度if((IC1_Width==0)||(IC2_Pulse==0))return;temp=temp%10000;LCD_DisplayChar(Line2,319-(12*16),'0'+temp/1000);temp=temp%1000;LCD_DisplayChar(Line2,319-(13*16),'0'+temp/100);temp=temp%100;LCD_DisplayChar(Line2,319-(14*16),'0'+temp/10);temp=temp%10;LCD_DisplayChar(Line2,319-(15*16),'0'+temp);temp=IC2_Pulse;temp=temp%10000;LCD_DisplayChar(Line3,319-(12*16),'0'+temp/1000);temp=temp%1000;LCD_DisplayChar(Line3,319-(13*16),'0'+temp/100);temp=temp%100;LCD_DisplayChar(Line3,319-(14*16),'0'+temp/10);temp=temp%10;LCD_DisplayChar(Line3,319-(15*16),'0'+temp);
}

7.单通道捕获PWM

关于普通的输入模式捕获PWM。主要工作流程:1、第一次捕获到上升沿,计数器清零,存捕获寄存器值的变量清零,存中断次数的变量清零。改变触发边沿为下降沿触发,并将触发标志位为设置为1,使下次下降沿触发时,能进行相对应的处理。2、第一次捕获到下降沿,将捕获寄存器(CCR寄存器)的值,中断次数存入相应的变量。同时更改触发边沿为上升沿触发,并将触发标志位为设置为2,使下次上升沿触发时,能进行相对应的处理。3、第二次捕获到上升沿,再次将捕获寄存器(CCR寄存器)的值,中断次数存入相应的变量。将触发标志设置为0,目的为能够循环捕获。同时捕获完成标志为置1。4、在main函数中,使用在while循环,使用if语句进行捕获标志的轮询,从而在捕获完成后进行相应的数据处理。
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim==&htim2){switch(ICFlag){case 0://第一次上升沿__HAL_TIM_SetCounter (htim,0 );//计数器清零__HAL_TIM_SET_CAPTUREPOLARITY (htim,TIM_CHANNEL_2,TIM_ICPOLARITY_FALLING);//设置下降沿捕获ICFlag=1;break;case 1:Count1=HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_2);//捕获到下降沿,读出的值为高电平长度,单位为定时器定时一次时长__HAL_TIM_SET_CAPTUREPOLARITY (htim,TIM_CHANNEL_2,TIM_ICPOLARITY_RISING);//等待下一个上升沿__HAL_TIM_SetCounter (htim,0 );ICFlag=2;break;case 2:Count2=HAL_TIM_ReadCapturedValue (htim,TIM_CHANNEL_2);//读出的值为低电平长度ICFlag=0;break;}}
}
如果不用知道占空比,则不用改变捕获极性,两次上升沿间隔即为周期

4.基于STM32CubeMX使用TIM定时器相关推荐

  1. 【MCU】基于STM32CubeMX定时器中断实现LED闪烁

    基于STM32CubeMX定时器中断实现 LED 闪烁 本实验基于STM32CubeMX实现对STM32开发板的配置,通过定时器中断实现 LED 闪烁. Table of Contents 基于STM ...

  2. 【基于 STM32CubeMX + PWM + DMA驱动SW2812b全彩RGB灯】

    基于 STM32CubeMX + PWM + DMA驱动SW2812b全彩RGB灯 STM32CubeMX配置: 工程源码: END 以上就是相关配置,最需要注意的就是时钟以及pre数值以及芯片时钟频 ...

  3. 【STM32】HAL库 STM32CubeMX教程六----定时器中断

    前言: 今天我们来学习定时器,32的定时器有着非常丰富的功能, 输入捕获/输出比较,PWM,中断等等.是我们学习STM32最频繁使用到的外设之一,所以一定要掌握好,这节我们讲解定时器中断,本系列教程将 ...

  4. 每节课都是一个项目 手把手用STM32打造联网气象站-4-STM32基础三件套-TIM定时器和SYSTICK初始化

    STM32基础系列包含了三件套,掌握了这三件套,类似于掌握了程咬金三板斧,就可以开始干项目,创造价值了.毕竟,真正的编程是一项实战性很强的技术,掌握编程主要靠实战,而不是靠知识灌输. STM32的编程 ...

  5. 课程 | 基于STM32CubeMX和HAL驱动库的嵌入式系统设计

    帮成都这边一位老师友情分享一篇免费课程:基于STM32CubeMX和HAL驱动库的嵌入式系统设计. 如果想学习本课程,可以从文末给出的链接,或底部"阅读原文"进入报名,免费学习. ...

  6. 串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx

    引言:对于串口接收一些不定长的数据,必须面对一个问题:怎么判断一帧数据接收是否完成?通常使用RXNE非空中断配合简单的数据协议,在数据中加入帧头.帧尾,在程序中判断是否接收到帧尾来确定数据接收完毕,因 ...

  7. Linux基于升序链表的定时器

    模式简介 这是基于SIGALRM信号的定时器,关于该信号,可以参考这篇博客:https://blog.csdn.net/qq_35976351/article/details/86532889 本文来 ...

  8. 基于STM32cubemx的stm32f107vct6代码生成教程,实验一led闪烁

    基于STM32cubemx的stm32f107vct6代码生成教程 一.软件准备 *MATLAB2018a *Keil4/5 *STM32CUBEMX *STM2-MAT/TARGET 4.3.0 ( ...

  9. STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)

    本篇文章包含的内容 一.TIM 定时器 1.1 TIM 定时器简介 1.2 TIM 定时器类型及其工作原理简介 1.2.1 基本定时器工作原理及其结构 1.2.2 通用定时器工作原理及其结构 1.2. ...

最新文章

  1. Expo大作战(十八)--expo如何发布成独立应用程序,打包成apk或者ipa,发布到对应应用商店...
  2. DeepLearning:windows环境下C++环境实现Tensorflow编译部署
  3. leetcode 492. 构造矩形(Java版,三种解法)
  4. Java中部分常见语法糖
  5. 除了love和hate,还能怎么表达那些年的“爱恨情仇”?
  6. SpringBoot项目瘦身指南,大厂如何面试看出你的水平
  7. MySQL多线程并发调优
  8. JavaBridge install in ubuntu
  9. JCreator中怎样带参数运行程序,如何添加JDBC驱动程序
  10. md5和sha1文件完整性校验
  11. Jupyter notebook使用类错误提示 takes no arguments
  12. 按键精灵post请求_按键精灵安卓版能发送post和get请求吗
  13. 聚划算火拼如何参团 聚划算火拼效果怎么样
  14. 优信php面试流程_上海优信智能科技有限公司
  15. AR502H-CN开发笔记54:OVF和OVA的区别
  16. 来自法院解释股权代持就涵盖了股权转让的意思
  17. UE4热更新:需求分析与方案设计
  18. OpenGL ES_手把手教你打造VR全景播放器
  19. 从串口驱动到Linux驱动模型
  20. 非周期连续傅立叶变换的推导

热门文章

  1. Please reinstall the libzip distribution
  2. 励志22岁Android程序员小伙高中学历,现上海拿到25K offer,不迭代升级还等着被取代吗?
  3. 用计算机弹千本樱谱,原神千本樱琴谱怎么弹_风物之诗千本樱琴谱介绍_3DM网游...
  4. shell正则表达式提取数字
  5. Python之正则表达式小练
  6. Java常用工具类-发短信(集成云通信的企业信使短信平台)
  7. 华为OJ基础题-学英语
  8. Javascript在线调试安卓工具的实现
  9. Bottle模板引擎分析
  10. 基于SSM框架开发的零食商城系统