当前位置: 首页 > article >正文

HAL+M4学习记录_8

一、TIM的HAL库用法

这里记录学习HAL库开发TIM

1.1 定时中断基本结构

这里给出定时中断的基本结构
定时中断
基本步骤如下

  • 开启时钟
  • 选择时基单元时钟源
  • 配置时基单元
  • 配置输出中断控制,允许更新中断输出到NVIC
  • 配置NVIC,打开定时器中断通道
  • 运行控制
  • 编写中断服务函数

1.2 常用API

stm32f4xx_hal_tim.c文件和stm32f4xx_hal_tim.h文件中,给出了定时器相关库函数,通过以下API使用定时器,TIM默认时钟是内部时钟,即APB总线时钟

  • HAL_TIM_xxx_MspInit()配置底层
  • 底层初始化具体实现,包括时钟使能、中断、DMA等
  • HAL_TIM_xxx_Init()配置定时器工作模式
  • HAL_TIM_xxx_Start()开启定时器外设

二、案例演示

2.1 基本定时器

这里以基本定时器TIM6为例,实现0.5s定时中断,中断服务函数为LED翻转并打印hello!,具体实现如下

  • 定时器配置
  • 定时器底层驱动初始化
  • 开启定时器
  • 中断服务函数
    源文件代码如下
/*
*********************************************************************************************************
*	                                   Module Description
*
*	定时器模块和PWM驱动模块
*	- 实现基本定时器TIM6的定时中断,中断服务函数为LED翻转
*********************************************************************************************************
*/
#include "bsp.h"

/* private variables */
TIM_HandleTypeDef TIM_TimeBaseStructure;

/* private function prototypes */
void basic_tim6_Config(uint16_t _arr, uint16_t _psc);

/*
**********************************************************************************
*   @brief    定时器初始化
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
void bsp_InitTim()
{
	basic_tim6_Config(5000 - 1, 8400 - 1);		// 0.5s定时器
}

/*
**********************************************************************************
*   @brief    将TIM6配置为定时器
*				- 0.5s产生一次中断
*				- 终端服务函数实现LED翻转
*   @param	  零个参数
*				- _arr:自动重装值
*				- _psc:预分频系数
*   @return	  None
*   @note	  
**********************************************************************************
*/
void basic_tim6_Config(uint16_t _arr, uint16_t _psc)
{
	TIM_TimeBaseStructure.Instance = BASIC_TIM;						// 定时器基地址
	TIM_TimeBaseStructure.Init.Prescaler = _psc;					// 预分频系数
	TIM_TimeBaseStructure.Init.CounterMode = TIM_COUNTERMODE_UP;	// 递增计数模式
	TIM_TimeBaseStructure.Init.Period = _arr;						// 自动重装载值
	
	if(HAL_TIM_Base_Init(&TIM_TimeBaseStructure) != HAL_OK)			// 配置为简单的时基模式
	{
		Error_Handler();
	}
	HAL_TIM_Base_Start_IT(&TIM_TimeBaseStructure);					// 使能定时器和定时器更新中断
	
}

/*
**********************************************************************************
*   @brief    定时器底层驱动
*				- 开启时钟
*				- 开启中断
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == BASIC_TIM)
	{
		BASIC_TIM_CLK_ENABLE();							// 使能TIM6时钟
		HAL_NVIC_SetPriority(BASIC_TIM_IRQn, 1, 3);		// 设置优先级
		HAL_NVIC_EnableIRQ(BASIC_TIM_IRQn);				// 开启中断
	}
}

/*
**********************************************************************************
*   @brief    基本定时器TIM6中断服务函数
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
void TIM6_DAC_IRQHandler()
{
	HAL_TIM_IRQHandler(&TIM_TimeBaseStructure);
}

/*
**********************************************************************************
*   @brief    中断回调函数
*   @param	  
*   @return	  
*   @note	  
**********************************************************************************
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == BASIC_TIM)
	{
		bsp_LedToggle(1);
		bsp_LedToggle(2);
		printf("hello!");
	}
}

头文件如下

#ifndef __BSP_TIM_PWM_H
#define __BSP_TIM_PWM_H

/* private define */
#define BASIC_TIM					TIM6
#define BASIC_TIM_CLK_ENABLE()		do{__TIM6_CLK_ENABLE();}while(0)
#define BASIC_TIM_IRQn				TIM6_DAC_IRQn


/* public statement */
void bsp_InitTim();

#endif

2.2 通用定时器

输出比较模式中,可比较CNT和CCR的值,来对输出电平进行控制,可用于输出PWM波。输出PWM波主要取决于两个寄存器,ARR控制频率;CCR控制占空比。输出比较模式总共有八种
输出比较
这里讲解PWM模式,由上图可知PWM1和PWM2区别是REF电平相反,其他都相同。有两种模式,边沿对齐模式和中心对齐模式可用于产生PWM波

  • 边沿对齐模式
    边沿对齐模式
    这里使用的是PWM1、向上计数模式,ARR=8那么计数器寄存器从0计数到8共9个单位。可以看到,设置CCR=4 C N T ≤ C C R CNT\leq CCR CNTCCR时REF输出高电平,在 C N T ≥ C C R CNT\geq CCR CNTCCR时输出低电平,其他CCR值以此类推。

  • 中心对齐模式
    中心对齐模式
    这里使用的是PWM1、上/下计数模式,ARR=8那么计数器寄存器从0计数到8后又从8计数到0共16个单位。可以看到,设置CCR=4 C N T ≤ C C R CNT\leq CCR CNTCCR时REF输出高电平,在 C N T ≥ C C R CNT\geq CCR CNTCCR时输出低电平,其他CCR值以此类推。

综上可以得出PWM基本结构总结如下
PWM基本结构
相应的参数计算如下

  • PWM信号的频率为 C K _ P S C ( P S C + 1 ) ⋅ ( A R R + 1 ) \frac{CK\_PSC}{(PSC+1)\cdot (ARR+1)} (PSC+1)(ARR+1)CK_PSC
  • PWM信号的占空比为 C C R A R R + 1 \frac{CCR}{ARR+1} ARR+1CCR
  • PWM信号分辨率为 1 A R R + 1 \frac{1}{ARR+1} ARR+11

这里给出定时器TIM的回调函数,有5种,分析如下

  ==============================================================================
                        ##### TIM Callbacks functions #####
  ==============================================================================
 [..]
   This section provides TIM callback functions:
   (+) TIM Period elapsed callback			非阻塞模式下定时器超时回调函数
   (+) TIM Output Compare callback			非阻塞模式下定时器输出比较回调函数
   (+) TIM Input capture callback			
   (+) TIM Trigger callback
   (+) TIM Error callback

这里给出通用定时器PWM输出配置步骤

  • 配置TIM,设置自动重装载值、预分频系数和计数模式等
  • 使能TIM时钟,配置输出比较模式,开启PWM模式
  • 配置TIM底层驱动,设置输出通道GPIO

具体代码实现如下

  • tim.c文件
/*
*********************************************************************************************************
*	                                   Module Description
*
*	通用定时器模块
*	- 使用通用定时器TIM3产生PWM波
*	- 通过Channel2输出PWM
*********************************************************************************************************
*/
#include "bsp.h"

/* private variables */
TIM_HandleTypeDef TIM3_HandleStructure;

/* private function prototypes */
void general_tim3_Config(uint16_t _arr, uint16_t _psc);

/*
**********************************************************************************
*   @brief   定时器初始化 
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
void bsp_InitTim()
{
	general_tim3_Config(500 - 1, 84 - 1);
}

/*
**********************************************************************************
*   @brief    将TIM3配置为定时器
*   @param	  两个参数
*				- _arr:自动重装值
*				- _psc:预分频系数
*   @return	  None
*   @note	  
**********************************************************************************
*/
void general_tim3_Config(uint16_t _arr, uint16_t _psc)
{
	TIM_OC_InitTypeDef TIM_OC_InitStructure = {0};
	
	GTIM_PWM_CLK_ENABLE();															// 使能TIM时钟
	
	TIM3_HandleStructure.Instance 				= GTIM_PWM;							// 定时器基地址
	TIM3_HandleStructure.Init.Prescaler 		= _psc;								// 预分频系数
	TIM3_HandleStructure.Init.Period 			= _arr;								// 自动重装载值
	TIM3_HandleStructure.Init.CounterMode 		= TIM_COUNTERMODE_UP;				// 递增计数
	TIM3_HandleStructure.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;	// 自动重装载预装载使能
	if(HAL_TIM_PWM_Init(&TIM3_HandleStructure) != HAL_OK)							// PWM模式初始化
	{
		Error_Handler();
	}
	
	TIM_OC_InitStructure.OCMode 				= TIM_OCMODE_PWM1;					// PWM模式1
	TIM_OC_InitStructure.Pulse 					= _arr / 2;							// 占空比
	TIM_OC_InitStructure.OCPolarity				= TIM_OCPOLARITY_LOW;				// 低电平有效
	TIM_OC_InitStructure.OCFastMode				= TIM_OCFAST_DISABLE;				// 失能快速输出比较
	
	HAL_TIM_PWM_ConfigChannel(&TIM3_HandleStructure, &TIM_OC_InitStructure, GTIM_PWM_CHANNEL);
	if(HAL_TIM_PWM_Start(&TIM3_HandleStructure, GTIM_PWM_CHANNEL) != HAL_OK)		// 开启PWM模式
	{
		Error_Handler();
	}
}

/*
**********************************************************************************
*   @brief    TIM3底层驱动,配置输出通道GPIO
*   @param	  TIM_HandleTypeDef *htim
*   @return	  None
*   @note	  
**********************************************************************************
*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == GTIM_PWM)
	{
		GPIO_InitTypeDef GPIO_InitStructure;
		
		GTIM_PWM_GPIO_CLK_ENABLE();								// GPIO端口时钟使能
		
		GPIO_InitStructure.Pin 			= GTIM_PWM_GPIO_PIN;	// PWM输出GPIO引脚配置
		GPIO_InitStructure.Mode 		= GPIO_MODE_AF_PP;		// PWM输出GPIO推挽输出
		GPIO_InitStructure.Alternate 	= GTIM_PWM_GPIO_AF;		// PWM输出GPIO复用模式
		GPIO_InitStructure.Speed 		= GPIO_SPEED_FREQ_HIGH;	// PWM输出GPIO端口速度
		HAL_GPIO_Init(GTIM_PWM_GPIO_PORT, &GPIO_InitStructure);
	}
}


  • tim.h文件
#ifndef __BSP_GTIM_H
#define __BSP_GTIM_H

/* private define */
#define GTIM_PWM_GPIO_PORT			GPIOA
#define GTIM_PWM_GPIO_PIN			GPIO_PIN_7
#define GTIM_PWM_GPIO_CLK_ENABLE()	do{__HAL_RCC_GPIOA_CLK_ENABLE();}while(0)
#define GTIM_PWM_GPIO_AF			GPIO_AF2_TIM3

// TIM重映射
#define GTIM_PWM					TIM3
#define GTIM_PWM_CHANNEL			TIM_CHANNEL_2
#define GTIM_PWM_CCR				TIM3->CCR1
#define GTIM_PWM_CLK_ENABLE()		do{__TIM3_CLK_ENABLE();}while(0)
#define GTIM_PWM_IRQn				TIM3_IRQn


/* public statement */
void bsp_InitTim();

#endif


http://www.kler.cn/news/359295.html

相关文章:

  • MySQL常见优化策略
  • xRDP – 在 Ubuntu 18.04、20.04、22.04、22.10、23.04(脚本版本 1.4.7)上轻松安装 xRDP
  • 如何使用外呼电话机器人的功能可以更高效的获客?
  • 高可用之限流-07-token bucket 令牌桶算法
  • hive on tez 指定队列后任务一直处于running状态
  • 开发规范 - mac系统1小时装机极速装机开发环境
  • 软件定义汽车时代,当前智能汽车软件开发模式是什么?
  • 探究互联网数字化商品管理变革:从数据化到精准运营的路径转型
  • 数据结构与算法JavaScript描述练习------第14章高级算法
  • CTFHUB技能树之SQL——整数型注入
  • .net framework 3.5sp1插件怎么安装
  • 【机器学习】任务七:聚类算法 (K-means 算法、层次聚类、密度聚类对鸢尾花(Iris)数据进行聚类)
  • 什么SNMP协议,怎么使用python调用SNMP访问设备
  • 【移动应用开发】界面设计(二)实现水果列表页面
  • 关于测试用例的写法
  • 云原生-降本增效最佳案例分享-学习笔记
  • WEB前端作业1
  • GO语言指针有那些限制
  • QT sql驱动错误QMYSQL driver not loaded
  • 离线安装bitnami-gitlab8.8.4+汉化