STM32 学习笔记_6 定时器中断(上)

news2024/11/26 19:59:16

TIM

定时器是功能最强大,内容最复杂的32结构。

  1. 之前51用过的功能,定时产生中断。
  2. 输出比较,常用于产生 PWM 波形,驱动电机等。
  3. 输入捕获,测量方波频率。
  4. 编码器,读取正交编码器的波形。

最大定时时间:72M/65536/65536=中断频率,中断频率取倒数是最大定时时间。

定时器可以级联,比如 72MHz的最大定时 59.65s,级联一次 * 65536 * 65536.

类型编号总线功能
高级定时器TIM1、TIM8APB2拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能
通用定时器TIM2、TIM3、TIM4、TIM5APB1拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能
基本定时器TIM6、TIM7APB1拥有定时中断、主模式触发DAC的功能

从下到上越来越复杂且强大。f103c8t6 有 TM1-4(不同芯片不一样,要查阅手册!),我们主要学习通用定时器。

image-20230425201024320

PSC 对 RCC 分频,比如写入1代表2分频的话,就是输出72MHz/2=36MHz. 实际分频系数=预分频器值+1.

计数器按照时钟频率不断自增,=自动重装载寄存器值时清零并产生中断。UI 是中断,U 是事件。

主动触发 DAC:DAC 中断会很频繁,占用很多 CPU 资源。如果定时器可以自己操纵从设备处理 DAC 就节省许多 CPU 资源。上图中的 TRGO 就是。

image-20230425203158414

在基本计数器基础上,通用寄存器还支持向下计数和中央对齐计数(0-重装值-0-重装值……)

时钟可选内部72MHz时钟或外部时钟。

可以实现定时器级联,参照手册查看哪几个定时器和哪几个级联。自己输出的引脚 CH 也可以作为自己的时钟输入,作用后续展开。

四个输出是输出比较电路,左边是输入捕获电路。

image-20230425204348250

图中有阴影的就是有缓冲寄存器的,缓冲寄存器下面马上讲。

重复次数计数器允许几个周期才触发一次中断。

输出 CH1-3 可以输出互补的波,有用处。为了防止切换时产生直通现象(两个反相电路同时切换,类似x形),通过 DTG 死区生成电路, 切换前产生死区,让上下管全归零再切换。

左下角刹车输入,异常状态时可以终止定时器。

基本结构如下:

image-20230425205237061

运行控制就比如设置向上向下计数。

中断输出控制相当于一个标志位,决定这个中断需不需要。

image-20230425205647303

CK_PSC:预分频器的输入时钟。

CNT_EN:计数器使能,高电平开启。后面预分频器变为1,分频/2了,因此两次上升沿才触发一次。计数器寄存器随之不断自增。

达到自动重装器值后更新事件,计数器归零。

预分频寄存器修改后并不是立刻改变的,而是等触发中断后下一个开始计数周期后才修改预分频缓冲器,预分频缓冲器才能真正控制。

预分频计数器可见分频的原理,比如设置预分频缓冲器=1,也就是实际分频系数为2,那么计数0,1后达到实际分频系数-1,清零并计数器++。

C K _ C N T = C K _ P S C / ( P S C + 1 ) CK\_CNT=CK\_PSC / (PSC+1) CK_CNT=CK_PSC/(PSC+1)

对于计数器来说是这样的:

image-20230425211659817

实际分频系数为2,2次时钟周期才+1,溢出时更新事件和中断标志寄存器提示现在中断了。中断标志寄存器要在中断程序中手动清零。

计数器溢出频率:

C K _ C N T _ O V = C K _ C N T / ( A R R + 1 ) = C K _ P S C / ( P S C + 1 ) / ( A R R + 1 ) CK\_CNT\_OV = CK\_CNT / (ARR + 1) = CK\_PSC / (PSC + 1) / (ARR + 1) CK_CNT_OV=CK_CNT/(ARR+1)=CK_PSC/(PSC+1)/(ARR+1)

arr 是自动重装寄存器值。溢出时间取倒数即可。

arr 也有缓冲寄存器,可以自己选取用不用。

image-20230425212615653

如图,虽然 arr 改成了36,但是也得等这轮中断结束了再更新影子寄存器。

这个最好还是打开,因为如果快加到了arr的值,然后arr缩小了,计数器可能就要一直加加到溢出归零再来一圈才能触发中断之类的小问题。

接下来看看时钟,时钟是所有外设需要的东西。systemInit() 函数里就在配置。

image-20230425212944952

HSI HSE 是内外时钟源,外部更稳定一些。两者都提供系统时钟,一些外设(AHB APB12)就是依靠他俩。

LSE OSC 是 RTC。

LSI RC 是独立看门狗的时钟。

SystemInit() 先启动内部时钟,系统暂时以8MHz运行,再启动外部时钟进入 PLL 锁相环进行倍频,达到稳定 72MHz 后输出。

因此外部时钟电路出问题了,无法正常切换时可能感觉程序跑的慢,是在用8MHz系统内时钟跑。或者CSS时钟安全系统强行把外部电路停了也可能。CSS也参与到了高级控制定时器中的刹车输入电路。

本板APB1预分频系数2,APB2是1.

AHB 预分频器的分频系数直接对PCLK1做除法。定时器2-7则是:“如果预分频系数=1,则频率=36MHz不变;否则频率*2”,所以其内部基准时钟永远是72MHz。APB2上的定时器1,8也是。

所有时钟都连了一个与门,外加一个使能电路。

代码:定时器

流程:

  1. RCC。
  2. 设置时钟源。
  3. 设置时钟源的时基单元(初始化预分频器,自动重装器,计数器模式)。
  4. 设置中断控制(开启)。
  5. 配置 nvic,这个用前面学过的 NIVC_Init。
  6. 设置运行控制。
  7. 启动计数器。

需要的函数列表:

image-20230426005302884

TimeBaseInit:初始化预分频器,自动重装器,计数器模式。

TimeBaseStructInit:给时基单元赋初值。

Cmd:启动时钟。

ITConfig:开启对应时钟中断。

下面六个是时钟源选择,内部时钟,ITRx其他定时器时钟,TIx捕获通道的时钟,ETR模式1,2的时钟,单独配置ETR时基单元、极性、滤波器等设置的函数。

这五个函数是 Init 后单独修改时基单元的配置的函数(改预分频器,改计数模式,设置是否预装,改计数器值,改自动重装值,。

image-20230426010613144

image-20230426010918513

最后是四个获取清除寄存器的函数。

image-20230426010930216

代码就和exti有一些小的差别。

#include "stm32f10x.h"                  // Device header

extern uint16_t cnt;

void Timer_Init(void){
    //rcc, set timer source, set psc + set arr + set cnt mode(time base unit), set it controller, set nvic it handler, set running control, enable counter
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    TIM_InternalClockConfig(TIM2);//默认也是这个时钟,不写也行
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//滤波器采样,频率越低,采样点数越多,滤波效果越好。不过延迟也越大。采样频率就是内部时钟和这个分频参数共同作用的结果
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    //比如我们想定1s中断一次,CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1),也就是72M / (PSC + 1) / (ARR + 1) = 1
    //所以两者赋值可以是10000-1和7200-1,只要两者都在65535以内就行,赋值不唯一
    TIM_TimeBaseInitStructure.TIM_Period=10000-1;//arr自动重装器值,72M 计数10000次,耗时 10000/72M s
    TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//预分频器值,分7200频,即 10000/(72M/7200) s=1s中断一次。
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器值,高级计数器才用
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
    
    TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);//设为更新中断
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_Cmd(TIM2,ENABLE);
    
    
}

void TIM2_IRQHandler(void){
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){//这里设置为update
        cnt++;
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    }
}

这里把cnt变量写在main.c里了,通过extern变量声明“这个变量是在其他文件中的,编译器你去找吧”。其实.h里函数声明也应该加extern,不过可以省略。

启动开发板后,可以看到立刻出发了一次中断,这是为啥呢?TIM_BaseInit最后一句是这样的:

TIMx->EGR = TIM_PSCReloadMode_Immediate;   

我们知道自动重装寄存器写入值不是立刻写入的,是等到更新事件的时候才写入缓冲区。那一开始我们初始化自动重装寄存器后,写不进去呀,触发不了中断呀。

因此我们要在 TIM_BaseInit 里手动触发一次更新事件,就是上面这个语句。代价就是上电立刻触发一次中断。更新事件和更新中断是同时发生的。

想去掉这一次中断,可以在 TIM_BaseInit 后面立刻跟一个 “TIM_ClearFlag”。

接下来我们写一个用例,因为TIM2和PA0是一个引脚,所以我们设定TIM2通过外部时钟模式配置,这样我们把红外遮光器接到PA0后,手动挡一次光就相当于模拟了时钟一次周期。

需要做的修改:

  1. 时钟初始化加上GPIOInit,把内部时钟配置改成外部时钟(模式2)。
void Timer_Init(void){
    //rcc, set timer source, set psc + set arr + set cnt mode(time base unit), set it controller, set nvic it handler, set running control, enable counter
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);//这里是滤波,太小的话一次红外检测加好多
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period=10-1;
    TIM_TimeBaseInitStructure.TIM_Prescaler=1-1;//十次红外检测,定时器++
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
    
    TIM_ClearFlag(TIM2, TIM_IT_Update);
    
    TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_Cmd(TIM2,ENABLE);
}

这样效果就是通过红外传感器来制造clock波形让定时器读取。

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

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

相关文章

关于repeater录制的流量子调用的identity中带有~S的情况

前段时间同事问我,我们录制的流量中,尤其是dubbo的子调用显示经常他的末尾会带上一个小尾巴这个是什么意思呢,其实之前我没有太在意这个事情,只是同事这么疑问了,确实激起了好奇心,所以就差了下 到底是什么…

HTML(四) -- 多媒体设计

目录 1. 视频标签 2. 音频标签 3. 资源标签(定义媒介资源 ) 1. 视频标签 属性值描述autoplayautoplay如果出现该属性,则视频在就绪后马上播放。controlscontrols表示添加标准的视频控制界面,包括播放、暂停、快进、音量等…

交叉熵损失函数与参数更新计算实例(节点分类为例)

交叉熵损失与参数更新 数据准备 对于下面这样一个图网络网络: 假如我们得到了节点i的嵌入表示 z i z_i zi​数据如下: i d , x 0 , x 1 , x 2 , x 3 1 , 0.5 , 0.6 , 0.7 , 0.8 2 , 0.3 , 0.8 , 0.3 , 0.4 3 , 0.7 , 0.9 , 0.6 , 0.9 4 , 0.2 , 0.1…

【计算几何】判断一条线段和一段圆弧是否相交 C++代码实现

文章目录 一、前言二、线段与圆弧的代码表示2.1 线段代码表示2.2 圆弧代码表示 三、实现思路及数学推导3.1 第一步(粗略判断)3.2 第二步3.3 第三步 四、完整代码五、效果展示 一、前言 最近做项目,需要判断一条线段是否和一段圆弧相交&#…

利用Ad Hoc传感器网络上的局部信息组织全球坐标系(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 知道通信网络中节点的地理位置通常是有用的,但在每个节点上添加GPS接收器或其他复杂的传感器可能会很昂贵。 本文…

系统集成项目管理工程师 笔记(第14章 项目采购管理)

文章目录 采购管理包括如下几个过程14.2 编制采购计划 4621)采购管理计划2)采购工作说明书3)采购文件14.2.3 工作说明书(SOW) 14.3 实施采购 47414.3.2 实施采购的方法和技术 476(1)投标人会议&…

深入篇【C++】类与对象:构造函数+析构函数

深入篇【C】类与对象:构造函数析构函数 ①.构造函数Ⅰ.概念Ⅱ.特性1.函数名和类型相同。2.无返回值,也不用写void。3.自动调用对应的构造函数。4.构造函数可重载5.编译器的无参构造6.编译器的无参构造特性7.声明时可缺省8.构造函数的调用9.默认构造函数 …

进程控制下篇

进程控制下篇 1.进程创建 1.1认识fork / vfork 在linux中fork函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程 #include<unistd.h> int main() {pid_t i fork;return 0; }当前进程调用fork&#xff0c;…

【VScode】的 安装--配置--使用(中文插件下载不了怎么办?)

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 : VScode &#x1f606;今日分享 : ”兰因絮果“是世间定律吗&#xff1f; 一段美好爱情开始时你侬我侬、缠缠绵绵&#xff0c;最后却以相看两厌结尾&#xff0c;让人唏嘘。清代词人纳兰容若于是咏出「人生若只如初见&#xff…

后端程序员的前端必备【Vue】 -01 Vue入门

Vue概述与基础入门 1 Vue简介1.1 简介1.2 MVVM 模式的实现者——双向数据绑定模式1.3 其它 MVVM 实现者1.4 为什么要使用 Vue.js1.5 Vue.js 的两大核心要素1.5.1 数据驱动![请添加图片描述](https://img-blog.csdnimg.cn/963aca7d7a4447009a23f6900fdd7ee1.png)1.5.2 组件化 2 …

系统集成项目管理工程师 笔记(第13章 项目合同管理)

文章目录 13.2.1 按信息系统 范围 划分的合同分类 4451、总承包合同2、单项工程承包合同3、分包合同 13.2.2 按项目 付款方式 划分的合同分类 4461、总价合同2、成本补偿合同&#xff08;卖方有利&#xff09;3、工料合同 13.3.1 项目合同的内容 44713.3.2 项目合同签订的注意事…

进程地址空间与页表方面知识点(缺页中断及写时拷贝部分原理)

谢谢阅读&#xff0c;如有错误请大佬留言&#xff01;&#xff01; 目录 谢谢阅读&#xff0c;如有错误请大佬留言&#xff01;&#xff01; 抛出总结 开始介绍 发现问题 进程地址空间&#xff08;虚拟地址&#xff09; 页表 物理内存与进程地址空间映射 缺页中断基本…

Linux操作系统之mysql数据库简介

文章目录 数据库的介绍有关数据库的操作有关数据表的操作C语言访问mysql事务视图索引 数据库的介绍 mysql数据库模型&#xff1a; 关系型数据库与非关系型数据库&#xff1a; 关系型数据库&#xff1a;指采用了关系模型来组织数据的数据库&#xff0c;关系模型就是指二维表格模…

【PCL】—— 点云滤波

文章目录 直通滤波降采样使用统计滤波&#xff08;statisticalOutlierRemoval&#xff09;移除离群点使用条件滤波&#xff08;ConditionalRemoval&#xff09;或 半径滤波&#xff08;RadiusOutlinerRemoval&#xff09;移除离群点 在获取点云数据时&#xff0c;由于设备精度&…

Vue(组件化编程:非单文件组件、单文件组件)

一、组件化编程 1. 对比传统编写与组件化编程&#xff08;下面两个解释图对比可以直观了解&#xff09; 传统组件编写&#xff1a;不同的HTML引入不同的样式和行为文件 组件方式编写&#xff1a;组件单独&#xff0c;复用率高&#xff08;前提组件拆分十分细致&#xff09; 理…

【Fluent】Error: Model information is incompatible with incoming mesh.

一、问题背景 在原有workbench数据文件上&#xff0c;修改几何数据&#xff0c;然后重新划分网格&#xff0c;在更新网格后&#xff0c;workbench就弹出错误Error&#xff01; Model information is incompatible with incoming mesh. 因为当时并不影响我打开fluent求解器&am…

C语言数组介绍和用法

文章目录 前言一、数组的定义二、数组的大小三、数组的访问方法四、使用for循环遍历数组五、数组地址的访问方法六、二维数组七、二维数组的遍历总结 前言 本篇文章将带大家学习C语言中的数组&#xff0c;数组在C语言中是一个比较重要的点&#xff0c;大家需要好好理解并多加使…

Linux Shell 介绍及常用命令汇总

文章目录 Part.I shell 简介Chap.I 概念汇编Chap.II 命令概览 Part.II shell 常用命令大全Chap.I 关于文件和目录Chap.II 关于磁盘和内存Chap.III 关于进程调度 Reference Part.I shell 简介 Chap.I 概念汇编 下面是一些概念 shell 与 bash 的区别与联系&#xff1a;bash 是 b…

2023五一杯B题:快递需求分析问题

题目 网络购物作为一种重要的消费方式&#xff0c;带动着快递服务需求飞速增长&#xff0c;为我国经济发展做出了重要贡献。准确地预测快递运输需求数量对于快递公司布局仓库站点、节约存储成本、规划运输线路等具有重要的意义。附件1、附件2、附件3为国内某快递公司记录的部分…

从力的角度再次比较9-2分布和8-3分布

( A, B )---1*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有1个节点&#xff0c;AB各由11张二值化的图片组成&#xff0c;让A中有3个0&#xff0c;8个1.B中全是0&#xff0c;排列组合A的所有可能&#xff0c;统计迭代次数的顺序。在前面实验中得到了8-3分布的数据 A-B 迭代次数 …