【STM32】定时器

news2024/10/6 20:26:49

systick定时器:

【STM32】Systick定时器-CSDN博客

0.通用定时器框图

1.时钟源

2.控制器

3.输入捕获

计数器实际上是与比较寄存器的影子寄存器进行比较的。

4.输出比较

1.STM32的定时器学习要点

参考手册

STM32F1xx中文参考手册.pdf · 林何/STM32F103C8 - 码云 - 开源中国 (gitee.com)

1.通用定时器和其他的区别

1)其实最多可以有17个定时器

2)功能差别

2.STM32定时器的学习要点

1)先学会定时器基本概念的使用

2)高级功能用到到时再去细看

3)设计本身的复杂性导致学习难度大,要有耐心

4)很多书面概念要搞清楚,需要不断前后对照

5)学习三宝:数据手册+外设库源码+例程

2.通用定时器的数据手册

进行比较计数器和寄存器的值进行电平的反转。

1.TIMx主要功能

定时器是基于计数器进行的,分频,然后走一格就计数一次。

1.向上/向下

向上:加法计数器【从x不断++到65535】

向下:减法计数器【从x不断--到0】

2.TIM的所属APB

3.发生的中断/DMA

2.通用定时器框图

3.预分频器

1.时基单元

1)可以在运行的时候对预分频器的值进行修改

我们这里可以在运行时对其进行修改的是count计数器(可以在当前事件执行时进行更新,也可以等到下一次更新事件发生后在进行改变)

预分频器(预分频器的值只能在下一次更新事件到来时被采用。)

2)影子寄存器【预装载寄存器】:在硬件上实际上是存在的,但是没有给他分配地址(不需要程序进行干预)

1.1 TIMx_CR1_ARPE:修改位

1.2 TIMx_CR1_UDIS:中断允许位

1.3 TIMx_CR1_CEN:时钟和计数器的使能

注意点:

真正的计时器使能信号CNR_EN是在CEN的一个时钟周期后被设置(表示计数器是在一个周期后才开始计时)

2.预分频器描述

预分频器可以在工作时被改 变。但是新的预分频器参数只能在下一次更新事件到来时被采用。【因为预分频器中带有缓冲器】

2.1 计数器的时序图:1分频--2分频

2.2 计数器的时序图:1分频--4分频

4.计数器

1.向上计数器模式

1.与51单片机不同

2.基本概念

3.是否产生更新事件

4.计数器时序图

5.ARPE=0时的更新事件【立即模式-不缓存】

6.ARPE=1时的更新事件【下一周期改变--缓存】

2.向下计数模式

注意点:

向下计数模式没有【立即模式】,因为如果原来ff,然后现在走到05,然后修改为36,不可能重新回36在继续减,这是不合理的。

3.中央对齐模式(向上/向下计数)

在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器 溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。

1.注意点

1)在这个模式,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。

2)注意加减的边界值问题:

        加法计数器是寄存器值-1

        减法计数器是减到1

2.计数器时序图

3.ARPE=1时的更新事件【下一周期更新--缓存】

5.时钟选择

1.内部时钟(CK_INT)--常规模式

1.使能

通过设置TIMx_SMCR寄存器的SMS=000,表示使用内部时钟【常规模式】。

2.外部时钟模式1:外部输入脚(TIx)

3.外部时钟模式2:外部触发输入(ETR)

4.内部触发输入(ITRx):一个定时器的输出作为另外一个定时器的输入

6.库函数

1.TIM_TimeBaseInit

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
  uint16_t tmpcr1 = 0;

  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx)); 
  assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));
  assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));

  tmpcr1 = TIMx->CR1;  

  if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
     (TIMx == TIM4) || (TIMx == TIM5)) 
  {
    /* Select the Counter Mode */
    tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
    tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
  }
 
  if((TIMx != TIM6) && (TIMx != TIM7))
  {
    /* Set the clock division */
    tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
    tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
  }

  TIMx->CR1 = tmpcr1;

  /* Set the Autoreload value */
  //要计数的值
  TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
 
  /* Set the Prescaler value */
  //预分频参数
  TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
    
  if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))  
  {
    /* Set the Repetition Counter value */
    TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
  }

  /* Generate an update event to reload the Prescaler and the Repetition counter
     values immediately */
     //预分频器参数的改变
  TIMx->EGR = TIM_PSCReloadMode_Immediate;           
}

2.TIM_ITConfig

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
{  
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_IT(TIM_IT));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the Interrupt sources */
    TIMx->DIER |= TIM_IT;
  }
  else
  {
    /* Disable the Interrupt sources */
    TIMx->DIER &= (uint16_t)~TIM_IT;
  }
}

7.定时器例程分析和编程实践

1.RCC_Configuration

TIM2接APB1,GPIOB接APB2

2.GPIO_Configuration

配置的是GPIOB

3.NVIC_Configuartion

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  /* Enable the TIM1 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

 4.TIM2_IRQHandler

5.时钟编写

8.代码移植

1.先写定时器

如果不知道定时器的名字是什么可以去“startup_stm32f10x_hd.s”查看

再去“stm32f10x_it.c”中填写

2.RCC_Configuration

注意点:

TIM2和GPIOB所对应的APB对应不一样,所以一定要分开声明,要不然会出现错误。

TIM2---》APB2

GPIOB--》APB1

void RCC_Configuration(void)
{
	//打开时钟
	//注意点:
	//TIM2和GPIOB的APB不一样,所以只能分开声明,要不然不起效果
//	RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}

3.GPIO_Configuration

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

   /* GPIOA Configuration: */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure); 
  
  GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET); 
}

4.NVIC_Configuration

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  /* Enable the TIM1 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

5.APB的分频问题

TIM2接APB1,GPIOB接APB2

我们APB1不能超过36MHZ,所以要对72MHZ进行分频

		//72MHZ定时器的定义
		// 主频是72MHz,HCLK是72M,PCLK2是72M,PCLK1是36M
		// TIM2接在PCLK1下(APB1)所以源是36M,CK_CNT是36M/7200=5KHz
		TIM_TimeBaseStructure.TIM_Prescaler = 7199;
	//例如:时钟频率=72/(时钟预分频+1)
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
		// 计数个数是10000,所以计数时间是10000*1/5000=2s
		TIM_TimeBaseStructure.TIM_Period = 9999;//自动重装载寄存器周期的值(定时时间)累计
		//0xffff 个频后产生个更新或者中断(也就是说定时时间到)

6.完整代码

main

#include "stm32f10x.h"                  // Device header
/**

	根据定时器2来实现数码管每隔1秒闪烁一次
*/


void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

int main(){
	  //设置TIM2定时器
	  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	
	  RCC_Configuration();  //系统时钟配置
  	NVIC_Configuration();	 //NVIC配置
  	GPIO_Configuration();	 //通用IO端口配置
	
		//72MHZ定时器的定义
		// 主频是72MHz,HCLK是72M,PCLK2是72M,PCLK1是36M
		// TIM2接在PCLK1下(APB1)所以源是36M,CK_CNT是36M/7200=5KHz
		TIM_TimeBaseStructure.TIM_Prescaler = 7199;
	//例如:时钟频率=72/(时钟预分频+1)
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
		// 计数个数是10000,所以计数时间是10000*1/5000=2s
        //注意点:我们计算出来的值是5,但是我们实际上是从0开始,所以我们这里要-1
		TIM_TimeBaseStructure.TIM_Period = 4;//自动重装载寄存器周期的值(定时时间)累计
		//0xffff 个频后产生个更新或者中断(也就是说定时时间到)
		TIM_TimeBaseStructure.TIM_ClockDivision = 0;
		//初始化定时器2
		TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
		
		//打开中断,溢出中断
		TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 
	  //定时器打开
		TIM_Cmd(TIM2, ENABLE); 
		while (1);
		//进入中断

	return 0;
}


void RCC_Configuration(void)
{
	//打开时钟
	//注意点:
	//TIM2和GPIOB的APB不一样,所以只能分开声明,要不然不起效果
//	RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}


void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

   /* GPIOA Configuration: */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure); 
  
	//使亮数码管
  GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET); 
}

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  /* Enable the TIM1 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

stm32f10x_it.c

void TIM2_IRQHandler(void){
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)  //检测制定的中断是否发生
  {
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  //清除中断处理位。
		//LED的取反
	 	GPIO_WriteBit(GPIOB, GPIO_Pin_8, !GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8));
  }  
}

9.问题解决:APB频率计算问题

cnt的计数公式 

cnt=1s*频率值(HZ)

例如:

此时TIM2一定是分完频,结果为36MHZ

初始化:TIM_TimeBaseStructure.TIM_Prescaler = 7199;--》【最后要+1】

CK_CNT=36M/72 00=5KHZ

实际测试得到的是1KHZ的结果,说明前面分析有误

初始化:计数个数为1 0000个

所以:计数时间为:1 0000*1/5000=2s

结论:APB1时钟确实是36MHZ,但是APB1到定时器时钟那边中间被乘以2,所以又变成72MHZ了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LIUNX】机器互访:免密登陆

服务器端 /etc/ssh/sshd_config 口常见SSH服务器监听的选项如下: Port 22//监听的端口为22 Protocol 2//使用SSH V2协议 ListenAdderss 0.0.0.0 //监听的地址为所有地址 UseDNS no//禁止DNS反向解析 客户端 /etc/ssh/ssh_config 口常见用户登录控制选项如下&#…

Red Giant Trapcode Suite 2024.0.1

Red Giant Trapcode Suite是一款ae视觉效果插件软件,适用于After Effects和Premiere Pro等流行的视频编辑软件。该软件集合了一系列强大而创新的工具,可以帮助用户创建令人惊叹的视觉效果和动态图形。 Red Giant Trapcode Suite包含多种插件&#xff0c…

3-知识补充-MVC框架

3-知识补充-MVC框架 文章目录 3-知识补充-MVC框架MVC概述M、V、C各自负责功能及常用包MVC框架图非前后端分离框架图前后端分离框架图 MVC概述 MVC(Model、View、Controller)是软件工程中的一种**软件架构模式,它把软件系统分为模型、视图和控…

SpringCloudAlibaba——Nacos

Nacos是服务注册中心服务配置中心。替换了以前的EurekaConfigBus。 1.Nacos作为服务注册中心 Nacos支持AP和CP模式的转换。 2.Nacos作为服务配置中心 服务要配置两个yml文件,bootstrap.yml和application.yml。因为Nacos同springcloud-config一样,在项…

NeRF神经辐射场渲染过程详解,三维重建渲染过程基本原理_光线采样sample_pdf()和光线渲染render_rays ()代码详解

目录 1 神经辐射场 1.1 基本原理 1.2 基本流程 1.3 数学解释 2 三维场景图像渲染详解 2.1射线采样 2.2 NeRF 模型预测 2.3 体积渲染 3 采样与渲染代码详解 (rending.py) 3.1 神经体积渲染代码解析 3.2 sample_pdf 函数 3.3 render_rays 函数 …

号牌模拟数据生成

说明 自己开发的测试数据生成工具,用于生成数据训练对应模型。 项目 效果

微带线的ABCD矩阵的推导、转换与级联-Matlab计算实例

微带线的ABCD矩阵的推导、转换与级联-Matlab计算实例 散射参数矩阵有实际的物理意义,但是其无法级联计算,但是ABCD参数和传输散射矩阵可以级联计算,在此先简单介绍ABCD参数矩阵的基本用法。 1、微带线的ABCD矩阵的推导 其他的一些常用的二端…

【教程】多进程下载百度旋转验证码图片-制作数据集

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 效果展示: 直接上代码,开箱即用(当然selenium库自己装一下): import os import time import requests from selenium import webdriver from selenium.…

为什么HTTP用得很好的,开始普及HTTPS呢?

显而易见,现在的HTTP早已不安全,当我们在浏览各个网站时会发现HTTP前面都会显示不安全,因为HTTP是明文传输,一旦电脑被植入了木马,木马程序就会主动周期性发消息给Internet的控制终端,这样NAT小洞会一直敞开…

Markdown写作应用推荐

MWeb Pro 是一款适用于macOS的专业Markdown写作、笔记本应用软件。喜欢写博客的朋友,那你一定会需要 MWeb Pro 这款软件。为您提供最佳的写作体验。 Markdown 语法支持: 使用 Github Flavored Markdown 语法,简称 GFM 语法。支持表格、TOC、…

2023年云计算发展趋势:生活的智能未来

目录 引言1 智能家居的崭新时代2 无人驾驶的崭新时代3 虚拟现实的扩展与改进4 人工智能的综合应用5 云计算的可持续性结语 引言 时光荏苒,科技的飞速发展已经成为当今社会的标志之一。在这个数字化时代,云计算已经成为推动技术革新和生活方式改变的关键…

【深度学习】Python爬取豆瓣实现影评分析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、任务描述二、使用步骤1.数据爬取1.2.对爬取的页面数据进行解析,并保存为JSON文件2、数据分析2.1数据分析之评论时间分布图2.2角色评分 前言 爬…

雷神学习---视音频数据处理入门:RGB、YUV像素数据处理

原文地址:https://blog.csdn.net/leixiaohua1020/article/details/50534150 ​​​​​​​​从代码可以看出,如果想把YUV格式像素数据变成灰度图像,只需要将U、V分量设置成128即可。 这是因为U、V是图像中的经过偏置处理的色度分量。色度分…

Python继承和多态:基础继承、方法重写、多态的基本概念

文章目录 基础继承方法重写多态在编程语言中,特别是在面向对象编程(OOP)中,继承和多态是两个核心概念,它们提供了代码重用和接口设计的强大工具。Python 作为一种支持 OOP 的语言,也具备这些特性。 基础继承 继承是面向对象编程的一个基本概念,它允许我们定义一个类(…

Angew. Chem. Int. Ed.:Co-1T-MoS2-bpe碱性介质中电催化HER

高效析氢反应(HER)电催化剂决定氢动力清洁技术的质量分布,但仍面临着巨大的挑战。基于此,中国石油大学(华东)董斌副教授等人报道了通过CoMo -金属-有机骨架前驱体对1T-MoS2催化剂进行了配体调制和Co掺杂的协…

前端图片压缩上传,减少等待时间!优化用户体检

添加图片注释,不超过 140 字(可选) 这里有两张图片,它们表面看上去是一模一样的,但实际上各自所占用的内存大小相差了180倍。 添加图片注释,不超过 140 字(可选) 添加图片注释&…

JumpServer 打开RDP客户端出现由于在客户端检测到一个协议错误 错误代码 0x2104

环境: Win10 专业版 JumpServer Version v2.25.4 问题描述: JumpServer 打开RDP客户端出现由于在客户端检测到一个协议错误 错误代码 0x2104 个别电脑又是正常可以连接 解决方案: 检查网络连接:确保您的计算机和JumpServer之间的网络连接正常。尝试使用其他网络连接…

操作系统基础知识1

1、用户态和内核态的区别? a、访问权限。用户态下,应用程序只能访问受限的的资源和执行受限的程序;而在内核态下,操作系统具有完全的访问权限,可以访问系统的所有资源和执行所有操作; b、CPU指令集。用户态…

拍摄中的信息表达者---镜头语言!

炫我科技在影视动画行业为众多影片提供了渲染支持。涉及到的业务有云渲染系统、实时渲染系统、XR虚拟拍摄系统,强势赋能元宇宙。在影视动画创作过程中提供了多种解决方案,例如集群渲染、私有云渲染解决方案、虚拟拍摄等。 今天我们来聊一些不一样的东西…

学习pytorch15 优化器

优化器 官网如何构造一个优化器优化器的step方法coderunning log出现下面问题如何做反向优化? 官网 https://pytorch.org/docs/stable/optim.html 提问:优化器是什么 要优化什么 优化能干什么 优化是为了解决什么问题 优化模型参数 如何构造一个优化器…