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

本文开发环境:

  • 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
    请添加图片描述
  • 配置系统时钟:设置为外部晶振
    请添加图片描述
  • 配置系统时钟为最高的72M:请添加图片描述
  • 打开 SW 调试口:用以ST-LINK下载和调试程序请添加图片描述

定时器配置

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

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

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

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输出,输入捕获)_第4张图片

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

1. CubeMx 配置

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

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

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设置为输入捕获通道:
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)_第8张图片- 在 NVIC 中 打开输入捕获中断
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)_第9张图片
  • 生成工程
    STM32F1x HAL库学习笔记(11)定时器配置及中断(溢出中断,PWM输出,输入捕获)_第10张图片

2. 程序设计

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

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

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

示例

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输出,输入捕获)_第12张图片

五、附件

MDK5 示例工程
提取码:1234

你可能感兴趣的:(#,使用,STM32CubeMx,配置,STM32,外设)