正点原子--STM32基本定时器学习笔记(2)
目录
1. 相关寄存器介绍
1.1 控制寄存器 1(TIMx_CR1)编辑
1.2 DMA/中断使能寄存器(TIMx_DIER)
1.3 状态寄存器(TIMx_SR)
1.4 计数器(TIMx_CNT)
1.5 预分频器(TIMx_PSC)
1.6 自动重装载寄存器(TIMx_ARR)
2. 工程建立
3. 导入tim.c文件
4. 相关HAL库函数介绍
4.1 HAL_TIM_Base_Init()
4.2 HAL_TIM_Base_MspInit()
4.3 HAL_TIM_Base_Start_IT()
5. 编写代码
书接上文,本篇是对基本定时器实验部分进行总结!
实验目标:通过TIM6基本定时器定时500ms,让LED0每隔500ms闪烁。
解决思路:使用定时器6,实现500ms产生一次定时器更新中断,在中断里执行“翻转LED0”。
定时器什么时候会产生更新中断呢?
有两种情况:第一种是定时器计数到ARR值后溢出,这时会伴随更新事件和更新中断的产生;第二种是通过软件的方式,设置UG位产生软件的更新中断,从而产生更新中断。
1. 相关寄存器介绍
首先我们来学习控制寄存器 1(TIMx_CR1)、DMA/中断使能寄存器(TIMx_DIER)、状态寄存器(TIMx_SR)、计数器(TIMx_CNT)、预分频器(TIMx_PSC)、自动重装载寄存器(TIMx_ARR)的功能。
1.1 控制寄存器 1(TIMx_CR1)
首先介绍位7,由上篇理论部分的笔记中我们知道:
影子寄存器:是实际起作用的寄存器,不能直接访问,而ARPE位决定了ARR是否具有缓冲,当设置为有缓冲时,ARR的预装载寄存器写入某个值,这个值不会立即起作用,必须等到更新事件发生时,才会把ARR的预装载寄存器的值转移到影子寄存器,从而真正起作用生效;而设置无缓冲时,给ARR的预装载寄存器写入某个值,它会立即转移到影子寄存器中,会立即生效。(立即生效的时间可能在ns或是us级)
预装载寄存器实际上起到一个缓冲的作用。
比如:我们想让LED灯实现亮1s灭2s的功能,那么我们就需要对应操作ARR寄存器的值。假设系统时钟为72MHz,定时器预分频系数为7200,72000000/(7199+1)=10000,定时器将以10KHz的频率计数,即1s计10000个数,那么ARR值就为9999,倘若定时2s,ARR值需要修改为19999。
当ARPE配置为0,即ARR寄存器无缓冲时,我们先把ARR的值设为9999,定时1s,1s时间到达之后,需要再次操作ARR寄存器的值变为19999来定时2s,而操作ARR寄存器也需要一定时间(可能是ns或us级),相对于秒级来说微秒可以忽略不计了,但是如果定时的是50us,而操作ARR寄存器的时间也是微秒级,那就会有误差了!
当ARPE配置为1,即ARR寄存器有缓冲时,先让ARR设为9999生效,定时1s,这时我们再次修改ARR的值为19999,当1s到之后更新事件发生,才会把19999从ARR预装载寄存器转移到影子寄存器,从而节省了操作ARR寄存器的时间,精度也会很准确!
总结一下:有缓冲,提前写入,减少误差;无缓冲,按时写入,有误差。



再者介绍位0(CEN:计数器使能),默认情况下该位为0,计数器是关闭的状态;开启时把该位置1。
总结控制寄存器1在该实验的功能:用于设置ARR寄存器是否具有缓冲,使能/关闭计数器
1.2 DMA/中断使能寄存器(TIMx_DIER)

默认条件下,位8和位0都是0都是禁止状态。
当把位8置1即使能更新DMA请求,计数器计数溢出时就会产生DMA请求;
同理,把位0置1,当计数器溢出时会产生更新中断。此次实验用到了位0,没有用到位8。
总结中断使能寄存器在该实验的功能:用于使能更新中断
1.3 状态寄存器(TIMx_SR)

该寄存器只有位0有效,当计数器溢出时产生更新中断,该位被硬件置1,由程序编写清除。
总结:用于判断是否发生了更新中断,由硬件置1,软件清零
1.4 计数器(TIMx_CNT)

16位的计数器,实时数值,可用于设置计时器初始值,范围:0~65535
1.5 预分频器(TIMx_PSC)

用于设置预分频系数,范围:0~65535,实际预分频系数等于PSC+1。
1.6 自动重装载寄存器(TIMx_ARR)

当更新时间发生时,才会把预装载寄存器的值传送到其对应的影子寄存器当中,用于设置自动重装载值,范围:0~65535。
总结:预分频器和自动重装载寄存器实际起作用的都是对应的影子寄存器。
2. 工程建立
介绍完相关寄存器之后,现在开始实操训练了。也是以正点原子HAL库 实验1 跑马灯实验为基础,相当于是工程模板了,我们复制工程,在“Drivers--BSP”目录下建立TIMER文件夹,并创建tim.c和tim.h文件;

3. 导入tim.c文件
导入方法和上篇帖子一样,不清楚的小伙伴可以参考⬇⬇⬇⬇⬇
正点原子--STM32中断系统学习笔记(2)
在tim.h文件中添加这部分代码(之后自己新建的.c和.h文件都会按照此模板创建)
#ifndef _TIM_H
#define _TIM_H
#include "./SYSTEM/sys/sys.h"#endif
重要的一点是要添加hal库tim的驱动文件!!!不然编译不通过
4. 相关HAL库函数介绍

4.1 HAL_TIM_Base_Init()
我们找到这个函数的定义,分别去HAL_StatusTypeDef和TIM_HandleTypeDef里面看看。

返回值:

形参为定时器的句柄 :


下图为TIM6定时器的基地址

定时器初始化结构体成员:


Prescaler/*预分频系数*/ 对应操作PSC寄存器;
CounterMode/*计数模式*/ 基本定时器只有向上计数模式;
Period/*自动重载值*/ 对应操作ARR寄存器;
ClockDivision/*时钟分频因子*/ 基本定时器无该寄存器,只有通用/高级寄存器才需要配置;
RepetitionCounter/*重复计数器寄存器的值*/ 基本/通用定时器都无该寄存器,只有高级定时器才有用
AutoReloadPreload/*自动重载预装载使能*/ 对应控制寄存器1的位7:ARPE
在这次实验当中,我们只用到了三个:Prescaler、Period、AutoReloadPreload.
4.2 HAL_TIM_Base_MspInit()

该函数没有对应的寄存器,__weak是弱定义,用户可自己编写,主要在函数里存放NVIC、CLOCK、GPIO初始化代码。
4.3 HAL_TIM_Base_Start_IT()



中断处理函数和更新中断回调函数在之前的中断帖子有介绍,大同小异!
正点原子--STM32中断系统学习笔记(1)
5. 编写代码
配置思路:我们按照正点原子给的步骤一步步来配置,最重要的是学习配置思路,一通百通!!


①在定时器中断初始化函数里对定时器的参数进行配置(包括:基地址、自动重装载值、预分频值),以及使能更新中断并开启计数器;
②在定时器基础MSP初始化函数里,先进行检测是否为TIM6定时器,如果是TIM6,那么就使能TIM6时钟,并设置中断优先级和使能中断;这点和标准库配置有些差别,标准库是一开始就先使能时钟,而HAL库是在这个函数里完成那些功能!
③在TIM6中断服务函数里调用定时器中断公共处理函数,在定时器中断公共处理函数里进行清中断标志位,调用定时器中断回调函数HAL_TIM_IC_CaptureCallback()的操作。


④ 在定时器溢出中断回调函数里,先进行检测是否为TIM6定时器,如果是TIM6,那么就进行LED0的翻转。
执行流程:
在main函数里先进行定时器中断初始化配置,tim_it_init(4999, 7199);
定时500ms,时间一到便会产生定时器更新中断,进入TIM6中断服务函数,执行定时器中断公共处理函数(进行清中断标志位,调用定时器中断回调函数,在回调函数里进行LED灯的翻转)

以下是tim.c的代码:
#include "./BSP/TIMER/tim.h"
#include "./BSP/LED/led.h"TIM_HandleTypeDef tim_handle;/* 定时器中断初始化函数 */
void tim_it_init(uint16_t arr, uint16_t psc)
{tim_handle.Instance = TIM6;tim_handle.Init.Prescaler = psc;tim_handle.Init.Period = arr;HAL_TIM_Base_Init(&tim_handle); /* 配置定时器基础工作参数 */HAL_TIM_Base_Start_IT(&tim_handle); /* 使能更新中断并启动计数器 */
}/* 定时器基础MSP初始化函数 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM6) /* 判断定时器的基地址是否为TIM6 */{__HAL_RCC_TIM6_CLK_ENABLE(); /* 使能定时器6时钟 */HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0); /* 设置优先级 */HAL_NVIC_EnableIRQ(TIM6_IRQn); /* 使能中断 */}
}/* 定时器6中断服务函数 */
void TIM6_IRQHandler(void)
{HAL_TIM_IRQHandler(&tim_handle); /* 定时器中断公共处理函数 */
}/* 定时器溢出中断 中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM6) /* 判断定时器的基地址是否为TIM6 */{LED0_TOGGLE();LED1_TOGGLE();}
}
main.c代码:
#include "stm32f1xx_it.h"
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/tim.h"int main(void)
{HAL_Init(); /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟,72M */delay_init(72); /* 初始化延时函数 */led_init(); /* 配置STM32操作LED相关的寄存器 */tim_it_init(4999, 7199); /* 初始化定时器 */while(1){}
}
以上就是基本定时器实验的所有内容了!
本篇完。
本人博客仅代表个人见解方便记录成长笔记。
若有不足,请指出,感谢您的阅读!
相关文章:
正点原子--STM32基本定时器学习笔记(2)
目录 1. 相关寄存器介绍 1.1 控制寄存器 1(TIMx_CR1)编辑 1.2 DMA/中断使能寄存器(TIMx_DIER) 1.3 状态寄存器(TIMx_SR) 1.4 计数器(TIMx_CNT) 1.5 预分频器(TIMx_PSC) 1.6 自动重装载寄存器(TIMx_ARR) 2. 工程建立 3. 导入tim.c文件 4. 相关HAL库函数介绍 4.1 H…...
学习笔记:正则表达式
正则表达式是文本处理方面功能最强大的工具之一。正则表达式语言用来构造正则表达式,最终构造出来的字符串就称为正则表达式,正则表达式用来完成搜索和替换操作。 本文参考《正则表达式必知必会(修订版)》《Learning Regular Exp…...
03-抓包_封包_协议_APP_小程序_PC应用_WEB应用
抓包_封包_协议_APP_小程序_PC应用_WEB应用 一、参考工具二、演示案例:2.1、WEB应用站点操作数据抓包-浏览器审查查看元素网络监听2.2、APP&小程序&PC抓包HTTP/S数据-Charles&Fiddler&Burpsuite2.3、程序进程&网络接口&其他协议抓包-WireSh…...
C语言笔试题之实现C库函数 strstr()(设置标志位)
实例要求: 1、请你实现C库函数strstr()(stdio.h & string.h),请在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始);2、函数声明:int strStr(char* h…...
什么是IDE,新手用哪个IDE比较好
什么是IDE IDE(Integrated Development Environment,集成开发环境)是一种为程序员提供软件开发所需的代码编辑、构建、调试等功能于一体的应用程序。IDE通常包含了代码编辑器、编译器、调试器和图形用户界面等工具,这些工…...
Flask 入门6:模板继承
1. 一个网站中,大部分网页的模块是重复的,比如顶部的导航栏,底部的备案信息。如果在每个页面中都重复的去写这些代码,会让项目变得臃肿,提高后期的维护成本。比较好的做法是,通过模板继承,把一…...
欢迎来到操作系统的世界
🌞欢迎来到操作系统的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 🙏作者水平很有限,如果发现错误ÿ…...
寒假作业-day5
1>现有无序序列数组为23,24,12,5,33,5347,请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用直接插入排序实现升序排序 函数4:请使用插入排序实现升序排序 代码: #include<stdio.h&g…...
互联网加竞赛 基于深度学的图像修复 图像补全
1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学的图像修复 图像补全 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-se…...
用于制作耳机壳的UV树脂耳机壳UV胶价格高不高?
制作耳机壳的UV树脂价格相对于一些其他材料可能会略高,但具体的价格取决于多个因素,如品牌、型号、质量等。一些高端的UV树脂品牌和型号可能会价格较高,但它们也通常具有更好的性能和更广泛的应用范围。 此外,UV树脂的价格也与购买…...
【开源】JAVA+Vue+SpringBoot实现房屋出售出租系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…...
Golang 并发 生产者消费者模式
Golang 并发 生产者消费者模式 生产者-消费者模式能够带来的好处 生产者消费者模式是一种常见的并发编程模式,用于解决生产者和消费者之间的数据传递和处理问题。在该模式中,生产者负责生成数据(生产),而消费者负责处…...
Win32 SDK Gui编程系列之--ListView自绘OwnerDraw
ListView自绘OwnerDraw 1.ListView自绘OwnerDraw 正在试错是否使用了列表视图,尽量制作出智能的表格编辑器。本页显示了业主抽签的表格数据(二维数组数据)的显示方法。 显示画面和整个程序如下所示。使用ListView_GetSubItemRect宏的话,就不需要getRect函数了。 当nCol的…...
深度学习本科课程 实验5 循环神经网络
循环神经网络实验 任务内容 理解序列数据处理方法,补全面向对象编程中的缺失代码,并使用torch自带数据工具将数据封装为dataloader分别采用手动方式以及调用接口方式实现RNN、LSTM和GRU,并在至少一种数据集上进行实验从训练时间、预测精度、…...
Redis篇之过期淘汰策略
一、数据的过期策略 1.什么是过期策略 Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。 2.过期策略-惰…...
【Kubernetes】kubectl top pod 异常?
目录 前言一、表象二、解决方法1、导入镜像包2、编辑yaml文件3、解决问题 三、优化改造1.修改配置文件2.检查api-server服务是否正常3.测试验证 总结 前言 各位老铁大家好,好久不见,卑微涛目前从事kubernetes相关容器工作,感兴趣的小伙伴相互…...
前后端分离项目:前端的文件夹应该叫什么名字,后端呢
在前后端分离的项目中,为了提高项目的可读性和易管理性,给前端和后端的文件夹选择合适的名字是很重要的。这里提供一些建议,但请记住,最终的命名应该根据你的团队习惯、项目特性以及可能的公司规定来决定。 ### 前端文件夹命名建…...
2024.2.6
1.现有无序序列数组为23,24,12,5,33,5347,请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用快速排序实现升序排序 函数4:请使用插入排序实现升序排序 #include<stdio.h> #include<string.h&g…...
如何在 Microsoft Azure 上部署和管理 Elastic Stack
作者:来自 Elastic Osman Ishaq Elastic 用户可以从 Azure 门户中查找、部署和管理 Elasticsearch。 此集成提供了简化的入门体验,所有这些都使用你已知的 Azure 门户和工具,因此你可以轻松部署 Elastic,而无需注册外部服务或配置…...
在Visual Studio中引用和链接OpenSceneGraph (OSG) 库
在Visual Studio中引用和链接OpenSceneGraph (OSG) 库,按照以下步骤操作: 构建或安装OSG库 下载OpenSceneGraph源代码(如3.0版本)并解压。使用CMake配置项目,为Visual Studio生成解决方案文件。通常您需要设置CMake中的…...
玩转AI!用FastAPI+RAG轻松构建智能文档问答系统,代码、文档全公开!
在企业数字化转型的浪潮中,我们常遇到这样一个痛点:海量的业务文档、研究报告、技术手册堆积如山,当需要从中寻找某个特定答案时,员工往往要花费数小时甚至数天进行翻阅。这不仅是效率的浪费,更是知识资产沉睡的体现**…...
从零搭建企业级开源大模型平台:Ollama+Llama3+open-webui实战指南
1. 为什么选择OllamaLlama3open-webui组合? 最近两年大语言模型的发展速度简直让人瞠目结舌,从最初的GPT-3到现在的Llama3,模型能力突飞猛进的同时,部署门槛也在不断降低。作为一个在AI领域摸爬滚打多年的老手,我实测过…...
利用快马平台快速构建mcporter数据转换工具原型,十分钟验证数据管道设计
最近在做一个数据迁移项目时,遇到了需要频繁转换数据格式的需求。传统方式下,光是搭建开发环境、编写基础代码就要花上大半天时间。这次尝试用InsCode(快马)平台快速构建了一个mcporter数据转换工具原型,整个过程出乎意料地顺畅。 明确核心需…...
如何使用Compiler Explorer实时编译原理:揭秘代码到汇编的转换过程
如何使用Compiler Explorer实时编译原理:揭秘代码到汇编的转换过程 【免费下载链接】compiler-explorer Run compilers interactively from your web browser and interact with the assembly 项目地址: https://gitcode.com/gh_mirrors/co/compiler-explorer …...
避坑指南:华为Atlas200DK开发板联网常见错误及解决方法
华为Atlas200DK开发板联网避坑实战手册 当开发者第一次拿到华为Atlas200DK开发板时,联网往往是遇到的第一个技术门槛。这个看似简单的操作,在实际操作中却可能因为各种配置细节问题而耗费数小时。本文将深入剖析开发板联网过程中的典型故障场景ÿ…...
3步解锁苹果电脑新玩法:用PlayCover畅玩iOS游戏和应用
3步解锁苹果电脑新玩法:用PlayCover畅玩iOS游戏和应用 【免费下载链接】PlayCover Community fork of PlayCover 项目地址: https://gitcode.com/gh_mirrors/pl/PlayCover 还在羡慕朋友在iPad上玩热门手游,而你的Mac只能干看着?想知道…...
探索Comsol在光子晶体光纤SPR - PCF传感器及光学仿真中的奇妙世界
Comsol光子晶体光纤spr pcf传感器comsol光 Comsol光子晶体光纤spr pcf传感器 comsol光学仿真spr。 利用几何相位缺陷态光子晶体实现谷自旋分离在光学领域,光子晶体光纤(PCF)以及表面等离子体共振(SPR)相关的研究一直热…...
告别特征工程:用Python+Matplotlib把EEG脑电信号直接变成CNN能吃的时频图
从原始EEG到CNN输入:Python自动化生成时频图全流程解析 深夜的实验室里,显示器上跳动的脑电波形正被转化为一张张彩色图像——这不是科幻场景,而是现代脑机接口研究的日常。传统EEG分析中繁琐的特征工程正在被一种更直观的方法取代࿱…...
实战演练:在快马平台模拟静电地板排布与支架系统配置方案
今天想和大家分享一个特别实用的工具——在InsCode(快马)平台上快速搭建的静电地板施工模拟器。作为机房建设中的重要环节,静电地板施工的合理规划直接影响后期使用效果。这个工具能帮我们在实际施工前,通过可视化模拟规避很多潜在问题。 核心功能设计思…...
AI 辅助开发实战:基于低代码与智能生成的五金店管理系统毕设架构设计
最近在帮学弟学妹们看毕业设计,发现“五金店管理系统”是个高频选题。但很多人做着做着就陷入了“增删改查”的泥潭,前端界面简陋,业务逻辑也写得七零八落,最后答辩时演示效果平平,技术深度更是无从谈起。这让我开始思…...
