20:【stm32】定时器一:时基单元

时基单元

  • 1、什么是定时器
  • 2、时基单元的基本结构
    • 2.1:脉冲的来源
    • 2.2:预分频器PSC
    • 2.3:计数器CNT
    • 2.4:update事件与预加载
  • 3、标准库编程
    • 3.1:通过定时器中断来设置延迟函数

1、什么是定时器

定时器是一种专门负责定时功能的片上外设,而F1系列的单片机最多由14个定时器(TIM1~TIM14)。而STM32F103C8T6一共只有4个定时器。

在这里插入图片描述
如上图所示:STM32F103C8T6有一个高级定时器TIM1,3个通用定时器TIM2~4。而高级定时器TIM1挂载在APB2上面。

2、时基单元的基本结构

在这里插入图片描述
如图为定时器的基本结构,而时基单元是定时器结构的一部分,如下图所示。

在这里插入图片描述
如图:时基单元的基本结构由预分频器PSC,计数器CNT,自动重装寄存器ARR,重复计数器RCR组成。而RCR只有高级定时器才有,通用定时器没有。

 PSC (Prescaler): 对速时钟信号 分频
 CNT (Counter) :在时钟脉冲激励下 计数
 ARR (Auto Reload Register ):用于设置定时周期
 RCR (Repetition Counter Register):用于设置定时的 的次 
 Update事件 - 当RCR溢 时产生
 Update中断 - 由Update事件引发的中断

2.1:脉冲的来源

在这里插入图片描述
由晶振而来,具体情况可参考时钟树的相关知识。

在这里插入图片描述

由上图所示:如果是APB1产生的频率,那么频率 * 2,如果是APB2产生的频率,那么频率 * 1 STM32F103C8T6的定时器来源的频率max = 72MHz

2.2:预分频器PSC

在这里插入图片描述

预分频器由PSC由计数器,比较器和自动重装器构成。

在这里插入图片描述
想要分频率的频率脉冲连接计数器,作为输入信号。当计数器从1开始计数,数值和计数周期通过比较器相较,如果计数值 > 计数周期时,比较器输出一个脉冲,计数值归0,重新开始计数。

如上图所示:计数周期为7,输入脉冲输入了8个脉冲,比较器才输出1个脉冲,实现8分频
如上图:预分频器为16bit,就是计数器为16bit,则它能分频的最大倍数为:2^16 = 65536 。

2.3:计数器CNT

在这里插入图片描述
例如:如果是2bit的计数器,N也为2bit,那么最大分频倍数为2^2 = 4。
没有脉冲来时:计数器为00
第1个脉冲来:计数器为01
第2个脉冲来:计数器为10
第3个脉冲来:计数器为11
第4个脉冲来:计数器变为00,然后向外输出一个脉冲。
在这里插入图片描述

在这里插入图片描述

2.4:update事件与预加载

在这里插入图片描述N值决定了 的周期,有时我们需要在 运行的过程中 态地调整N的值为了防止出错这个调整需要加一些保护措施(预加载 Preload)。
新的N值首先被写 shadow中,等到下一次Update事件时传 active ,至此才能真正发挥作用。
在这里插入图片描述
如图:在计数的中途改变N的值时,N的值保存在影子寄存器中,然后等待这一次的计数完成后,影子寄存器在将N的值写入shadow里面。

3、标准库编程

在这里插入图片描述

3.1:通过定时器中断来设置延迟函数

#include "stm32f10x.h"                  // Device header


void Time_Init(void);
void LED_Init(void);
void Delay_us(uint64_t us);
void Delay_ms(uint32_t ms);
static uint32_t count = 0;

int main(void)
{
	Time_Init();
	LED_Init();
	while(1)
	{
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
		Delay_ms(1000);
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
		Delay_us(1000000);
	}
}


void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
}

/*
	定时器的初始化
*/
void Time_Init(void)
{
	//1. 使能挂载定时器TIM3的总线时钟
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3,ENABLE);//复位
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3,DISABLE);//复位
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能时钟
	
	//2. 使能ARR寄存器的预加载特性
	TIM_ARRPreloadConfig(TIM3,ENABLE);//打开预加载特性
	
	//3. 初始化时基单元,这些都是配置影子寄存器中
	TIM_TimeBaseInitTypeDef TIMInitStruct;
	TIMInitStruct.TIM_Prescaler = 71;//配置预分频器PSC
	TIMInitStruct.TIM_Period = 999;//配置自动重装寄存器ARR
	TIMInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//配置计数器为向上计数模式
	TIM_TimeBaseInit(TIM3,&TIMInitStruct);
	
	//4. 收到启动Update事件,必须手动启动,因为配置好了的定时器参数在影子寄存器中
	TIM_GenerateEvent(TIM3,TIM_EventSource_Update);
	
	//5. 使能Updata中断
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//打开Updata触发的中断源
	
	//6. 配置NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVICInitStruct;
	NVICInitStruct.NVIC_IRQChannel = TIM3_IRQn;
	NVICInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVICInitStruct.NVIC_IRQChannelSubPriority = 0;
	NVICInitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVICInitStruct);
	
	//7. 使能定时器TIM3
	TIM_Cmd(TIM3,ENABLE);
	
}

/*
	定时器的中断函数,由上面的定时器初始化得,PSC = 71,则分频72倍,72MHz/72 = 1MHz
	1MHz代表1s/1000000 = 0.000001s = 1us,所以没间隔1us计数一次。
	自动重装器为999,则代表每隔1000 * 1us = 1ms触发一个Update事件,然后产生一个中断。

*/
void TIM3_IRQHandler(void)
{
	//判断中断标准位,是谁产生的中断源
	if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update) == SET)//如果是Update产生的中断源
	{
		TIM_ClearFlag(TIM3,TIM_FLAG_Update);//清除中断标准位
		count++;//代表每隔1ms,count加1。
	}
}

/*
	定义一个ms的延迟函数
*/
void Delay_ms(uint32_t ms)
{
	uint64_t time = count + ms;
	while(count < time);
}

/*
	定义一个us的延迟函数
*/
void Delay_us(uint64_t us)
{
	uint64_t time = count * 1000 + TIM_GetCounter(TIM3) + us;//TIM_GetCounter(TIM3)获取计数器计数的值
	while(count * 1000 + TIM_GetCounter(TIM3) < time);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/871324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

45.【C语言】指针(重难点)(H)

目录&#xff1a; 22.函数指针变量 *创建 *使用 *两段代码分析 23.函数指针数组 *基本用法 *作用 往期推荐 22.函数指针变量 *创建 类比数组指针变量的定义&#xff1a;存放数组地址的指针变量&#xff0c;同理函数指针变量存放函数的地址 格式 函数的返回类型 (*指针变量的…

产品帮助中心如何搭建?五步让客户满意度提升100%

一、引言 创建帮助文章的好处是节省了招募大量客户联系代理的昂贵成本。它们现在通过解决客户的早期问题而无需支持干预&#xff0c;并为自助提供逐步指导&#xff0c;从而取代了支持代理。 当您创建帮助文章时&#xff0c;您会构建知识库并为将来保留它。这些帮助文章充当新…

作业帮 TiDB 7.5.x 使用经验

作者&#xff1a; 是我的海 原文来源&#xff1a; https://tidb.net/blog/5f9784d3 近期在使用 TiDB 时遇到的一些小问题的梳理总结&#xff0c;大部分版本都在6.5.6和7.5.2 1、limit 导致的扫描量过大的优化 研发定时任务每天需要扫描大量数据&#xff0c;到时机器网卡被…

开放式耳机好还是入耳式耳机好?2024五款热销开放式耳机推荐!

开放式耳机与入耳式耳机各有优缺点&#xff0c;适合不同的使用场景和用户需求。 开放式耳机的优点主要包括&#xff1a; 1. 佩戴舒适性好&#xff0c;由于设计宽松&#xff0c;不会给耳朵带来压迫感&#xff0c;适合长时间使用 。 2. 透气性能好&#xff0c;尤其在夏天或运动…

《江南:在爱开始的地方等你》将上映 赖雨濛刘冬沁演绎刻骨之恋

在等到你之前&#xff0c;我们的故事一直未完待续。 用这句话来诠释电影《江南&#xff1a;在爱开始的地方等你》最为精准不过&#xff0c;该片改编自康锐原创小说《月落姑苏》&#xff0c;由康锐导演、编剧&#xff0c;赖雨濛、刘冬沁领衔主演、朱丹妮、王沛为、金巧巧、阎青…

Linux/Windows下线程间通信机制及其API总结

线程间通信&#xff08;Thread Inter-Communication, TIC&#xff09;是指在一个进程内的多个线程之间进行数据交换和同步的方法。与进程间通信相比&#xff0c;线程间通信通常更简单、更高效&#xff0c;因为它们共享相同的内存空间。下面是一些常见的线程间通信机制及其相关A…

vue-element-admin解决三级目录的KeepAlive缓存问题(详情版)

vue-element-admin解决三级目录的KeepAlive缓存问题&#xff08;详情版&#xff09; 本文章将从问题出现的角度看看KeepAlive的缓存问题&#xff0c;然后提出两种解决方法。本文章比较详细&#xff0c;如果只是看怎么解决&#xff0c;代码怎么改&#xff0c;请前往配置版。 一…

【原创教程】电气电工07:网线的制作方法

电气电工经常会遇到做网线,我们做网线需要网线钳与测试仪。需要了解网线的两种接线标准。 我们来看一下网线钳的操作步骤: 这种压线钳也同时具有剥线、剪线功能。 用这种网线钳能制作RJ45网络线接头。RJ11电话线接头、4P电话线接头。适用于RJ45,RJ11型网线 做网线的时候我…

Temu全托管和半托管的区别:一文说清temu全托和半托的差异

TEMU在今年3月再出王炸&#xff0c;上线半托管模式。这是TEMU继全托管模式爆火跨境圈之后的又一个大动作。那么&#xff0c;TEMU全托管和TEMU半托管有哪些不同&#xff1f;卖家朋友应该如何选择呢&#xff1f;今天给大家详细拆解一下。 TEMU全托管和半托管有什么区别 首先是定…

汇编语言lea指令取数组偏移地址

最近看到一条指令&#xff0c;x86汇编&#xff0c; LEA BX, 6[DI] 根据资料&#xff0c;它的含义是&#xff0c;某数组含20个元素&#xff0c;每个元素占一个字节&#xff0c;序号为0~19。设DI指向数组开头处&#xff0c;把序号为6的元素的偏移地址送到BX中&#xff1b; lea指令…

如何进行长截图的两种方法

前言 本文主要讲2种截图方式&#xff0c;分别是谷歌和QQ。 谷歌分为Web端 和 移动端&#xff0c;选一种即可。 第一种&#xff1a;谷歌浏览器控制台自带的 1.先把控制台语言更改为中文&#xff0c;方便查看 ①.按F12&#xff0c;点击设置面板 ②.修改语言为中文并关闭 ③.点击…

BFS解决单源最短路问题

目录 迷宫中离入口最近的出口 最小基因变化 单词接龙 为高尔夫比赛砍树 迷宫中离入口最近的出口 题目 思路 使用宽度优先遍历解决这道题&#xff0c;需要一个二维数组标记是否被遍历过&#xff0c;也需要一个队列辅助完成宽度优先遍历&#xff0c;类似于水波纹一样&#x…

java接口 controller层接收list集合传参,postman 调用接口时required parameter XXX is not present

开发过程中开发一个java接口 controller层接收list集合传参&#xff0c;然后postman调用一直不成功&#xff0c;报错 使用RequestParam方式&#xff0c;如果postman 调用接口时报错required parameter XXX is not present 可能是&#xff08;value“items”&#xff09;跟你输…

线索获取:多渠道获客策略解析

在当今商业环境中&#xff0c;企业面临着激烈的市场竞争和不断变化的客户需求。在此背景下&#xff0c;销售线索作为销售活动的基础和起点&#xff0c;重要性更加凸显&#xff0c;尤其是在营销精耕的当下&#xff0c;做好线索的精细化管理成为企业获取竞争优势的关键环节之一。…

数据结构----队列

1 什么是队列&#xff1f; 只允许在两端进行插入和删除操作的线性表&#xff0c;在队尾插入&#xff0c;在队头删除 插入的一端&#xff0c;被称为"队尾"&#xff0c;删除的一端被称为"队头" 在队列操作过程中&#xff0c;为了提高效率&#xff0…

《重生到现代之从零开始的C语言生活》—— 指针3

数组名的理解 在我们使用&arr[0]的方式拿到了数组第一个元素的地址&#xff0c;但是其实&#xff0c;数组名本来就地址&#xff0c;而且是数组首元素的地址 所以数组名就是数组首元素的地址 但是会有两个例外 sizeof(数组名)&#xff0c;sizeof中单独放数组名&#xff0c…

[Linux] 查看系统资源 (持续更新中)

概述 在Linux中&#xff0c;有许多命令和工具可用于查看系统的资源使用情况。以下是一些常用的方式&#xff1a; top&#xff1a;top命令是最常见的实时系统监视工具之一。它显示了当前运行的进程列表&#xff0c;以及每个进程的CPU、内存使用情况、nice值等信息。top命令还会…

帆软报表,达梦数据库驱动上传失败

1、按照正常操作新建数据库连接&#xff0c;上传准备好的达梦驱动时&#xff0c;提示如图一需要修改SystemConfig.driverUpload为true才可以。 2、FineDB存储了数据决策系统中除平台属性配置以外的所有信息。详情请参见&#xff1a; FineDB 数据库简介。 3、因此管理员可通过…

Kubectl基础命令使用

一.Kubectl 基础命令 格式&#xff1a; kubectl [command] [TYPE] [NAME] [FLAGS] kubectl 是 Kubernetes 的命令行工具&#xff0c;用于管理 Kubernetes 集群。以下是一些常用的 kubectl 命令及其选项&#xff1a; 常用命令 获取资源 列出所有资源类型&#xff08;Pods、De…

机器学习|什么是梯度下降(小白向)|探寻最优解之路

文章目录 前言一、什么是梯度下降&#xff1f;二、梯度下降法一般步骤1.确定一个小目标——预测函数2.找到差距——代价函数3.明确搜索方向——梯度计算4.一步要走多远&#xff1f;——学习率 三、梯度下降的分类批量梯度下降&#xff08;Batch Gradient Descent&#xff09;随…