欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

程序员文章站 2022-04-01 15:37:11
...

本文开发环境:

  • MCU型号:STM32F103C8T6
  • IDE环境: MDK 5.27
  • 代码生成工具:STM32CubeMx 5.6.1
  • HAL库版本:STM32Cube_FW_F1_V1.8.0

本文内容:

  1. STM32CubeMx 配置 定时器
  • 溢出中断
  • PWM输出
  • 输入捕获

附件 :

  • MDK工程:定时器溢出中断
  • MDK工程:定时器PWM输出
  • MDK工程:定时器输入捕获

一、 定时器

STM32 定时器其实就是一个计数器,用户可以设置计数的个数,方向(数值越来越大,或数值越来越小),初始值(从多少开始计数),计数的频率等等。

  • 溢出中断:当定时器计数结束后,可以产生一个中断
  • PWM输出:定时器计数值与用户设置的值匹配时候,改变IO口输出电平
  • 输入捕获: 当IO口电平为设置电平时候,定时器将此时计数的值保存到寄存器中,用户可以读取。

1. 溢出中断

溢出中断可以用来做一些周期性的动作,比如设置定时器的计数频率为72MHz,计数个数为72个,初始化值为0,并使能了自动装载(即使定时器计数完成后,自动重新把用户设置的初值装载到计数器中),那么每 1ms 就可以产生一次中断。

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
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
  • 配置系统时钟:设置为外部晶振
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
  • 配置系统时钟为最高的72M:STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
  • 打开 SW 调试口:用以ST-LINK下载和调试程序STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

定时器配置

  • 设置定时器的时钟和具体参数
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
    这里设置分频系数的值为7199,即 7200 分频,所以计数频率为 1KHz,计数值为4999,所以需要计算5000个数溢出,可见溢出的时间为500ms。

  • 使能溢出中断
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

  • 生成工程:
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

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! \r\n",cnt++);     //每次中断打印一次值
    }
}
/* USER CODE END 0 */

int main(void)
{
  ... ... 
  HAL_TIM_Base_Start_IT(&htim1);          //开启使能定时器中断
  while (1)
  {
      ... ...
  }
}

启用ST-LINK调试,可以看到Debug窗口每秒打印两次数据:
STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

三、PWM 输出 CubeMx 配置及程序实现

1. CubeMx 配置

配置基本与上文相同,需要稍作修改:

  • 打开通道1,作为PWM输出IO口:
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
  • 关闭溢出中断
    这里不需要处理溢出中断,所以可以将其关闭:
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
  • 生程工程
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
    如果保持默认,就会刷新原有的工程。

2. 程序设计

HAL 默认是没有打开PWM输出的,所以需要用户打开PWM输出,由于没有使用到PWM中断,所以只需使用库函数:HAL_TIM_PWM_Start();打开输出即可:

示例

int main(void)
{ 
  ... ...
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  while (1)
  {
  ... ...
  }
}

通过逻辑分析仪可以看到PA8产生了一个2Hz的方波:
STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

四、输入捕获 CubeMx 配置及程序实现

1. CubeMx 配置

CubeMx 输入捕获的配置与上文基本相同。

  • 将通道1设置为输入捕获通道:
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)- 在 NVIC 中 打开输入捕获中断
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)
  • 生成工程
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

2. 程序设计

STM32CubeMx 默认是上升沿捕获的,用户只需要:

  • 开始计数并使能捕获中断:
    HAL_TIM_IC_Start_IT(); 使能了定时器,并开启了捕获中断。
  • 使用中断函数
    HAL_TIM_IC_CaptureCallback() 是定时器捕获到指定电平的回调函数,它是一个弱函数,可以直接在其它定义,然后使用它。

注意,这个版本的库函数 TIM_RESET_CAPTUREPOLARITY 宏定义多出一个括号,需要用户改正, 否则无法编译通过:
STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

示例

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 ms\r\n",cap_time);   
		}
	}
}
... ...
int main(void)
{
... ...
  HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);;
}

通过PA8 点触 GND 的方法,可以观察到高电平时长的捕获。
STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)

五、附件

MDK5 示例工程
提取码:1234