|
STM32 定时器(一)——定时器时间的计算 STM32的定时器是灰常NB的,也是灰常让人头晕的(当然是对于白菜来说的)。 STM32中的定时器有很多用法: (一)系统时钟(SysTick) 设置非常简单,以下是产生1ms中断的设置,和产生10ms延时的函数: - <div align="left">void RCC_Configuration(void)
# L9 C5 w) N3 N - {, F: f' G7 ~! f& |9 n; u# m
- RCC_ClocksTypeDef RCC_ClockFreq;
& f V3 v$ x7 z. K$ K/ P0 j0 _ - SystemInit();//源自system_stm32f10x.c文件,只需要调用此函数,则可完成RCC的配置.
* ]( O: K* B' q' E5 s2 p( g - RCC_GetClocksFreq(&RCC_ClockFreq);</div><div align="left">//SYSTICK分频--1ms的系统时钟中断
s! V2 H6 a! E3 @ k8 z - if (SysTick_Config(SystemFrequency / 1000))
2 L u3 ?- x w - { $ x% ?- m& w% R t# B
- while (1); // Capture error3 V0 d4 ~" r8 l
- }
" T* o) Y5 h; |& R% u6 S S - }</div><div align="left">void SysTick_Handler(void)//在中断处理函数中的程序
0 |& _5 P' J6 j# H! G$ r; ~ E% _9 j - {$ d# j' ~2 H! t6 T6 h
- while(tim). b( Z/ e h! ~1 d. L
- {- Q: I- A$ @! G$ M$ G* `! a
- tim--;
+ r! m( ?8 n/ ^2 i5 ^/ P - }% O, F; j O, H1 E+ t1 m# B0 G* Z
- }</div><div align="left">//调用程序:
/ R3 t1 k. ]. A( T4 P+ U# J: s - Delay_Ms(10);</div>
复制代码 ) ?" J1 [' x6 n$ @9 T9 _& J
当然,前提是要设置好,变量tim要设置成volatile类型的。 (二)第二种涉及到定时器计数时间(TIMx) - /*TIM3时钟配置*/5 U: w# P$ Y# `( Z9 @% @
- TIM_TimeBaseStructure.TIM_Prescaler = 2; //预分频(时钟分频)72M/(2+1)=24M
( Y6 T3 [# o5 O5 T% d# a - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
) O1 Y0 |! `" L7 `( X' O# h8 Y# y - TIM_TimeBaseStructure.TIM_Period = 65535; //装载值18k/144=125hz
. } l! p, f9 P* [9 C2 i - TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;2 Z" t4 e O; B0 B- H
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;0 [0 @9 q, k5 z
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
复制代码
5 R& q, L: e) y- f! `& Y( B5 r* x定时时间计算: 4 p6 Q6 w2 `" |( z" f, l* W/ I
- TIM_TimeBaseStructure.TIM_Prescaler = 2;, H/ W( H4 F& d! O5 [6 {, ?
- //分频2 72M/(2+1)/2=24MHz9 R j- t2 L! J V
- TIM_TimeBaseStructure.TIM_Period = 65535; //计数值65535; R) _2 f r5 b3 q1 }
- ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+2)/72M)*(1+65535)=0.00273秒=366.2Hz */
复制代码 ) O& b- g$ C) L: y7 g1 z, X7 n9 K/ z
注意两点(来自大虾网,未经检验)1 F8 U" t( M" p0 X6 c9 U$ g2 A
(1)TIMx(1-8),在库设置默认的情况下,都是72M的时钟;" O/ g! r9 k2 X: Q- s2 v4 v2 c1 g; Z$ l
(2)TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
/ c) _7 L9 ? U是重复计数,就是重复溢出多少次才给你来一个溢出中断,( y' _8 I2 V6 ]3 j) }$ d
它对应的寄存器叫TIM1 RCR.
9 M1 [1 U; Z* N* X( e. B, P/ C如果这个值不配置,上电的时候寄存器值可是随机的,本来1秒中断一次,可能变成N 秒中断一次,让你超级头大! STM32 定时器用于外部脉冲计数 因为用stm32f103c8作主控制器,来控制小车,小车的转速由两路光电编码盘输入(左右各一路).因此想到外部时钟触发模式(TIM——ETRClockMode2Config)。 可以试好好久,发现TIM1不能计数,到网上查了很久,也没有找到相关的文章,开始怀疑TIM1是不是需要特殊设置。经过很久的纠结,终于找到了问题——其实是我自己在GPIO设置的时候,后面的不小心覆盖了前面的了——没想到自己也会犯这么SB的事情。 现总结程序如下: 第一步,设置GPIO - <div align="left">GPIO_InitTypeDef GPIO_InitStructure;</div><div align="left">/* PA0,PA12-> 左右脉冲输入 */
: ~, F) i$ c3 o4 B6 H+ ^) w+ [7 c - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_12;1 m3 k/ D$ ~ }: z' v4 A9 a/ F
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //2 Y9 ~* [! ~" N& m- A4 e, C
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
0 M- O# {* c) Y* o - GPIO_Init(GPIOA, &GPIO_InitStructure);</div>
复制代码
4 D4 p6 Y6 f4 B7 U! B4 u: r注意:(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的配置.
' n1 P( h. p. d: v& ]( O - RCC_GetClocksFreq(&RCC_ClockFreq);</div><div align="left">RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);* [ Q4 F2 z9 @6 v' q! w1 V. ]
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);2 X! w# z8 R2 H( T; K5 O1 C
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);( u7 O q4 k! Y& f. N
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);</div>
复制代码
7 {, Q3 J7 l! Y1 h e( e2 }第三步,设置定时器模式 - <div align="left">void TIM1_Configuration(void) //只用一个外部脉冲端口
& H9 u$ {% e3 G. \- I8 |3 G - {0 P6 h. g8 X6 b. U7 G8 \+ ~
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</div><div align="left">
7 ]/ E7 z ~6 t9 r - //配置TIMER1作为计数器
B& K) U k2 d, d, `: d0 C; i5 M - TIM_DeInit(TIM1);</div><div align="left"> TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
, P6 \' T- K- j - TIM_TimeBaseStructure.TIM_Prescaler = 0x00;* {9 I5 e( f/ O" b$ I1 q
- TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
' `) r4 ?$ N/ J) e q$ t - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
p0 Z. f7 d0 l! V - TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // Time base configuration Y+ e3 v+ _! J( `% G5 P2 M
2 {" r, ]- C! Y- Z- TIM_ETRClockMode2Config(TIM1, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);</div><div align="left">TIM_SetCounter(TIM1, 0);
4 N/ {; r* r8 G5 X$ q: \ - TIM_Cmd(TIM1, ENABLE);
0 x+ m2 r: |+ T* | - }
4 G! f/ d P: W. P3 E3 u: O - - D( l! j& t' I# A) v% F
- void TIM2_Configuration(void) //只用一个外部脉冲端口* q# ^- `9 U' ~% [$ S
- {
" m3 e* s6 ^# F# c5 v6 P - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</div><div align="left">
$ q! {+ N$ h2 d3 V2 r8 s3 G9 U - //配置TIMER2作为计数器: F- |) {! J# ?- Q |* w- e
- TIM_DeInit(TIM2);</div><div align="left"> TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
. R2 q" T& ~; C; a" ~/ ^/ {' T. |7 V - TIM_TimeBaseStructure.TIM_Prescaler = 0x00;' ^$ e+ S$ R! h& C
- TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;0 s- Z: ~' {, K$ K% v% \/ T N
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;5 V) W$ ?: j0 L" e$ v$ y
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // Time base configuration: { C! s4 k& v$ Z1 _
- / L; h7 h/ w$ ~( p; k, u
- TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);</div><div align="left">TIM_SetCounter(TIM2, 0);
- R5 I- o% M) K- h! e* k - TIM_Cmd(TIM2, ENABLE);8 g" @" x! T |
- }</div>
复制代码
& p- n- W% `& u& r" h$ ^( R* a第四步,可以在主函数中读取计数器的值,其它的应用,就看具体的情况了。 - <div align="left">u16 COUN1=0;
' g! U2 T$ F3 v' Y% }6 f1 k - u16 COUN2=0;</div><div align="left">int main(void)+ n3 w' k$ u5 F' R6 z
- {; |8 F4 @1 s* p3 ?: y
- ChipHalInit();8 R* \ J, e! r" x7 h
- ChipOutHalInit();</div><div align="left">while(1)
4 ^4 ~: T' e) _( x - {
- H: G, \$ G" Q6 K* J - COUN1=TIM1->CNT;
( _, J S* l% q# s - COUN2=TIM2->CNT;
8 l! y! |# M; m% w6 f - }</div><div align="left">}</div>
复制代码 # p$ M. ^$ Y& ^/ y* J7 j8 l" ~
2 M3 L- _$ W) `' k. i$ X# x% A) S
+ M3 e# }0 n: J
% F' n1 a. J/ C( L4 \0 a
|