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模式1TIM_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.rhkb.cn/news/453599.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么九齐单片机中不能使用bit?

如果开发环境不支持bit 定义static unsigned char task_720ms_flag 0;还可以用什么方式替代bit定义标志,使其占用内存空间小。 如果开发环境不支持位定义,可以使用 unsigned char 的多个状态位来替代。可以将多个标志合并到一个 unsigned char 中&…

Vue - Element 选择器 el-select 既可以选择下拉又可以手动输入文本功能(手动输入的值只能是数字 并且支持4位小数)

Vue - Element 选择器 el-select 既可以选择下拉又可以手动输入文本功能(手动输入的值只能是数字 并且支持4位小数) 备注 filterable 下拉框开启快速搜索功能 no-match-text 当输入的内容在下拉框中找不到时;下拉框提示的文字 handFocus 触发…

软件测试快速入门:测试对象、过程模型、生命周期与测试用例

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

redis集群介绍

Redis集群是一种分布式存储系统,它通过将数据分散存储在多个Redis节点上来实现可扩展性和高可用性。每个节点都是一个独立的Redis服务器实例,它们通过网络相互连接,共同协作以提供数据服务。 在Redis集群中,数据被划分为多个槽&am…

【Vercel】Vercel静态部署踩坑

背景 在现代的软件开发中,自动化部署是一个不可或缺的环节。Vercel作为一个流行的前端部署平台,提供了与GitHub的无缝集成,使得开发者能够在每次提交代码后自动触发部署流程。然而,自动化部署过程中可能会遇到一些挑战&#xff0…

自动化工具:Ansible

目录 一、运维自动化工具有哪些 二、Ansible 概述 1、Ansible 概念 2、Ansible 特点 3、Ansible 工作流程 三、安装部署Ansible 1、环境部署 2、管理节点安装 Ansible 3、查看Ansible相关文件 4、配置主机清单 5、免密管理 ssh-keygen 5.1、测试连通性 5.2、简洁输…

IPC通信-消息队列

使用消息队列实现两个进程的相互通信 #include<myhead.h>//定义结构体存储信息种类和信息正文 typedef struct {long mtype; //信息类型char mtext[128]; //信息正文 }msgbuf;//宏定义信息正文的大小 #define MESIZE sizeof(msgbuf)-sizeof(long)typedef struct sockad…

vscode:创建fastapi项目

1.选择py解释器 或者 uvicorn main:app --reload

java游戏网站源码

题目&#xff1a;java游戏网站源码 编号B22A390 主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Mysql|大数据|SSM|SpringBoot|Vue|Jsp|MYSQL等)、学习资料、JAVA源码、技术咨询 文末联系获取 感兴趣可以先收藏起来&#xff0c;以防走丢&#xff0c;有任何选题、文档编…

雷池WAF自动化实现安全运营实操案例终极篇

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

Unity DOTS中的Archetype与Chunk

Unity DOTS中的Archetype与Chunk 在Unity中&#xff0c;archetype&#xff08;原型&#xff09;用来表示一个world里具有相同component类型组合的entity。也就是说&#xff0c;相同component类型的entity在Unity内部会存储到一起&#xff0c;共享同一个archetype。 使用这样的设…

React是如何工作的?

从编写组件到最后屏幕生成界面&#xff0c;如上图所示&#xff0c;我们现在需要知道的就是后面几步是如何运行的。 概述 这张图解释了 React 渲染过程的几个阶段&#xff1a; 渲染触发&#xff1a;通过更新某处的状态来触发渲染。渲染阶段&#xff1a;React 调用组件函数&…

智能优化算法-生物地理学算法(BBO)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍 生物地理学优化算法 (Biogeography-Based Optimization, BBO) 是一种基于生物地理学原理的元启发式优化算法&#xff0c;由Dan Simon于2008年提出。BBO通过模拟物种在不同栖息地之间的迁移过程来搜索最优解&…

Dongle Sentinal在Jenkins下访问不了的问题

背景&#xff1a; 工作站部署的jenkins的脚本无法正常打包&#xff0c;定位后发现是本地获取不了license&#xff0c;但是使用usb over network的远程license都能获取并正常打包 分析&#xff1a; 获取不了license的原因是本地无法识别dongle。根据提供信息&#xff0c;之前…

卡特兰数解释相关的样例以及补充例题

目录 拓展的场景分析 1.圆上连接线段 2.二叉树问题 3.多边形划分三角形问题 补充的例题 P1976 鸡蛋饼 P1722 矩阵 II 通过取模处理判断选择用哪个式子​编辑 P2532 [AHOI2012] 树屋阶梯 P3978 [TJOI2015] 概率论 拓展的场景分析 1.圆上连接线段 一个圆上有2*n个点&am…

nginx中的HTTP 负载均衡

HTTP 负载均衡&#xff1a;如何实现多台服务器的高效分发 为了让流量均匀分配到两台或多台 HTTP 服务器上&#xff0c;我们可以通过 NGINX 的 upstream 代码块实现负载均衡。 方法 在 NGINX 的 HTTP 模块内使用 upstream 代码块对 HTTP 服务器实施负载均衡&#xff1a; upstr…

基于微博评论的自然语言处理情感分析

目录 一、项目概述 二、需要解决的问题 三、数据预处理 1、词汇表构建&#xff08;vocab_creat.py&#xff09; 2、数据集加载&#xff08;load_dataset.py&#xff09; 四、模型构建&#xff08;TextRNN.py&#xff09; 1、嵌入层&#xff08;Embedding Layer&#xff…

Unity通过高德开放平台获取天气信息

一、注册高德开放平台账号&#xff0c;获取天气接口Key 1、构建自己的应用 网址&#xff1a;https://lbs.amap.com/api/webservice/guide/api/weatherinfo 最终调用api的地址形式&#xff1a; https://restapi.amap.com/v3/weather/weatherInfo?city110101&key<用户…

ionic Capacitor 生成 Android 应用

官方文档 https://ionic.nodejs.cn/developing/android/ https://capacitorjs.com/docs/getting-started 1、创建新的 Capacitor 应用程序 空目录下面 npm init capacitor/app2、install Capacitor npm install npm start在这里插入图片描述 3、生成dist目录 npm run buil…

华为eNSP:MAC地址漂移防止与检测

一、什么是MAC地址漂移&#xff1f; MAC地址漂移是指在计算机网络中&#xff0c;MAC&#xff08;Media Access Control&#xff09;地址被动态更改的现象。每个网络接口设备都有一个唯一的MAC地址&#xff0c;用来标识该设备在网络中的身份。然而&#xff0c;有些恶意软件或网…