
等精度测量法:定时器1对被测信号计数65536个周期作为闸门时间,在这个闸门时间内定时器2对标准信号进行计数。假定在这个闸门时间内标准信号的计数值为M。则有:65536/fc=M/fb通过这个公式就可以算出被测信号:fc=65536*fb/M。 本程序利用定时器3产生30KHZ的被测信号。定时器1对被测信号进行65536个周期计数。) {! w0 O& s' a; ] X( {/ t3 M0 V0 v 定时器4产生60KHZ的标准信号。定时器2对标准信号在定时器1产生的闸门时间内计数。% N! Y0 H s: ], X 主程序如下:2 t) d' k8 ^, m; I* b6 m /**0 }5 M9 e: ^1 E. B: R. l ****************************************************************************** * @file app.c * T/ j$ C1 N# a }3 ^ * @author wangfei/ D6 ?" \+ `. i5 f# G ` * @date 13-April-2012: k3 x5 _/ E% ]8 Q2 ]( U3 G * @e-mail wfmjj@hotmail.com$ ^3 H3 {+ k$ c' ^2 u2 P * @brief Initialize peripherals.) }' F" x) o' M) Z *****************************************************************************/3 i" Y4 Q- i3 n4 R8 O& D) m5 ]+ V) I( S /* Includes ------------------------------------------------------------------*/& I3 Q9 g# c. K5 U #include "stm32f4xx.h" #include "app.h" #include "bsp.h". L* a: {& }( i( o7 t. v1 T: _ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/# [4 h% S2 i5 f T* m# K8 u /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ extern uint8_t TimeFlag;* @/ k3 P# ]+ x/ q# j3 B extern uint32_t n_Counter;: y3 X0 b) R" a3 D( R8 ] uint16_t Counterh,Counterl; uint8_t Data[5]; /* Private function prototypes -----------------------------------------------*// V" y, g) E# D) p0 V( [ /* Private functions ---------------------------------------------------------*//**& s* K/ Y; U& o * @brief This function handles NMI exception.# P4 ^1 f$ @& @9 O; ~$ ?9 i0 m * @param None1 }1 ^- d3 a- }5 m! {$ H1 Z * @retval None */. F3 ]+ x7 K+ A. H* f$ F' ^ int main(void) {6 H* O; a6 [/ S: o$ x. |( ?7 I$ W6 m0 B GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间6 c" W4 f o1 W6 R' P$ e u Bsp_Init(); while(1)% j2 D. w) j9 j0 S- [! A7 Q {9 u1 w" r3 }3 r: n- A uint8_t i; TIM_ITConfig(TIM1,TIM_IT_Trigger,ENABLE); //允许定时器1的触发中断, S2 k, ] J: x! i$ _ GPIO_SetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); TIM_Cmd(TIM1,ENABLE); //打开定时器1,当检测到TIM1_CH1通道的上升沿后立即触发中断 while(TimeFlag==0); //等待定时器1溢出中断& B. ]" d" |! l$ [" | TIM1->DIER&=0X0000; //失能定时器1的所有中断 GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间; O. h6 t8 F+ p TimeFlag=0; //定时器1溢出标志置00 i4 N# j$ ]- o( | Counterh=n_Counter>>16; //得到32位数据中的高16位5 f1 V0 n8 A. `; |1 z Counterl=n_Counter; //得到32位数据中的低16位 Data[0]=Counterh>>8;4 b7 K# O5 e3 _ Data[1]=Counterh; Data[2]=Counterl>>8; Data[3]=Counterl; <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. s7 l f6 V: H) T TIM1->CCER&=0XFF5F;0 Q& p$ u4 T! E9 s* C TIM1->SMCR|=0X0067;7 r9 R$ i/ _* f0 B; h9 z. _ TIM_ClearFlag(TIM1,(TIM_FLAG_Update|TIM_FLAG_Trigger));; K, ?$ i% p" P }0 d; C9 Z6 _3 p$ L. T3 R /**+ Y8 i* a$ @% R5 @, q0 Y7 L- L * @brief This function config timer3. * @param None * @retval None */ void Bsp_TIM3_Config(void). j; L/ S' q. z' U% B( S {: d2 K0 J$ I0 i# g- }( i TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;2 @9 V1 B$ ~" F0 e G8 ]/ } TIM_OCInitTypeDef TIM_OCInitStructure;1 \+ t# P5 C5 } RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Open TIM3 Clock TIM_TimeBaseStructure.TIM_Prescaler=3; //clk_cnt prescale TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM3 Count mode TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=21000000/700=30KHZ TIM_TimeBaseStructure.TIM_ClockDivision=0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: TIM3_Ch1 */1 u1 N0 G3 @! C# `8 i TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode6 Z$ N3 [+ V9 V- _/ ^. _ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc1 as output TIM_OCInitStructure.TIM_Pulse=350; //config TIM3_CCR1 vaule TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc1 high level avaliable TIM_OC1Init(TIM3, &TIM_OCInitStructure);" w0 C; S- c# M& S TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc1 preload & {+ ~9 @$ J" Z" O4 x8 ~; l . _/ V, h! f% ?. O1 U! p /* PWM1 Mode configuration: TIM3_Ch2 */, G6 @% \1 R6 T8 _ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode7 Q) G$ C# E6 K TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output TIM_OCInitStructure.TIM_Pulse=200; //config TIM3_CCR2 vaule# B6 A5 e) O. ]2 j, t: D TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable TIM_OC2Init(TIM3, &TIM_OCInitStructure);/ _4 n- K6 N: I/ [ 1 P- j2 c' d# a5 |( i* ~( Y- L TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc2 preload 6 \ N/ _3 V- m' K! T /* PWM1 Mode configuration: TIM3_CH3 */2 T0 `- t# L% A) T+ b* f TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode9 }+ X7 O9 L' g TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output 7 B0 e, z1 ?3 F6 ]0 N) @+ t, X TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule. D% f9 v) q8 y8 U6 s" y TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable TIM_OC3Init(TIM3, &TIM_OCInitStructure);! T) p4 S! a- z8 \% j 6 u) f3 M5 x# V$ f! i+ i TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc3 preload , z6 o/ l: ?) G( J3 ~4 I) T r /* PWM1 Mode configuration: TIM3_CH4 */& y, D1 j: ]/ E4 O TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output 6 [ F; h& N$ m- \/ e TIM_OCInitStructure.TIM_Pulse=500; //config TIM3_CCR1 vaule TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable TIM_OC4Init(TIM3, &TIM_OCInitStructure);% X0 z) `( K) c* `; N# t+ Z& o $ u& z) s& ?$ ~. {# ~, }, W& T TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc4 preload 3 ?. d9 z& ]4 y, g o TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE);9 ~. O: d7 C6 F/ p! V& W' C }" @* A( J" x: w9 w 6 I: E+ q# L. X |
* @brief This function config usart3." g) j' [+ {/ l: _
* @param None
* @retval None* ^: M: k! B- J& f& E* t" x2 V
*/7 Q& E- C3 |5 H
void Bsp_USART3_Config(void)8 V* x! {- J6 N& x) W) W
{
USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //turn on usart3 clock
USART_InitStructure.USART_BaudRate =115200 ; //波特率设置5 V8 y) B( e" V
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;1 ^1 S: x$ E7 P% g& t" g
USART_InitStructure.USART_Parity = USART_Parity_No;$ f( j& y, M! ~
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; ' r% [& P9 W" Y. \) \
USART_Init(USART3, &USART_InitStructure);
//USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
USART_Cmd(USART3,ENABLE);
USART_ClearFlag(USART3, USART_FLAG_TC); //清除发送完成标志位) _3 E8 O4 `" U0 S' w4 S" I+ }
}
/**
* @brief This function config nvic.$ g# Y2 p# u+ ^
* @param None: a5 l9 H5 r ]5 }% a
* @retval None
*/
void Bsp_NVIC_Config(void)
{6 D4 y' n1 w& Z
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel=TIM1_TRG_COM_TIM11_IRQn;# j5 e) P3 u! i( g( a7 `
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;6 I' ]6 K, ?( S* h
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
5 A0 \8 q' ]9 l% M" p& J
NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_TIM10_IRQn;. M4 q& p6 H$ K
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;2 M' X+ |% h+ w6 z
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;9 m* Y9 B: F! E- j# z
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);, I+ w' i. T2 E) V- s8 \1 h
}3 o% Z3 p1 V" R7 a: @4 o
/**1 ]! S M+ m: |
* @brief This function config timer2.
* @param None
* @retval None
*/- }& h$ A$ e0 i- Q$ V' @
void Bsp_TIM2_Config(void)0 ~. z- f F0 A% p
{7 |9 i$ e" ^) _' u
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开定时器2的时钟$ n1 Z3 R# t6 V5 u$ l
TIM_DeInit(TIM2);6 x, p! ^+ A. ?! h) B
2 Y$ T9 i$ s6 J3 g3 Y
TIM_TimeBaseStructure.TIM_Prescaler=0; + |; f1 P# D' e' T9 n: N
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //定时器2向上计数
TIM_TimeBaseStructure.TIM_Period=0xffff;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;" v8 l4 L' U% |& D
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);( L- X: y: J. _# |% X
TIM2->ARR|=0XFFFFFFFF; //配置
//定时器2外部时钟模式1的配置
TIM2->CCMR1|=0X0001;
TIM2->CCER&=0XFFF5;
TIM2->SMCR|=0X0057;
; X; q" F3 f4 ]- R l9 P! Y
TIM_ClearFlag(TIM2,TIM_FLAG_Update); //初始化时必须将溢出中断清0必须在开溢出中断之前。+ J, ^; |' W% o3 Q6 Y; A
}
/**
* @brief This function config timer4.
* @param None! x/ v$ A3 d$ p9 n) ?
* @retval None
*/
void Bsp_TIM4_Config(void)
{1 a) ^: i" x. B. X1 \$ g
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;8 r: s$ x! H, L9 d W7 D2 ?
' k- ]3 W) `& @/ n" c1 b# u$ ]& x' X
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$ O/ Z8 L& ?8 E3 C+ [ C# l8 n2 Z
TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=42000/700=60KHZ, i- Q* W% P0 {, w' W8 u( U" J3 B
TIM_TimeBaseStructure.TIM_ClockDivision=0; ) x7 `" u& g; l7 Z
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
) h! p7 }) u- h$ a) ^% E4 t
/* PWM1 Mode configuration: TIM4_Ch1 */0 N' C4 R, F5 w I- V4 V
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc1 as output
TIM_OCInitStructure.TIM_Pulse=350; //config TIM3_CCR1 vaule
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc1 high level avaliable
TIM_OC1Init(TIM4, &TIM_OCInitStructure);% o% {& a9 [ G, n1 T+ T
4 w1 s! C, u. K6 a t( r: A
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc1 preload - i% k q/ `! A; W
( y& u, P p! x7 n& B
/* PWM1 Mode configuration: TIM4_Ch2 */0 l7 X+ ^0 a; `6 l( t0 T* _
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output & `* g7 U# ?5 M0 ^) @
TIM_OCInitStructure.TIM_Pulse=500; //config TIM3_CCR2 vaule6 Y4 V0 _ V* z M
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable
TIM_OC2Init(TIM4, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc2 preload
/* PWM1 Mode configuration: TIM4_CH3 */
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode J5 a4 ]/ [2 e+ h. t. |
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output & h! Y2 B6 {9 ^& k/ c) s% g
TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
T# K5 d! }" w; _8 h O
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc3 preload / f! Y+ S" e7 D1 I5 i( d& Q
/* PWM1 Mode configuration: TIM4_CH4 */- F2 n; _5 V* x! M, ~! y ~
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output
TIM_OCInitStructure.TIM_Pulse=600; //config TIM3_CCR1 vaule! f9 G9 ^# c+ }! L, s: u7 B
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable
TIM_OC4Init(TIM4, &TIM_OCInitStructure);
& }& @; I: G I; \# v w
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc4 preload
9 V4 v1 @; n7 b% I( |
TIM_ARRPreloadConfig(TIM4, ENABLE); /* TIM3 enable counter */1 b B o4 K2 n& E$ V
TIM_Cmd(TIM4, ENABLE);6 b% J6 N4 ~. y% \/ q4 z4 b
# s8 S. X& \. f Y4 C) g4 b
}
定时器1触发中断程序如下:
void TIM1_TRG_COM_TIM11_IRQHandler(void)- W. T u; W0 S' g
{2 a6 G W; b1 e9 X
if(TIM_GetITStatus(TIM1,TIM_IT_Trigger)==SET) //检查是否为触发中断7 J E; q4 v+ |; N* d5 ?
{# S( G, Q; i8 `% J5 d$ ]1 b
TIM1->DIER&=0XFFBF; //清除定时器1的触发中断+ O8 E$ z* m8 P2 @$ G+ M C
TIM1->DIER|=0X0001; //使能定时器1的溢出中断# q, d1 d0 {2 W, ?2 _8 t
TIM2->CR1|=0X0001; //打开定时器2使其对标准信号开始计数' t+ C3 f* R* _9 j# r
TIM1->SR&=0XFFBF; //在退出中断之前必须清除其中断标志位
}; \0 o, _3 }5 J- ]; V2 {
}- c" @3 o; o. @0 c' i( C! k1 B: w# f
定时器1溢出中断如下:' v1 G6 _; m6 P) |: W: {
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //检查定时器1溢出标志位是否置1
{ P# g! ]) p9 i
n_Counter=TIM2->CNT; //读出计数器2的值
TIM1->CR1&=0XFFFE; //关闭定时器1& |" D. O8 r3 h* r
TIM2->CR1&=0XFFFE; //关闭定时器2
TIM2->CNT&=0X0000; //清除计数器2计数寄存器的值& P! P6 ?- s- R& c4 ?
TimeFlag=1; //1s标志位置1" v1 S) @7 b0 T3 F! a
TIM1->SR&=0XFFFE; //退出定时器1溢出中断之前,必须清除定时器1的溢出标志位
}3 u, F! m U4 S2 p" s9 f. B$ Q
}
</i>
; u8 Y3 H& K3 b- ]8 \
; n: M8 x( S0 c3 _# x
1 N0 t9 S) s: \