
本例程出自STM32MED1开发板附带光盘,其工程目录路径为:\Code Package\Peripheral Devices\06 TIM\0602_Chaining。 , U; B4 D3 K% v% ~# j 本例程是使用TIM3作为TIM4的预分频器。下面代码出自timer.c文件。# Z, [* b C# ?! b void TIM3_4_ChainConfig(u16 Period1, u16 Period2)- H! C6 I4 Q' D ~: C {* j$ X" j- `' ]0 W TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;- i; q6 K9 |# k0 C9 r# o; d NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3| RCC_APB1Periph_TIM4, ENABLE); // 1) $ P8 f) X1 N4 t, O7 F TIM_TimeBaseStructure.TIM_Period = Period1; // 2)* P: s- N& C, p7 o, a0 I O TIM_TimeBaseStructure.TIM_Prescaler = (u16)(SystemCoreClock / 1000) - 1; // 3)5 ^) k% W, R/ H3 _- t2 P TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 4) TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);0 n* h; J0 q% [6 R TIM_TimeBaseStructure.TIM_Period = Period2; // 5)6 }: J( ?7 o0 l# R. v, [. V1 W TIM_TimeBaseStructure.TIM_Prescaler = 0;/ B& f: f0 X( V& V* K) s. f TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 8 C5 z8 X8 o) |) i5 |* y! D; O TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); // 6) TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_External1); // 7). F( m" T7 i4 `' ~ h5 X TIM_SelectInputTrigger(TIM4, TIM_TS_ITR2); // 8) % M; c- e% G5 ~) Z) ~- n TIM_ITConfig(TIM4, TIM_IT_Trigger | TIM_IT_Update, ENABLE); // 9) TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Global); // 10) 1 X( v E8 ]: D2 ] // (11 NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;+ _4 [8 X9 p1 N n* U& S NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;) b) F0 n9 o" ?+ m5 g NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;( a/ h5 q) b0 l: i6 P; D3 r7 a. q NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;5 [' m" w ^: s+ t* n3 N# n NVIC_Init(&NVIC_InitStructure); // 11)" x; n) J' [3 o& a" g TIM_Cmd(TIM4, ENABLE); // 12)1 _8 @* p1 |) M* }) l TIM_Cmd(TIM3, ENABLE); // 13)" j' L. @5 f$ n }' |0 \$ o* ?0 M: [( Y. P ! J# X' z, F( @ d: a6 m 在对定时器的寄存器进行配置前先应通过调用函数RCC_APB1PeriphClockCmd()使能相应定时器的时钟,如代码行1)。代码行2)是设置TIM3的周期,即设置寄存器TIM3_ARR的值。代码行3)是设置TIM3的预分频器值。由于TIM3的从模式控制器被禁止,TIM3预分频器的时钟由内部时钟CK_INT提供。全局变量SystemCoreClock定义于system_stm32f10x.c,如下代码所示:3 |# X- M% r9 t$ `* Z# q# j uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz;' e7 L& N2 I- W8 J) N% S( d+ y# E3 M 由此可见,代码行3)将预分频器值设为SystemCoreClock / 2000 – 1,则预分频器的输出时钟CK_CNT=1000Hz,也就是说TIM3的计数器每1ms计数一次。代码行4)将计数器模式设置为向上计数模式。也就是说定时器使能后,计数器将从0开始计数,每1ms计数一次,计数到TIM3_ARR中值时产生更新事件,计数器将重新从0开始计数。代码行5)是设置TIM4计数器的周期,也就是寄存器TIM4_ARR的值。TIM4的预分频器值设为0,计数模式同样是设为向上计数。代码行6)将TIM3的更新事件设为其触发输出源,代码行8)则将TIM3的触发输出选为TIM4的触发输入,即每当TIM3产生一个更新事件,TIM4就将收到一个触发信号。代码行7)是选择TIM4的从模式:外部时钟源模式1,即将TIM4的触发输入脉冲作为TIM4计数器的时钟。这样一来,TIM3将每Period1 ms产生一个更新事件,此时TIM4产生一个触发事件,TIM4的计数器将计数一次,经过(Period1*Period2) ms的时间后,TIM4将产生一个更新事件。代码行9)是开启TIM4的触发及更新中断。代码行10)是指仅当TIM4计数器上溢或下溢时更新事件。代码段11)是配置并开启TIM4的中断通道。代码行12)及代码行13)分别开启TIM4及TIM3。4 `4 G0 Y; r0 ]" O7 j T 6 z3 A: e) Z3 l9 I! ~ 下面是文件stm32f10x_it.c中TIM4的中断处理代码: void TIM4_IRQHandler(void)% w ]# r: A! C- M- y' ~* g { if (TIM_GetITStatus(TIM4, TIM_IT_Trigger) != RESET) // 1) { LED_Toggle(LED1); TIM_ClearITPendingBit(TIM4, TIM_IT_Trigger); } if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) // 2)" `5 O# P- \7 |0 z9 \$ f { LED_Toggle(LED2); TIM_ClearITPendingBit(TIM4, TIM_IT_Update);) o. H& T; {4 G } } 代码行1)是判断TIM4是否产生触发中断,若产生了触发中断,则反转开发板上LED1的状态,而后清除该中断的挂起状态位。同理,代码行2)是判断TIM4是否产生更新中断,若是则反转LED2的状态,然后清除中断挂起位。* p) k0 k1 \# i. o+ M% H ]( |" ?4 U7 c) x- E9 ?, D9 I7 T) ] 函数main()位于main.c文件中: int main(void) { /* Code here configures LEDs on board */1 T1 Q' K, F0 B( k) @ TIM3_4_ChainConfig(1000, 3); // 1), Y* k0 A3 z( r) i# f . _, W3 s4 m: Q5 H9 i while (1)& |# X3 M. ?/ n/ ?* q# y) T {! d3 w8 h2 t8 v( \' a/ m6 r /* Waiting for interrupts */5 I3 I. i y3 M+ K3 z0 X } }* t/ t: f2 e" S' z9 l& t1 |1 P+ H. I 代码行1)将TIM3的周期设为1000,也就是每秒TIM3将产生一个更新事件,同时TIM4产生一个触发事件,由于TIM4的触发中断已开启,其对应的中断处理代码将得以执行,即LED1的状态将翻转。TIM4的周期设为3,也就是说3秒后,TIM4将产生更新中断,LED2的状态将翻转。; g7 ^. E) h! V8 u, {! [7 a 2 I |" {, d- _ ~9 k/ e4 F" B 了解更多,请点击访问我们的首页 |