目录

1.基本定时器

2.基本定时器TIM的工作原理

2.1范例:定时1ms的计算

3.程序流程:

3.1配置时基初始化结构体

3.1.1时钟线的选择

3.1.2开启定时器更新中断

3.1.3TIM_ClearFlag()和函数TIM_ClearITPendingBit()区别

3.1.4允许更新中断函数及其寄存器DIER

3.2配置中断优先级

3.2.1移位

3.3使能定时器

3.4编写中断服务函数

3.5Main函数

4.代码示例


1.基本定时器

功能:定时,无PWM

● 计数器寄存器(TIMx_CNT)

● 预分频寄存器(TIMx_PSC)

● 自动重装载寄存器(TIMx_ARR)


2.基本定时器TIM的工作原理

来自内部时钟源的CK_PSC(频率=72MHz,72*10^6)进入到预分频器,预分频器PSC再对内部时钟CK_PSC分频,得到计数器时钟 CK_CNT = CK_PSC/(PSC+1)

当CNT_EN使能为1后,计数器CNT在CK_CNT时钟信号下,从0开始计数,电压周期性(计数一次的时间 1/CK_CNT) 的变为1/0,电压每变为1就记作是一次,当CNT的值与ARR的值相等时,就自动生成事件,且CNT自动清0,再重新开始计数


2.1范例:定时1ms的计算

PSC=72-1,72MHz=1/(72*10^6)usCNT=72MHz/(72-1+1)=1MHz=1us;即每过1us,有一次脉冲ARR=1000-1,从0计数到999,所以就记了1000次ARR*CNT=1ms

3.程序流程:

先配置中断,再配置TIM

3.1配置时基初始化结构体

 TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;RCC_APB1PeriphClockCmd(TIM_CLK,ENABLE);TIM_BaseInitStructure.TIM_Prescaler=TIM_PRE-1;TIM_BaseInitStructure.TIM_Period=TIM_ARR-1;

首先肯定要开启时钟线啦,至于开哪条呢?下面我也展示出来了

3.1.1时钟线的选择

APB1外设时钟使能寄存器(RCC_APB1ENR)

【28】PWR_EN是电源

APB2 外设时钟使能寄存器(RCC_APB2ENR)

我们可以观察到,APB1往往跟四大通讯方式,基本定时器,通用定时器(TIM2~TIM7)有关

而APB2往往与GPIO,EXTI(AFIO),高级定时器(TIM1,TIM8),注意还有一个USART1

总而言之呢,APB2在我们项目中比较常用的一些模块

3.1.2开启定时器更新中断

TIM_ClearFlag(BASICTIM,TIM_FLAG_Update);//清除更新中断标志位
TIM_ITConfig(BASICTIM,TIM_IT_Update,ENABLE);//TIM_IT_Update,开启更新中断

3.1.3TIM_ClearFlag()和函数TIM_ClearITPendingBit()区别

代码中有这样一条,有人会问函数TIM_ClearFlag()和函数TIM_ClearITPendingBit()有什么区别?其实重点在Flag和IT,前者是外设的状态标志,而后者是外设的中断标志。状态标志就是一个外设它有自身的一些标志位(Flag),来表明它处于什么状态,下图就是定时器的状态标记。中断标志就是使能外设的中断后,每次发生一次中断,它会表明发生了什么样的中断,同样中断也有相应的标记。两者分别靠函数TIM_GetFlagStatus()和函数TIM_GetITStatus()来获取

void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{  /* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG));/* Clear the flags */TIMx->SR = (uint16_t)~TIM_FLAG;
}
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_IT(TIM_IT));/* Clear the IT pending Bit */TIMx->SR = (uint16_t)~TIM_IT;
}

可以看到,两个函数基本一样,只是对TIM_FLAG或TIM_IT操作不同


3.1.4允许更新中断函数及其寄存器DIER

对于允许更新中断函数

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;}
}

可以简单看到,这个函数就是对中断使能寄存器【DIER】至0或至1操作

3.2配置中断优先级

NVIC_InitStructure.NVIC_IRQChannel=TIM_IRQN;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=NVIC_HIGHT_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=NVIC_LOW_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

我们可以看一下 NVIC_InitTypeDef 这个结构体里面都有什么

NVIC_IRQChannel

这一个是定义你的中断源,中断源可以在启动文件中找到

NVIC_IRQChannelPreemptionPriority

这一个是设置主优先级的结构体,由于我们是

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

所以范围只能选(0~3)

NVIC_IRQChannelSubPriority

设置从优先级,同理

那下面这句话有什么用呢

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

我们不妨先来看看这段NVIC_Init的函数

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;/* Check the parameters */assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE){/* Compute the Corresponding IRQ Priority --------------------------------*/    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;tmppre = (0x4 - tmppriority);tmpsub = tmpsub >> tmppriority;tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;tmppriority = tmppriority << 0x04;NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;/* Enable the Selected IRQ Channels --------------------------------------*/NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);}else{/* Disable the Selected IRQ Channels -------------------------------------*/NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);}
}

NVIC_InitStruct->NVIC_IRQChannelCmd会读取你是否是ENABLE,然后把配置好的主从优先级,中断源写进相关寄存器中

tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;

这一段代码,主要是先判断选择了哪一组的中断分组,然后把主从优先级依次写进AIRCR寄存器中,因为AIRCR只有10-8位才是控制优先级的,所以我们需要移位

3.2.1移位

关于移位,我用C写了一小段代码,当作是复习

3.3使能定时器

TIM_Cmd(BASICTIM,ENABLE);//打开定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Enable the TIM Counter */TIMx->CR1 |= TIM_CR1_CEN;}else{/* Disable the TIM Counter */TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN));}
}

3.4编写中断服务函数

void TIM6_IRQHandler()
{if(TIM_GetFlagStatus(TIM6,TIM_FLAG_Update)!=RESET){N++;}TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
}

3.5Main函数

//对基本定时器初始化
BasicTIM_Init();

4.代码示例

基本定时器示例

代码的移植性很高,里面也已经有大量的注释

STM32学习笔记(3) TIM基本定时器相关推荐

  1. STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)

    本篇文章包含的内容 一.TIM 定时器 1.1 TIM 定时器简介 1.2 TIM 定时器类型及其工作原理简介 1.2.1 基本定时器工作原理及其结构 1.2.2 通用定时器工作原理及其结构 1.2. ...

  2. STM32学习笔记(六)丨TIM定时器及其应用(输入捕获丨测量PWM波形的频率和占空比)

    本篇文章包含的内容 一.输入捕获 1.1 输入捕获简介 1.2 输入捕获通道的工作原理 1.3 输入捕获的主从触发模式 1.4 输入捕获和PWMI结构 二.频率的测量方法 2.1 测频法 2.2 测周 ...

  3. STM32学习笔记(10)——高级定时器TIM

    前排提示:本笔记参考了野火PPT的大部分内容.本人初学定时器,倍感冗杂,有错烦请指出,谢谢! STM32学习笔记(10)--高级定时器TIM 一.时钟源 1. 内部时钟源 2. 外部时钟模式 1 (1 ...

  4. STM32学习笔记(八)丨ADC模数转换器(ADC单、双通道转换)

    本篇文章包含的内容 一.ADC 模数转换器 1.1 ADC简介 1.2 逐次逼近型ADC工作原理 1.3 STM32中的ADC基本结构 1.4 STM32中ADC的输入通道 1.5 STM32中的AD ...

  5. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  6. 《STM32学习笔记》4——核心功能电路与编程(下)

    接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.蜂鸣器驱动 1.蜂鸣器介绍 2.蜂鸣器电路 3.蜂鸣器程序 二. MIDI 音乐 ...

  7. 硬件学习、高速dsp开发板制作、STM32学习笔记

    1.硬件工程师成长之路(1)--元件基础_[云轩]的博客-CSDN博客_硬件工程师的成长之路 总目录:https://blog.csdn.net/weixin_44407238/category_10 ...

  8. 《STM32学习笔记》3——核心功能电路与编程(上)

    接上文,文中的图片,大多数来自视频的截图(来自洋桃电子). 欢迎大家批评指正! STM32学习笔记-专栏 文章目录 一.核心板电路分析 二.点灯 LED 1.LED电路 2.LED功能相关初始化配置 ...

  9. STM32学习笔记(七)---SysTick

    STM32学习笔记(七)-SysTick 文章目录 STM32学习笔记(七)---SysTick 一.SysTick简介 二.SysTick功能框图 三.SysTick寄存器 四.SYSTICK使用 ...

  10. STM32学习笔记——基于正点原子例程编码器模式小结

    STM32学习笔记--基于正点原子例程编码器模式小结 最近一段时间学习了,STM32f4的编码器功能,经过自己探索和他人的热心帮助,对于编码器模式有了一定了解.STM32f4单片机提供编码器模式,以便 ...

最新文章

  1. 一文全面解析 Postman 工具
  2. VRRP与VLAN实验(HuaWei)
  3. 9-Building FIP images with support for Trusted Board Boot
  4. 1337:【例3-2】单词查找树
  5. 中根遍历二叉查找树所得序列一定是有序序列_二叉搜索树(BST)
  6. “3+3”看华为云FusionInsight如何引领“数据新基建”持续发展
  7. MySQL自动化审核平台部署说明
  8. Linux 命令(131)—— usermod 命令
  9. 各种翻页的效果! FILTER: revealTrans使用说明
  10. 恒生电子:O45好在哪儿(深度)| 国君计算机李沐华
  11. android studio怎么创建布局,Android Studio--活动创建简单布局
  12. Could not initialize class com.android.build.gradle.internal.VariantManager解决方案
  13. 解决Chrome账户无法同步
  14. 第五课:实现花样流水灯
  15. arm linux关机命令,嵌入式Linux的关闭命令是什么?
  16. 1、零基础学工控——初识plc
  17. 小马哥----高仿苹果6s 主板型号S106s 更换内核 刷机拆机主板图与开机识别图
  18. 操作系统学习——分时操作系统
  19. nginx通过获取环境变量实现动态IP代理配置
  20. warning: go env -w GO111MODULE=... does not override conflicting OS environment variable

热门文章

  1. 计算机基础 进制转化,计算机基础知识_进制转化(示例代码)
  2. 【C生万物】 指针篇 (进级) 上
  3. Kettle Could not initialize class org.apache.batik.bridge.CursorManager
  4. 微信的一些优点整理(持续更新)
  5. CSDN 的中铁粉是什么?如何获得粉丝与铁粉呢?一篇文章告诉你,干货满满,建议收藏
  6. 数据分析技能点-Excel的36个常规操作
  7. RuntimeError: cuda runtime error (30) : unknown error at /pytorch/aten/src/THC/THCGeneral.cpp:50
  8. keil 跳转不了(Go To Definition “XXX”失败)
  9. 现代OpenGL学习笔记二:第一个三角形
  10. 博弈论——万元陷阱和智猪博弈