深圳市航顺芯片技术研发有限公司
直播中

李巍

7年用户 1481经验值
私信 关注
[问答]

小编科普STM32CubeMx是如何配置定时器的

什么是STM32定时器?
溢出中断CubeMx配置及程序是如何实现的?
PWM输出CubeMx配置及程序是如何实现的?

回帖(1)

孔朱磊

2021-8-18 17:52:40
  本文开发环境:
  MCU型号:STM32F103C8T6
  IDE环境: MDK 5.27
  代码生成工具:STM32CubeMx 5.6.1
  HAL库版本:STM32Cube_FW_F1_V1.8.0
  本文内容:
  STM32CubeMx 配置 定时器
  溢出中断
  PWM输出
  输入捕获
  附件 :
  MDK工程:定时器溢出中断
  MDK工程:定时器PWM输出
  MDK工程:定时器输入捕获
  一、 定时器
  STM32 定时器其实就是一个计数器,用户可以设置计数的个数,方向(数值越来越大,或数值越来越小),初始值(从多少开始计数),计数的频率等等。
  溢出中断:当定时器计数结束后,可以产生一个中断
  PWM输出:定时器计数值与用户设置的值匹配时候,改变IO口输出电平
  输入捕获: 当IO口电平为设置电平时候,定时器将此时计数的值保存到寄存器中,用户可以读取。
  1. 溢出中断
  溢出中断可以用来做一些周期性的动作,比如设置定时器的计数频率为72MHz,计数个数为72个,初始化值为0,并使能了自动装载(即使定时器计数完成后,自动重新把用户设置的初值装载到计数器中),那么每 1us就可以产生一次中断。
  2. PWM输出
  PWM可以设置极性等,简单来说,用户可以设置定时器的计数频率为72MHz,计数个数为72个,对比数值为36,那么定时器启动以后,就会从0计数到72,计数到第36个时,就改变一次电平,这样就会输出要给方波,用户可以通过不断修改对比值,来产生一系列PWM。
  3. 输入捕获
  输入捕获可以用来捕获IO口的电平,用户可以设置定时器的计数频率为72MHz,计数个数为72个,捕获电平为高电平,那么定时器启动以后,就会从0计数到72,如果捕获到高电平,就把该电平的值保存到寄存器中,供用户读取。通常可以用来捕获一个电平的宽度,比如设置高电平捕获,捕获到高电平时候,读取计数的值,然后设置为低电平捕获,捕获到低电平以后,读取这个计数的值,那么两个值的差,就是高电平的时间。
  4. 时基与通道
  STM32 的定时器可以有多个通道,不同通道可以独立设置,比如PWM输出中不同通道可以有不同的占空比,但是一个定时器同时只能有一个计数频率,用户无法让TIM1(定时器1)通道1输出 38KHz PWM,通道2输出 50KHz PWM,但是可以输出2个 38Khz 占空比不同的 PWM。
  二、溢出中断 CubeMx 配置及程序实现
  1. CubeMx 配置
  基础配置
  基础配置是每一个工程都必须的,包括系统时钟,指定延时函数定时器,打开调试口等:
  选择芯片:STM32F103C8T6
  配置系统时钟:设置为外部晶振
  配置系统时钟为最高的72M:
  打开 SW 调试口:用以ST-LINK下载和调试程序
  定时器配置
  设置定时器的时钟和具体参数
  这里设置分频系数的值为7199,即 7200 分频,所以计数频率为 1KHz,计数值为4999,所以需要计算5000个数溢出,可见溢出的时间为500ms。
  使能溢出中断
  生成工程:
  2. 程序设计
  NOTE:本文使用 ST-LINK 输出打印信息作为调试方法,详见:STM32 使用 ITM 输出调试信息
  STM32CubeMx 默认是生成 HAL 库函数,HAL 生成的函数会自动添加初始化函数,用户只需要:
  使能中断:
  HAL_TIM_Base_Start_IT(); 使能了定时器,并开启了中断。
  使用中断函数
  HAL_TIM_PeriodElapsedCallback() 是定时器溢出后的回调函数,它是一个弱函数,可以直接在其它定义,然后使用它。
  示例
  /* USER CODE BEGIN 0 */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(TIM1 == htim-》Instance) { static uint16_t cnt = 0; printf(“Update %d! rn”,cnt++); //每次中断打印一次值 }}/* USER CODE END 0 */int main(void){ 。。。 。。。 HAL_TIM_Base_Start_IT(&htim1); //开启使能定时器中断 while (1) { 。。。 。。。 }} 启用ST-LINK调试,可以看到Debug窗口每秒打印两次数据:
  三、PWM 输出 CubeMx 配置及程序实现
  1. CubeMx 配置
  配置基本与上文相同,需要稍作修改:
  打开通道1,作为PWM输出IO口:
  关闭溢出中断
  这里不需要处理溢出中断,所以可以将其关闭:
  生程工程
  如果保持默认,就会刷新原有的工程。
  2. 程序设计
  HAL 默认是没有打开PWM输出的,所以需要用户打开PWM输出,由于没有使用到PWM中断,所以只需使用库函数:HAL_TIM_PWM_Start();打开输出即可:
  示例
  int main(void){ 。。。 。。。 HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); while (1) { 。。。 。。。 }} 通过逻辑分析仪可以看到PA8产生了一个2Hz的方波:
  
  四、输入捕获 CubeMx 配置及程序实现
  1. CubeMx 配置
  CubeMx 输入捕获的配置与上文基本相同。
  将通道1设置为输入捕获通道:
  - 在 NVIC 中 打开输入捕获中断
  生成工程
  2. 程序设计
  STM32CubeMx 默认是上升沿捕获的,用户只需要:
  开始计数并使能捕获中断:
  HAL_TIM_IC_Start_IT(); 使能了定时器,并开启了捕获中断。
  使用中断函数
  HAL_TIM_IC_CaptureCallback() 是定时器捕获到指定电平的回调函数,它是一个弱函数,可以直接在其它定义,然后使用它。
  注意,这个版本的库函数 TIM_RESET_CAPTUREPOLARITY 宏定义多出一个括号,需要用户改正, 否则无法编译通过:
  示例
  uint32_t cap_start;uint32_t cap_end;uint32_t cap_time;uint8_t flg_cap = 1; //状态标志位void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){ if(TIM1 == htim-》Instance) { switch(flg_cap){ case 1: cap_start = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1); //获取当前的捕获值。 TIM_RESET_CAPTUREPOLARITY(&htim1, TIM_CHANNEL_1); //复位捕获极性 TIM_SET_CAPTUREPOLARITY(&htim1, TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING); //设置为下降沿捕获 flg_cap = 0;; break; case 0: cap_end = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);//获取当前的捕获值。 cap_time = (float)(cap_end - cap_start)/2.5; printf(“高电平时间: %d msrn”,cap_time); } }}。。。 。。.int main(void){。。。 。。。 HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);;} 通过PA8 点触 GND 的方法,可以观察到高电平时长的捕获。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分