STM32 定时器(一)——定时器时间的计算 STM32的定时器是灰常NB的,也是灰常让人头晕的(当然是对于白菜来说的)。 STM32中的定时器有很多用法: (一)系统时钟(SysTick) 设置非常简单,以下是产生1ms中断的设置,和产生10ms延时的函数: - <div align="left">void RCC_Configuration(void)
/ h7 `1 q: j& Q! y. b% S' r M - {6 J- F4 a, y1 G' w# d( M+ k
- RCC_ClocksTypeDef RCC_ClockFreq;7 [$ l2 @: _5 Z
- SystemInit();//源自system_stm32f10x.c文件,只需要调用此函数,则可完成RCC的配置.3 Q) [! \9 A( E0 H( h
- RCC_GetClocksFreq(&RCC_ClockFreq);</div><div align="left">//SYSTICK分频--1ms的系统时钟中断4 j9 A' O& P0 W2 D% f" P# D! v
- if (SysTick_Config(SystemFrequency / 1000))9 c* \% Z3 i+ }3 z- s u
- { & v1 ]- o/ }: s" ~9 \. w" ]7 A$ b* o
- while (1); // Capture error1 A2 o S3 h' K- n4 N) f* e
- }
1 N: h* g. Z3 N7 Q7 t - }</div><div align="left">void SysTick_Handler(void)//在中断处理函数中的程序
h) @/ Q- J3 C2 A, ` - {
6 B/ q2 x, @6 `, Y! j. g2 J - while(tim)
1 }: g/ f/ P8 K$ W3 v9 c: Z I* S - {- e" |3 X, w7 h4 J2 \; C
- tim--;
D8 c6 Z: J# Y9 b6 a - }
! Z5 Q* [6 z, E6 k - }</div><div align="left">//调用程序:
* n& k! x- u, v - Delay_Ms(10);</div>
复制代码 $ {/ O, `4 u R
当然,前提是要设置好,变量tim要设置成volatile类型的。 (二)第二种涉及到定时器计数时间(TIMx) - /*TIM3时钟配置*/! ~- X8 L+ Q6 Y9 u: g) R% }
- TIM_TimeBaseStructure.TIM_Prescaler = 2; //预分频(时钟分频)72M/(2+1)=24M4 n$ C' c/ @5 x
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
. Y1 u% p" }3 X" A2 k9 j) R - TIM_TimeBaseStructure.TIM_Period = 65535; //装载值18k/144=125hz
2 Y0 Z: e a/ k+ U; [; O( n - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;, s! S X6 ^6 F6 ?- D7 Z
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;! t$ \, B9 H* Z0 t6 Q' E+ c/ x
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
复制代码
- g5 ?% s, f2 F! J5 s定时时间计算:
; V8 K6 I) L3 y% _( ~- TIM_TimeBaseStructure.TIM_Prescaler = 2;2 K8 ]) s/ T4 y, X B
- //分频2 72M/(2+1)/2=24MHz7 e! T8 h$ a# K8 i( ?4 A
- TIM_TimeBaseStructure.TIM_Period = 65535; //计数值65535
9 c! D" ]/ q' V4 z/ H - ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+2)/72M)*(1+65535)=0.00273秒=366.2Hz */
复制代码 / u# A. h! u' K/ r- _4 ~
注意两点(来自大虾网,未经检验)
+ B/ G, g Q" |( r; z& }' h(1)TIMx(1-8),在库设置默认的情况下,都是72M的时钟;9 t2 @% F8 I; }6 e0 G" N6 v
(2)TIM_TimeBaseStructure.TIM_RepetitionCounter=0;/ Z. Q3 k( U9 j$ q
是重复计数,就是重复溢出多少次才给你来一个溢出中断,2 e/ T8 ]& _$ c
它对应的寄存器叫TIM1 RCR.
( G+ c! Y# W) B0 q2 ?* h如果这个值不配置,上电的时候寄存器值可是随机的,本来1秒中断一次,可能变成N 秒中断一次,让你超级头大! STM32 定时器用于外部脉冲计数 因为用stm32f103c8作主控制器,来控制小车,小车的转速由两路光电编码盘输入(左右各一路).因此想到外部时钟触发模式(TIM——ETRClockMode2Config)。 可以试好好久,发现TIM1不能计数,到网上查了很久,也没有找到相关的文章,开始怀疑TIM1是不是需要特殊设置。经过很久的纠结,终于找到了问题——其实是我自己在GPIO设置的时候,后面的不小心覆盖了前面的了——没想到自己也会犯这么SB的事情。 现总结程序如下: 第一步,设置GPIO - <div align="left">GPIO_InitTypeDef GPIO_InitStructure;</div><div align="left">/* PA0,PA12-> 左右脉冲输入 */
! ^6 P& U3 t2 } g6 Z* w - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_12;
. l, u/ \) W! b _; L - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
5 ~9 G, }! ]: U# M: m - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
5 Q8 Z1 U0 m& s" T - GPIO_Init(GPIOA, &GPIO_InitStructure);</div>
复制代码 ) S9 Q' l4 K0 x/ n
注意:(1)stm32f103c8只有TIM1_ETR(PA12,Pin33),和TIM2_CH1_ETR(PA0,Pin10)两个可以用。其它更多管脚的芯片,有更多的可以输入(如100管脚的有4个可以输入的);(2)外部时钟输入与中断无关;(3)stm32f103c8的这个两个应用中,不需要重映射。 对于哪些需要重映射,参考数据手册。 第二步:设置RCC - <div align="left">RCC_ClocksTypeDef RCC_ClockFreq;</div><div align="left">SystemInit();//源自system_stm32f10x.c文件,只需要调用此函数,则可完成RCC的配置.
$ G3 J1 o" z: q/ n - RCC_GetClocksFreq(&RCC_ClockFreq);</div><div align="left">RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- b9 P- D- N) ~4 p" ]& D - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
) k' |% Z& [% @$ \" w- Q8 [/ j- ]2 _, _ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
3 _) p" `9 b: Z& `+ r- G2 w! a0 ? - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);</div>
复制代码 9 a+ k3 u* j! q" q9 I) u: q$ [% C
第三步,设置定时器模式 - <div align="left">void TIM1_Configuration(void) //只用一个外部脉冲端口
' W; }, p4 ~. L% s" F# b+ O/ n! y - { s5 \8 G- g) \1 K4 l# M1 p- e+ w5 A
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</div><div align="left">
3 c" s+ b* p9 q, z. ~ - //配置TIMER1作为计数器
: c3 B2 v2 ~ V& ], | - TIM_DeInit(TIM1);</div><div align="left"> TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
2 |& H5 `$ i; b+ b; ?9 R* E - TIM_TimeBaseStructure.TIM_Prescaler = 0x00;
6 [8 e; ^; r$ n N - TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;8 [, e" U9 ]6 P
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
% Q& c6 K0 P5 V* n! u - TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // Time base configuration! V2 c& r; E) _1 s
4 s' h: h, Q4 P) L1 S3 q- TIM_ETRClockMode2Config(TIM1, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);</div><div align="left">TIM_SetCounter(TIM1, 0); @$ C0 I1 r& g7 n
- TIM_Cmd(TIM1, ENABLE);
. E, T, W r" c6 N, Q1 |" f - }
1 D2 ~1 P% u K& k" { - . P+ a& L/ f9 R0 c* G
- void TIM2_Configuration(void) //只用一个外部脉冲端口
6 N! h7 j, W% I( u4 B+ j - {
! i, t5 S2 x% b* u4 u - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</div><div align="left">
- y2 h4 m; {* y7 E" A - //配置TIMER2作为计数器# Y, `2 t( U5 r/ U( G
- TIM_DeInit(TIM2);</div><div align="left"> TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
N- _+ j: |; \# R& B$ U" Y2 w. G - TIM_TimeBaseStructure.TIM_Prescaler = 0x00;
8 Z }2 v: A- p( a+ J3 E - TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
2 _6 C i s9 a1 S- {4 D5 i s - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;8 P' C1 y9 G8 H
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // Time base configuration
/ n0 c% ~: W* p2 A* N' Z% i - & o( |; }' ~. R% L" G7 f
- TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);</div><div align="left">TIM_SetCounter(TIM2, 0);8 d0 j u" w& b+ r
- TIM_Cmd(TIM2, ENABLE);
P+ n# v* E7 ~! J6 n$ i - }</div>
复制代码 , w- @+ J! B: E. [
第四步,可以在主函数中读取计数器的值,其它的应用,就看具体的情况了。 - <div align="left">u16 COUN1=0;6 z' _, d* {: q9 K+ h* {* \
- u16 COUN2=0;</div><div align="left">int main(void)8 l, Y0 S3 ]' w2 r7 O& h
- {/ Q6 r% I+ \' H2 z5 t; M% {
- ChipHalInit();$ m# ^0 a7 O S* L) s$ o* Z
- ChipOutHalInit();</div><div align="left">while(1)
! }; l7 c2 a9 z1 y - {
5 |- T4 X5 I4 g+ @& \* {; n- s2 [ - COUN1=TIM1->CNT;* v* e8 g `6 J
- COUN2=TIM2->CNT;# \0 y( x: n) R4 l
- }</div><div align="left">}</div>
复制代码 ' z5 e7 U6 g/ E$ U) E. D
' g8 R$ E% U1 ^% f a
+ L4 l2 L0 q$ _8 F, v$ t7 H
/ |. P2 j8 A0 V8 d |