0601STM32TIM
STM32TIM
- 内容概述
- TIM简介
- 定时器类型
- 基本定时器
- 时基单元
- 主从触发模式
- 通用定时器
- 外部时钟模式2
- 外部时钟模式1
- 定时器级联
- 输出捕获寄存器
- 高级定时器
- 定时中断基本结构
- 预分频器时序
- 计数器时序
- 计数器无预装时序
- 计数器有预装时序
- RCC时钟树
- 程序编写
内容概述
分为四部分,八小节
一部分:主要讲定时器基本定时的功能,也就是定一个事件,让定时器每隔这个时间产生一个中断,来实现每隔一个固定时间来执行一段程序的目的,比如做一个时钟、秒表,或者使用一些程序算法的时候,都需要用到定时中断的功能
二部分:定时器输出比较的功能,输出比较模块最常见的用途是产生PWM波形,用于驱动电机等设备(学习一下驱动舵机和直流电机)
三部分:定时器输入捕获的功能,学习使用输入捕获这个模块实现测量方波频率的例子
四部分:定时器的编码器接口,使用编码器接口,更加方便地读取正交编码器的输出波形,在编码电机测速中,应用广泛
STM32中功能最强大、结构最复杂的一个外设——定时器
TIM简介
定时器本质上是一个计数器,当计数器的输入是一个准确可靠的基准时钟的时候,那就基准时钟计时的过程中,实际上就是计时的过程,比如STM32中,定时器的基准时钟一般都是主频72MHz,比如对72MHz计72个数,那就是1MHz也就是1us的时间,如果计72000个数,就是1KHz,1ms时间,
16位计数器就是用来执行技术定时器的一个寄存器,每来一个时钟,计数器加1,
预分频器可以对计数器的时钟进行分频,让这个计数更加灵活
自动重装寄存器就是技术的目标值,就是想要计时多少个时钟申请中断
这些寄存器构成了定时器最核心的部分,我们把这一块电路称为时基单元。
时基单元里计数器、预分频器、自动重装寄存器都是16位的,216=65536,也就是如果预分频器设置最大,自动重装也设置最大,那定时器的最大定时时间就是59.65s, 72M/65536/65536得到的是中断频率,然后取倒数,就是59.65s多。如果还觉得不长,STM32的定时器还支持级联的模式,也就是一个定时器的输出,当做另一个定时器的输入,,这样就是59.65s再乘两次65536=8千多年,如果还嫌短,再级年一个定时器,,定时时间再延长65536*65536倍,时间大概是34万亿年。可见指数爆炸的威力。
由于定时器的这个基本结构是非常通用的,很多模块电路都能用到,所以STM32定时器上扩展了非常多的功能,第一部分讲定时器中断和内外时钟源选择的功能,第二部分讲输出比较,第三部分讲输入捕获和主从触发模式,第四部分讲编码器接口。
定时器类型
学习学的是通用定时器
因为同一块芯片有很多定时器,所以TIM后面会跟一个数字,编号和定时器类型的对应关系就是TIM1和TIM8是高级定时器,2345是通用定时器,67是基本定时器。连接的总线不一样,需要注意一下。
高级定时器中比通用定时器多的功能主要是为了三相无刷电机的驱动设计的。本课程暂时不会涉及到
不同的型号,定时器的数量是不同的,在使用这个外设之前,要看数据手册是不是有这个外设
基本定时器
时基单元
预分频器、计数器和自动重装寄存器构成最基本的计数计时电路,所以这一块叫时基单元
预分频器之前,连接的就是基准技术时钟的输入,由于基本定时器只能选择内部时钟,所以可以直接认为,这根线连到了内部时钟CK_INT,内部时钟来源是RCC_TIMxCLK,这里频率值一般是系统主频72MHz
预分频器可以对72MHz的计数时钟进行预分频,比如寄存器写0,那就是不分频,或者说是1分频。如果预分频器写1,那就是2分频,输出频率=输入频率/36MHz,预分频器的值和实际的分频系数相差了1,即实际分频系数=预分频器的值+1。预分频器是16位的,所以最大值可以写65535,也就是65536分频。
计数器可以对预分频后的计数时钟进行计数,计数时钟每来一个上升沿,计数器的值就加1,计数器也是16位的,里面的值可以从0-65535,所以计数器的值在计数过程中可以不断地自增运行,当自增运行到目标值时,产生中断,那就完成了定时的任务。
所以还需要一个存储目标值的寄存器,那就是自动重装寄存器,也是16位的,存的是我们写入的计数目标。在运行过程中,计时值不断自增,自动重装值时固定的目标,当计数值等于自动重装值时,也就是计数时间到了,那就会产生一个中断信号,并且清零计数器。计数器自动开始下一次的计数计时。
画的向上的折线箭头,就代表会产生中断信号。像这种计数值等于自动重装值产生的中断,一般叫做“更新中断”,更新中断之后,就会通往NVIC,再配置好NVIC的定时器通道,那定时器的更新中断就能得到CPU的响应了
向下的箭头代表会产生一个事件,这里对应的事件叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作。
以上这些是定时器定时中断的全部流程。
主从触发模式
STM32定时器的一大特色:主从触发模式:它让内部硬件在不受程序的控制下实现自动运行,如果主动触发模式掌握好,在一些情景下将极大地减轻CPU的负担。
比如:在使用DAC时,会使用DAC输出一段波形,那就需要每隔一段时间来触发一次DAC,让它输出下一个电压点,如果正常的思路来实现:就是先设置一个定时器产生中断,每隔一段时间在中断程序中调用代码手动触发一次DAC转换,然后DAC输出。但是会使主程序频繁被中断的状态,这会影响主程序的运行和其他中断的响应。
所以定时器设置了一个主模式:使用主模式可以把定时器的更新事件映射到触发输出TRGO(Trigger Out)的位置,然后TRGO直接接到DAC的触发转换引脚上,这样定时器的更新就不需要通过中断来触发DAC转换了,仅需要把更新事件通过主模式映射到TRGO,然后TRGO就会直接去触发DAC了,整个过程不需要软件的参与,实现了硬件的自动化。 除了主模式还有很多硬件自动化的设计,后续再做了解。
通用定时器
基本定时器仅支持向上计数一种模式
通用定时器:除了向上计数的模式外,还支持向下计数模式和中央对齐模式
向下计数模式:从重装值开始,向下自减,减到0后,回到重装值同时申请中断,然后继续下一轮,依次循环
中央对齐计数模式,从0开始,先向上自增,计到重装值,申请中断,然后向下自减,减到0后再申请中断,然后继续下一轮,依次循环
外部时钟模式2
内外时钟源的选择和主从触发模式的结构,
对于内外时钟源的选择,基本定时器只能选内部时钟,就是系统频率72MHz。
通用定时器还可以选择外部时钟:
1.TIMx_ETR 引脚上的外部时钟,ETR(External),比如可以在TIM2的ETR引脚,也就是PA0上接一个外部方波信号,然后配置内部的极性选择,边沿检测和预分频器电路,再配置一下输入滤波电路,这些电路可以对外部时钟进行一定的整形,因为是外部的引脚的时钟,所以难免有毛刺,这些电路就可以对输入的波形进行滤波。滤波后的信号分为两路,上面一路ETRF进入触发控制器,然后就可以选择作为时基单元的时钟了,如果想在ETR外部引脚提供时钟,或者相对ETR时钟进行计数,把这个定时器当做计数器来用的话,那就可以配置这一路电路,在STM32中,这一路也叫做:“外部时钟模式2”
外部时钟模式1
2.TRGI(Trigger In)单从名字来看,主要是用作触发输入来使用,这个触发输入可以触发定时器的从模式(后续再讲),本节讲的是这个触发输入当做外部时钟来使用的情况,当TRGI当做外部输入时钟来使用的时候,这一路叫做“外部时钟模式1”
通过这一路的外部时钟都有:
ETR引脚信号 既可以通过上面这一路进来当做时钟,又可以通过下面这一路进来当做时钟,两种情况对于输出而言是等价的,只不过下面这一路输入会占用触发输入的通道而已。
定时器级联
ITR信号是来自于其他定时器的,从右边可以看出,主模式的输出TRGO可以通向其他定时器那通向其他定时器的时候,就接到了其他定时器的ITR引脚上了,这个ITR0-ITR3分别来自其他4个定时器的TRGO输出,这个表可以看到TIM2的ITR0接到了TIM1的TRGO上。通过这1路可以实现定时器级联的功能,比如初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,接着在初始化TIM2,这里选择ITR2,对用就是TIM3的ITGO,然后后面再选择时钟为外部时钟模式1,这样TIM3的更新事件就可以驱动TIM2的时基单元,也就实现了定时器的级联。
3.TI1F_ED,这里连接的是输入捕获单元的CH1引脚,也就是从CH1引脚获得时钟,ED(Edge 边沿的意思),也就是这一路时钟,上升沿和下降沿均有效,
4.TI1FP1和TI2FP2获得,其中TI1FP1就是CH1引脚的时钟,TI2FP1就是CH2引脚的时钟,
一般情况下,外部时钟通过ETR引脚就可以了,下面设置这么复杂的输入,不仅仅是为了扩大时钟输入的范围,更多的是为了某些特殊应用场景而设计的,比如为了定时器的级联而设计的这一部分,再下面讲输入捕获和测频率时,还会继续讲到。
对于时钟而言,最常用的还是72MHz的时钟,如果要使用外部时钟,首选ETR引脚外部时钟模式2的输入,这一路最简单,最直接。
这是定时器的一个编码器接口,,可以读取正交编码器的输出波形,后续再讲。
输出捕获寄存器
右边是输出比较电路,总共4个通道,分别对应CH1-CH4的引脚,可以用于输出PWM波形,驱动电机。
左边是输入捕获电路,总共4个通道,对应CH1-CH4的引脚,可以用于测量输入方波的频率等
中间的寄存器是捕获/比较寄存器,是输入捕获和输出捕获比较电路共用的。因为输入捕获和输出比较不能同时使用,所以寄存器共用,引脚也共用。
本节先讲定时中断和内外时钟源选择,
高级定时器
主要变动的部分:
1.申请中断的地方,增加了一个重复次数计数器,有了这个计数器之后,就可以实现每隔几个计数周期,才发生一次更更新事件和更新中断,原来的结构是每个计数周期完成后都会发生更新,这就相当于对输出的更新信号又做了一次分频,这里可以59s多再乘65536,
2.对输出比较模块的升级:DTG(Dead Time Generate)是死区生成电路,右边的输出引脚由原来的一个变为了两个互补的输出,可以输出一对互补的PWM波,这些电路是为了驱动三相无刷电机的,三相无刷电机还是比较常用,比如四轴飞行器,电动车的后轮、电钻等里面都可能是三相无刷电机,因为三相无刷电机的驱动电路需要三个桥臂,每个桥臂两个大功率开关管来控制,总共需要6个大功率开关管来控制,所以这里的输出PWM引脚的前三路就变为了互补的输出,而第4路却没什么变化。
为了防止互补输出的PWM驱动桥臂时,在开关切换的瞬间,由于器件的不理想,造成短暂的直通现象,所以前面加上了死区生成电路,在开关切换的瞬间,产生一定时长的死区,让桥臂的上下管全都关断,防止直通现象。
3.刹车输入的功能,是为了给电机驱动提供安全保障的,如果外部引脚BKIN(Break IN)产生了刹车信号,或者内部时钟失效,产生了故障,那么控制电路就会自动切断电机的输出,防止意外的发生。
定时中断基本结构
本小节的两个任务:定时中断和内外时钟源的选择
最重要的还是PSC(Prescaler)预分频器,CNT(Counter)计数器,ARR(AutoReloadRegister)自动重装器这三个寄存器构成的时基单元。
下面是运行控制,就是控制寄存器的一些位,比如启动停止,向上或向下计数等等,操作这些寄存器就可以控制时基单元的运行了
左边是为时基单元提供时钟的部分,这里可以选择内部时钟,也可以选择ETR引脚提供的外部时钟模式2,
此小节示例程序,第一个定时器定时中断就是用的内部时钟这一路,第二个定时器外部时钟就是用的外部时钟模式2这一路。
中断信号会先在状态寄存器里置一个中断标志位,这个标志位会通过中断输出控制,到NVIC申请中断
加中断输出控制的原因:因为定时器模块很多地方都要申请中断,不仅更新要申请中断,触发信号也会申请中断,输入捕获和输出比较匹配也会申请。如果需要中断,就允许,如果不需要,那就禁止。简单来说,中断输出控制就是一个中断输出的允许位。如果需要某个中断,就记得允许一下。
预分频器时序
CK_PSC 预分频器的输入时钟
CNT_EN 计数器使能,高电平计数器正常运行,低电平计数器停止
CK_CNT 计数器时钟,既是预分频器的时钟输出,也是计数器的时钟输入,可以看到计数器未使能,计数器时钟不运行,使能后前半段预分频器系数为1,计数器的时钟等于预分频器前的时钟。后半段预分频器系数变为2,计数器的时钟也变为预分频器前时钟的一半了。
在计数器时钟的驱动下,下面计数器寄存器也跟随着时钟的上升沿不断自增,这里可以推断ARR自动重装值就是FC,当计数值计到和重装值相等,并且下一个时钟来临时,计数值才清零。同时下面产生一个更新事件。 这就是一个计数周期的工作流程
下面的三行时序描述的是预分频寄存器的一种缓冲机制,也就是预分频器实际上是有两个,一个供我们读写用的,并不直接决定分频系数,另外还有一个缓冲寄存器或者说影子寄存器,这个才是真正起作用的寄存器。
比如在某个时刻,把预分频寄存器由0改成1,如果在此时理科改变时钟的分频系数,那么就会导致这里在一个计数周期内,前半部分和后半部分的频率不一样,当计数计到一半时,频率突然改变了,这虽然不会有什么问题。但是STM32比较严谨,设计了这个缓冲寄存器,当计数计到一半的时候,改变了分频值,这个变化并不会立刻生效,而是会等到本次计数周期结束时,产生了更新事件,预分频寄存器的值才会传递到缓冲寄存器里面去,才会生效。
所以这里可以看到,即使在计数中途改变了预分频器的值,计数频率仍然会保持为原来的频率,直到本轮计数完成,在下一轮计数时,改变后的分频值才会起作用。
最后也是,预分频器内部实际上也是靠计数来分频的。当预分频值为0时,计数器就一直为0,直接输出原频率。当预分频器值为1时,计数器就0、1 、0、 1、 这样计数。在回到0时,输出一个脉冲。这样输出频率就是输入频率的2分频。预分频器的值和实际的分频系数之间有一个数的偏移。
计数器时序
增加到36的时候,发生溢出,那计到36的时候,再来一个上升沿,计数器清零,计数器溢出,产生一个更新事件脉冲,另外还会置一个更新中断标志位UF,这个标志位只要置1了,就会去申请中断,然后中断响应后,需要在中断程序中手动清零,这是计数器的工作流程。
带一个黑色阴影的寄存器,都是有影子寄存器这样的缓冲机制的。包括预分频器、自动重装寄存器、和下面的捕获比较寄存器。
所以计数器的这个ARR自动重装寄存器,也是有一个缓冲寄存器的。并且缓冲寄存器是用还是不用,可以自己设置
计数器无预装时序
就是没有缓冲寄存器的情况
突然更改自动加载寄存器,就是自动重装寄存器,由FF改为36,那计数值的目标就由FF变成了36,所以这里计到36之后,就直接更新,开始下一轮计数,
计数器有预装时序
就是有缓冲寄存器的情况,通过ARPE位,就可以选择是否使用预装功能。
突然更改自动加载寄存器,就是自动重装寄存器,由F5改为36,那计数值的目标还是计到F5之后,产生中断事件,同时要更改的36才被传递到影子寄存器。
在下一个计数周期这个更改的36才有效。
所以可以看出,引入影子寄存器的目的实际上是为了同步,就是让值的变化和更新中断事件同步发生,防止在运行途中更改造成错误。
如果不使用影子寄存器,F5改到36立刻生效,但此时计数器已经到了F1,已经超过36了,F1只能增加,但它的目标却是36,比它还小,这样F1就只能一直加,一直加,加到FFFF,再回到0再加到36才能产生更新,这就可能会造成一些小问题。
RCC时钟树
这个时钟树就是STM32中用来产生和配置时钟,并且把配置好的时钟发送到各个外设的系统,
时钟是所有外设运行的基础,所以时钟也是最先需要配置的东西,在程序中主函数之前还会执行一个SystemInit函数,这个函数就是用来配置时钟数的。
结构看上去挺复杂,配置起来还是比较麻烦的,但是ST公司已经写好了配置这个时钟树的SystemInit函数。
从SYSCLK系统时钟,划一根线,左边的都是时钟的产生电路,右边的都是时钟的分配电路
时钟产生电路,有4个震荡源,分别是内部的8MHz高速RC振荡器、外部的4-16MHz高速石英晶体振荡器,也就是晶振,一般都是接8MHz,外部的32.768KHz低速晶振,这一般是给RTC提供时钟的,40KHz低速RC振荡器,可以给看门狗提供时钟。
高速晶振用来提供系统时钟,我们的AHB、APB2、APB1时钟都来源于这两个高速晶振,外部的石英振荡器比内部的RC振荡器更加稳定,所以一般用外部晶振,但是系统简单并且不需要那么精确的时钟,那也可以使用内部RC振荡器,这样就可以剩下外部晶振的电路了。
在SystemInit函数里,ST是这样来配置时钟的:
首先启动内部时钟,选择内部8MHz为系统时钟,暂时以内部8MHz的时钟运行,然后再启动外部时钟,配置外部时钟,进入PLL锁相环进行倍频,8MHz倍频9倍,得到72MHz,等到锁相环输出稳定后,选择锁相环输出为系统时钟,这样就可以把系统时钟8MHz切换为72MHz,这是ST配置的流程。
也可以自己分析SystemInit函数,这样分析之后,可以解决实际应用的一个问题,那就是如果外部晶振出问题了,可能会导致一个现象,就是会发现,程序的时钟慢了大概10倍,比如用定时器定一个1s的时间,结果过了大概10s才会进中断,这个问题就出在这里,如果外部晶振出问题了,系统时钟就无法切换到72MHz,那就会以内部的8MHz运行,8MHz相比较72M,大概慢了10倍。
CSS是时钟安全系统,它也是负责切换时钟的,它可以监测外部时钟的运行状态,一旦外部时钟失效,就会自动把外部时钟切换回内部时钟,保证系统时钟的运行,防止程序卡死造成事故。
高级定时器中也有CSS的身影,在刹车输入这里,一旦CSS检测到外部时钟失效,通过或门立刻反映到输出比较,让输出控制的电机立刻停止,防止意外。
右边是时钟分配电路:
系统时钟72MHz进入AHB总线,AHB总线有一个预分频器,在SystemInit里配置的分频系数为1,那AHB就是72MHz,然后进入APB1总线,这里配置的分频系数是2,所以APB1总线的时钟为72MHz/2=36MHz。
通用定时器和基本定时器是接在APB1上的,但是频率*2,通向定时器2-7的时钟单独输出了一路。
具体情况还得根据SystemInit里面的配置,
APB2也是单独输出一路,时钟输出这里,都有一个与门进行输出控制,控制位写的是外部时钟使能,这既是在程序中写RCC_APB2/1PeriphClockCmd作用的地方,打开时钟就是在这个位置写1,让左边的时钟能够通过与门输出给外设。
程序编写
1.RCC开启时钟,基本上每个代码都是第一步,不用多想,打开时钟后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了,
2.选择时基单元的时钟源,对于定时器中断,选择内部时钟源,
3.配置时基单元,包括预分频器、自动重装器、计数模式等,用一个结构体配置就好了
4.配置输出中断控制,允许更新中断输出都按NVIC
5.配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级
6.运行控制,整个模块配置完成后,还需要使能一下计数器,要不然计数器不会运行。
当定时器使能后,计时器就会开始计数了,当计数器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断每隔一段时间就能自动执行一次了。
TIM_DeInit(TIM_TypeDef* TIMx) 恢复缺省配置、
TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) 时基单元初始化,用来配置这个图里的时基单元的 两个参数:第一个TIMx选择某个定时器,第二个是结构体,里面包含了配置时基单元的一些参数
这样就可以在代码左边添加一个书签,再点一下就清楚书签。这个书签只是做个标记,方便查找代码用的,对代码运行没有任何影响,有做标记的需要时要用到书签。
TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) 这个函数可以把结构体变量赋一个默认值,这个之前都见过,没啥说的
TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState) 使能计数器的,对应图里的运行控制 有两个参数:第一个TIMx选择定时器,第二个NewState新的状态,也就是使能还是失能。使能计数器可以运行,失能计数器不运行。
TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState) 使能中断输出信号的,对应中断输出控制位置 第一个TIMx选择定时器、第二个TIM_IT,选择要配置哪个中断输出、第三个NewState新的状态使能还是失能。 这个函数还会经常碰到,就是使能外设的中断输出
这6个函数对应就是时钟选择部分,可以选择RCC内部时钟,ETR外部时钟、ITRx其他定时器、TIx捕获通道这些。
1.TIM_InternalClockConfig(TIM_TypeDef* TIMx) 选择内部时钟,参数只有一个TIMx
2.TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) 选择ITRx其他定时器的时钟,参数是TIMx,选择要配置的定时器和InputTriggerSource,选择要接入哪个其他的定时器。
3.TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter)
选择TIx捕获通道的时钟, 参数 TIMx, TIxExternalCLKSource选择TIx具体的某个引脚,ICPolarity输入的极性 ICFilter滤波器
对于外部引脚的波形,一般都会有极性选择和滤波器,这样更灵活一些,
4.TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter)
选择ETR通过外部时钟模式1输入的时钟, 参数TIMx, ExtTRGPrescaler外部触发预分频器,这里可以对ETR的外部时钟再提前做一个分频,ICPolarity输入的极性 ICFilter滤波器
5.TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
选择ETR通过外部时钟模式2输入的时钟
对于ETR输入的外部时钟而言,4.5.这两个函数是等效的。它们的参数也是一样的,如果不需要触发输入的功能,那么两个函数可以互换。
6.TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
不是用来选择时钟的,就是单独用来配置ETR引脚的预分频器、极性、滤波器这些参数的。
NVIC用NVIC_Init函数
TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode),就是用来单独写预分频值的,
参数:Prescaler 要写入的预分频值, PSCReload写入的模式 预分频器有一个缓冲器,写入的值在更新事件发生后才有效的,这里写入的模式:可以选择时听从安排,在更新事件生效,或者是写入后,手动产生一个更新事件,让这个值立刻生效。
TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
用来改变计数器的计数模式,参数counterMode 选择新的计数器模式,
TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
自动重装器预装功能配置
调用这个函数选择时有预装还是无预装
TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
给计数器写入一个值,如果想手动给一个计数值,就可以用这个函数
TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
给自动重装器写入一个值,如果想手动给一个自动重装值,就可以用这个函数
TIM_GetCounter(TIM_TypeDef* TIMx)
获取当前计数器的值,如果想看当前计数器计到哪里了,就可以调用一下这个函数,返回值就是当前计数器的值
TIM_GetPrescaler(TIM_TypeDef* TIMx)
获取当前预分频器的值,
下面的四个是获取标志位和清除标志位的函数
Clockdivision时钟分频的参数