
等精度测量法:定时器1对被测信号计数65536个周期作为闸门时间,在这个闸门时间内定时器2对标准信号进行计数。假定在这个闸门时间内标准信号的计数值为M。则有:65536/fc=M/fb通过这个公式就可以算出被测信号:fc=65536*fb/M。2 w& c6 Y7 Z$ }9 } 本程序利用定时器3产生30KHZ的被测信号。定时器1对被测信号进行65536个周期计数。 定时器4产生60KHZ的标准信号。定时器2对标准信号在定时器1产生的闸门时间内计数。 主程序如下: /**5 X3 H7 s2 r; v6 Y$ [ ****************************************************************************** * @file app.c * @author wangfei' [/ h7 f- @; I" g+ W# B2 H! X * @date 13-April-2012 * @e-mail wfmjj@hotmail.com, }8 T8 i; E8 x; P0 s2 P * @brief Initialize peripherals. *****************************************************************************/ /* Includes ------------------------------------------------------------------*/( L% X0 {( d* k #include "stm32f4xx.h" #include "app.h" #include "bsp.h"( D; _* e4 B1 {# z" J9 O /* Private typedef -----------------------------------------------------------*/" Y+ F; l) z b% b/ } /* Private define ------------------------------------------------------------*/, O1 V, _% \! [* T: _" N /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/# k! r2 e0 @ d2 H# U& k extern uint8_t TimeFlag; extern uint32_t n_Counter; uint16_t Counterh,Counterl; uint8_t Data[5]; /* Private function prototypes -----------------------------------------------*/" I: w: p: R; [0 C1 o; _ /* Private functions ---------------------------------------------------------*//** * @brief This function handles NMI exception. * @param None * @retval None1 A& t& d: t8 {" Y0 L2 H( K. I */ int main(void). K" c$ J$ \0 ?; {, `, w { GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间 Bsp_Init(); while(1) {5 T- y* C: c- l3 x uint8_t i;* C8 x, B# e& P TIM_ITConfig(TIM1,TIM_IT_Trigger,ENABLE); //允许定时器1的触发中断 GPIO_SetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3));9 z- j1 x# O6 |2 B# _ TIM_Cmd(TIM1,ENABLE); //打开定时器1,当检测到TIM1_CH1通道的上升沿后立即触发中断% ?* X2 b6 _: ~* w while(TimeFlag==0); //等待定时器1溢出中断/ b5 J1 s; h- D. X; v TIM1->DIER&=0X0000; //失能定时器1的所有中断7 F- x! i+ i% b+ e GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间( u. P( k& g7 s3 i- O; ] TimeFlag=0; //定时器1溢出标志置0 Counterh=n_Counter>>16; //得到32位数据中的高16位" L! e; J0 N P5 h+ t D ? Counterl=n_Counter; //得到32位数据中的低16位9 @% |5 K' N- { Data[0]=Counterh>>8;0 A6 {( |8 u6 e Data[1]=Counterh;: Q) _; j% i) v& N5 f Data[2]=Counterl>>8;4 q/ v. i) ?( [- z( t" C Data[3]=Counterl;& `: h- {# G6 I, q6 \# v <span style="color: rgb(34, 34, 34); font-family: sans-serif; font-size: 18px; line-height: 27px; background-color: rgb(238, 238, 238); "> for(i=0;iCCMR1|=0X0100; //配置定时器1为外部时钟模式1 TIM1->CCER&=0XFF5F; TIM1->SMCR|=0X0067;4 U8 g9 H/ E( e# W$ J4 L8 k! ?) y- | TIM_ClearFlag(TIM1,(TIM_FLAG_Update|TIM_FLAG_Trigger)); } /** * @brief This function config timer3. * @param None * @retval None4 l& r# i8 ^9 @3 S */2 W; P3 |3 ] Q" A/ @, e8 m void Bsp_TIM3_Config(void)2 I# U; z* c/ q0 a% T& }& E2 z8 _ {3 x6 z! Y; }2 q TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;- w+ @& x* p% \ TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Open TIM3 Clock ) U! _/ W8 O) d, s TIM_TimeBaseStructure.TIM_Prescaler=3; //clk_cnt prescale& O( ^/ v4 V: d9 V TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM3 Count mode TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=21000000/700=30KHZ' y5 N* H W, t TIM_TimeBaseStructure.TIM_ClockDivision=0; & M6 B# L8 c% L/ K, f& } 7 _$ ]0 k% w- ?" z# a% Y" ` ?: d TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);& t' ~9 y3 O+ L/ ]# b; i$ K* G2 v /* PWM1 Mode configuration: TIM3_Ch1 */3 l$ _1 C% o) P0 c% {( v TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode. }9 e7 v4 q$ v TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc1 as output ) E3 m! Y4 [2 W6 e s TIM_OCInitStructure.TIM_Pulse=350; //config TIM3_CCR1 vaule u8 a! o3 q! e: _# ] ~7 z: d TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc1 high level avaliable TIM_OC1Init(TIM3, &TIM_OCInitStructure);( r( f" _" {5 r/ A- F: T/ F( a+ d . ~0 W1 |6 Z+ P: Q* y TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc1 preload $ Y. `$ ?" f |/ o2 F /* PWM1 Mode configuration: TIM3_Ch2 */" I: E" e# F: @3 l TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode2 b9 T, c8 ?5 q! L* d TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output / a, L$ }6 r2 ]/ n TIM_OCInitStructure.TIM_Pulse=200; //config TIM3_CCR2 vaule r' S' [6 b* o) |$ N2 G TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable, ]3 f7 B# k" @ TIM_OC2Init(TIM3, &TIM_OCInitStructure);1 A$ \, e. l2 I: Z7 q+ s9 D, f% F . E1 k$ }) R8 w. S. i9 l0 m TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc2 preload 6 l5 {, I+ B, ^8 h+ g8 w /* PWM1 Mode configuration: TIM3_CH3 */ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output ; {4 R7 C* b, T3 _ TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable TIM_OC3Init(TIM3, &TIM_OCInitStructure);3 |+ c7 w# Y9 S9 _3 e7 S: P. f TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc3 preload # F/ F9 ? C8 [* z# K /* PWM1 Mode configuration: TIM3_CH4 */* t- C9 N# J6 b( x- Z" I TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output . M" o% P2 O# B3 S TIM_OCInitStructure.TIM_Pulse=500; //config TIM3_CCR1 vaule TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable! g# T8 C2 J/ N+ ]+ z TIM_OC4Init(TIM3, &TIM_OCInitStructure); 0 q' q! U: y+ j) P TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc4 preload u3 v' ], c% r% ~; M+ [ TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM3 enable counter */+ V. z6 l" q. m9 |$ h- a TIM_Cmd(TIM3, ENABLE);, q, M! V' V$ D1 O. e }" g" [* G9 N: M |
* @brief This function config usart3.+ {$ f+ i9 z9 l6 I
* @param None% `4 o( q- A8 K
* @retval None
*/: r/ {$ \! w, M$ {8 b
void Bsp_USART3_Config(void)3 p5 \. [( g( ^9 z5 _
{
USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //turn on usart3 clock, M) N( b q! w# e
) @+ p, M4 S# j4 `. A1 q1 F
USART_InitStructure.USART_BaudRate =115200 ; //波特率设置, S1 `( P% E. s8 G6 _6 P( T; K' l# J
USART_InitStructure.USART_WordLength = USART_WordLength_8b;% c# n% H. Z6 B5 D4 H
USART_InitStructure.USART_StopBits = USART_StopBits_1;3 t5 s3 \1 X' f$ H5 N
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);( F3 w( `7 W8 u* w' O
9 _4 }- G) Q* R' H7 y& B
//USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);% Y* x3 F3 r- _4 M5 M# m
USART_Cmd(USART3,ENABLE);
USART_ClearFlag(USART3, USART_FLAG_TC); //清除发送完成标志位
}2 E5 g9 K$ z l' A
/**6 Q6 ?3 }3 J8 N, t+ {/ ~
* @brief This function config nvic.
* @param None
* @retval None: @( E4 e' J. b" w; B' S% a
*/: l2 Z- j8 _; l+ X
void Bsp_NVIC_Config(void)
{0 A$ _# k s- ?/ N
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);$ b! U0 }" E9 C1 w# K
NVIC_InitStructure.NVIC_IRQChannel=TIM1_TRG_COM_TIM11_IRQn;! S+ H0 _6 J3 F) w0 b3 F; ^
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;7 c4 K* z A, W) N, K J ?8 a
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);8 F+ V* n1 `/ V6 w- ^4 l9 X& Y
/ u4 Z3 C( A5 X5 Z
NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_TIM10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);6 R- B" N0 K" m
}: }4 x, \8 P2 s! k8 o, B* A# y; w! M
/**$ b4 W+ ?" ~ g) Q) j
* @brief This function config timer2.
* @param None
* @retval None# P5 E! r# ^& l G, {
*/
void Bsp_TIM2_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开定时器2的时钟
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Prescaler=0; 4 D8 D% g8 \" }1 s7 u- Y. i* {
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //定时器2向上计数
TIM_TimeBaseStructure.TIM_Period=0xffff; 2 S( N: E! P" J7 d# J6 Y
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM2->ARR|=0XFFFFFFFF; //配置1 c7 X2 f: L/ E J. W
//定时器2外部时钟模式1的配置( M& C2 n E m4 U0 ~8 [* G' m6 a
TIM2->CCMR1|=0X0001; 7 T3 T5 h8 }: L4 ~, W
TIM2->CCER&=0XFFF5;
TIM2->SMCR|=0X0057;8 I1 h# g7 n- z- t& [' l
( w0 t U$ S! x. S$ q/ S
TIM_ClearFlag(TIM2,TIM_FLAG_Update); //初始化时必须将溢出中断清0必须在开溢出中断之前。# Q: h" E9 m- {% q) K% |8 O% y
}5 M+ r ?1 J! H& S
/**4 L( f5 n4 ^% }2 n5 c8 P: l+ U
* @brief This function config timer4.3 g+ ^0 M- m9 Y7 u
* @param None
* @retval None9 a5 E* S8 l5 J7 s' m
*/
void Bsp_TIM4_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;/ e) J6 ^) n( h! U
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //turn on TIM4 clock TIM_TimeBaseStructure.TIM_Prescaler=1; //Fck_cnt=84MHZ/2=42MHZ
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM3 Count mode( Y; Z5 o- \$ S
TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=42000/700=60KHZ
TIM_TimeBaseStructure.TIM_ClockDivision=0; 3 m; k, k# S z; r4 p: }$ g
- O$ G5 Y# w$ M( f( u! }) {. w
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
% [4 t9 I( w+ T* z! ^4 b
/* PWM1 Mode configuration: TIM4_Ch1 */1 _) D& g# k0 Y! R) i2 N9 Y
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc1 as output 0 \2 L) L9 T) I; q9 v$ K, ~
TIM_OCInitStructure.TIM_Pulse=350; //config TIM3_CCR1 vaule! T' D! s2 l" `# B$ C# M
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc1 high level avaliable
TIM_OC1Init(TIM4, &TIM_OCInitStructure);% _. o8 x6 V2 R/ r3 o( W% p
7 r0 ]* q7 y" F9 q- y
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc1 preload & d$ h. p/ G9 G' p1 _6 [
/* PWM1 Mode configuration: TIM4_Ch2 */9 X/ c. q8 ~5 u( K' y9 E
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode2 u7 L, b& k- n( M+ r7 \* i
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output # T& y) H2 m3 F8 X& ~! A6 @" S& M
TIM_OCInitStructure.TIM_Pulse=500; //config TIM3_CCR2 vaule
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable
TIM_OC2Init(TIM4, &TIM_OCInitStructure);
/ T2 v+ A! p) Q+ a. `2 O( `$ X
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc2 preload
: g; c1 o+ y/ s- }* x3 e; U
/* PWM1 Mode configuration: TIM4_CH3 */
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output 2 c% J# o/ o6 B7 F# o/ @
TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule& v& `/ m# b# D' b( D% Y
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable
TIM_OC3Init(TIM4, &TIM_OCInitStructure);. y+ c3 m* q% P
/ E( w2 Z; P* `4 B+ S3 w: j2 a
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc3 preload & G& `# p9 [) Q& c' H8 t
/* PWM1 Mode configuration: TIM4_CH4 *// p1 X* N, z* Y$ e. H( V/ v3 @( [
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode6 J* _7 X- k/ s2 H( _3 O
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output / ^1 B9 p, {3 N' n4 Z
TIM_OCInitStructure.TIM_Pulse=600; //config TIM3_CCR1 vaule5 A) y# ~# a8 s3 \
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable
TIM_OC4Init(TIM4, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc4 preload
TIM_ARRPreloadConfig(TIM4, ENABLE); /* TIM3 enable counter */
TIM_Cmd(TIM4, ENABLE);. r0 {; |- c. Y6 i. Z2 O, w
}
定时器1触发中断程序如下:
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{: l P# x$ L4 W" s+ n
if(TIM_GetITStatus(TIM1,TIM_IT_Trigger)==SET) //检查是否为触发中断( a( U- Y4 P. J" H V0 x
{
TIM1->DIER&=0XFFBF; //清除定时器1的触发中断* A! N! ~6 V* f9 g5 q0 u( v
TIM1->DIER|=0X0001; //使能定时器1的溢出中断8 X! @/ c' S0 z1 J E6 z) J
TIM2->CR1|=0X0001; //打开定时器2使其对标准信号开始计数% C& s1 B% Q/ Q. x4 L5 S7 o
TIM1->SR&=0XFFBF; //在退出中断之前必须清除其中断标志位- T" G9 S; W5 b4 p6 D8 p& R7 m
}/ l0 f' ^6 g! W& @$ ^
}
定时器1溢出中断如下:5 h V' z B, Z4 P5 t$ X- |/ ?
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //检查定时器1溢出标志位是否置1
{# a3 J; t9 n. H
n_Counter=TIM2->CNT; //读出计数器2的值' S& e. ^, E8 u* s- Y5 S
TIM1->CR1&=0XFFFE; //关闭定时器16 q, J* d( U w' h
TIM2->CR1&=0XFFFE; //关闭定时器2! x7 _' I7 Y/ M" m+ }
TIM2->CNT&=0X0000; //清除计数器2计数寄存器的值5 h8 w! C8 E' R2 F
TimeFlag=1; //1s标志位置16 h& q7 R- C5 a! u
TIM1->SR&=0XFFFE; //退出定时器1溢出中断之前,必须清除定时器1的溢出标志位; ~& }+ X8 x3 c+ S* J/ \( `0 F
}; |) T+ j! Y: W9 F2 | Q3 {& k( o
}
</i>
7 d! M7 h+ x, H0 k. j& O/ n