等精度测量法:定时器1对被测信号计数65536个周期作为闸门时间,在这个闸门时间内定时器2对标准信号进行计数。假定在这个闸门时间内标准信号的计数值为M。则有:65536/fc=M/fb通过这个公式就可以算出被测信号:fc=65536*fb/M。 本程序利用定时器3产生30KHZ的被测信号。定时器1对被测信号进行65536个周期计数。7 u. s. q( ~2 B. { 定时器4产生60KHZ的标准信号。定时器2对标准信号在定时器1产生的闸门时间内计数。' E- f' k$ @. l8 f; ~ ? 主程序如下:0 H. B- u4 ~$ e! J2 V7 G! z( I: e /** ******************************************************************************% R* d" E, _2 J' ]/ l9 @ * @file app.c 1 c, O) O; D, E- F2 M' a * @author wangfei5 N0 Q+ w: L& j; C * @date 13-April-2012( |& I1 M B8 a( \ * @e-mail wfmjj@hotmail.com; q. ]4 k( Y, u' T a, r9 _1 E * @brief Initialize peripherals. *****************************************************************************/ /* Includes ------------------------------------------------------------------*/! l& F$ X% ^, z" e #include "stm32f4xx.h"5 e: X/ p0 T5 N9 l p6 d _- @ #include "app.h" #include "bsp.h"% r2 n. `" a: n5 I2 w' x /* Private typedef -----------------------------------------------------------*// v! p1 [3 ~! N1 u4 w9 a+ g1 M, F /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/$ n/ ?4 x3 j; E7 K/ X extern uint8_t TimeFlag;" J+ o! a: R- F7 D1 M" S extern uint32_t n_Counter; uint16_t Counterh,Counterl; [4 R4 q+ ^8 b6 T uint8_t Data[5]; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*//** * @brief This function handles NMI exception. * @param None' x, _+ O5 {8 j/ }9 ]5 i! Y9 V- S * @retval None */ int main(void)% U+ F& Q) K. h1 _8 v {/ F; Y- ]+ v- u. C- e- j! z GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间) {/ p* p% f7 A9 F- M Bsp_Init(); while(1) { uint8_t i;& ^/ m% x+ R3 X5 J) {% h) u TIM_ITConfig(TIM1,TIM_IT_Trigger,ENABLE); //允许定时器1的触发中断: C6 W5 G9 F: }5 f! t, y GPIO_SetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3));: V) r; _, [( F; j$ Y3 ` TIM_Cmd(TIM1,ENABLE); //打开定时器1,当检测到TIM1_CH1通道的上升沿后立即触发中断 while(TimeFlag==0); //等待定时器1溢出中断 TIM1->DIER&=0X0000; //失能定时器1的所有中断. f, ~6 K! w; E7 k GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间9 @! r: P* j2 Y& d1 y& n' _) p# ~ TimeFlag=0; //定时器1溢出标志置0 Counterh=n_Counter>>16; //得到32位数据中的高16位 Counterl=n_Counter; //得到32位数据中的低16位 Data[0]=Counterh>>8; Data[1]=Counterh; Data[2]=Counterl>>8;; T$ x! D% d3 v+ i$ U& [1 ] 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 TIM1->CCER&=0XFF5F; TIM1->SMCR|=0X0067; TIM_ClearFlag(TIM1,(TIM_FLAG_Update|TIM_FLAG_Trigger)); }& s. _( K. S' }) {4 ? /**/ \! D1 k; K9 y( H5 _ * @brief This function config timer3. * @param None * @retval None */9 U2 j8 y& o8 [; o) s void Bsp_TIM3_Config(void) {6 x0 S8 D4 o( h8 R TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure;/ l. x8 ~9 p: v' ^2 Q- p$ { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Open TIM3 Clock + r1 d& A% w) A; Q# p6 g' A& \ TIM_TimeBaseStructure.TIM_Prescaler=3; //clk_cnt prescale8 u/ W; l0 k$ }& Q2 C# q4 j5 B! R8 J TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM3 Count mode8 W* a5 A& u# v' f7 U' M 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 */ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc1 as output 2 r' I( w: U( a- b" a TIM_OCInitStructure.TIM_Pulse=350; //config TIM3_CCR1 vaule7 b- M2 g4 J6 i- y, _" ? TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc1 high level avaliable TIM_OC1Init(TIM3, &TIM_OCInitStructure);* j# D' `8 t2 q9 k3 w2 ~ 8 Q K4 t( w/ w/ a TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc1 preload ' l! i1 a) [0 {3 e# O$ i /* PWM1 Mode configuration: TIM3_Ch2 */ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode( ^! k Q: k" l$ z TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output TIM_OCInitStructure.TIM_Pulse=200; //config TIM3_CCR2 vaule TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable4 Y) {7 Q% e. c! V& W, N7 g' S; S) Q TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc2 preload /* PWM1 Mode configuration: TIM3_CH3 */+ l1 a9 [: {$ z; y8 u TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable, z9 M' }1 W9 E4 y- N TIM_OC3Init(TIM3, &TIM_OCInitStructure);1 j* D# t* E# z+ D ) ~( S2 o) z5 \+ g+ V TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc3 preload /* PWM1 Mode configuration: TIM3_CH4 */5 Y. |; L! R0 M5 G9 ] 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=500; //config TIM3_CCR1 vaule( s* ]+ \, b; c2 w* S: U3 ` TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable TIM_OC4Init(TIM3, &TIM_OCInitStructure);+ ?1 ]% |* C1 H1 ?; h/ [! g2 z - R8 B$ Q7 E1 o; q! v+ h8 j TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc4 preload ! G8 E# I& k4 q0 k1 X3 t TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE);, s2 b3 G# D8 a! Z }: D( _4 I/ H2 S! l; p* A9 G |
基于STM32F407和Cubemx的ADC采集+DMA传输实现简易示波器经验分享
STM32固件库分享,超全系列整理
基于STM32F407的DMA采样+FFT时域经验分享
基于STM32F407中的RNG获取随机数经验分享
【中文文档】AN3965_STM32F40x和STM32F41x基于串口的IAP
STM32F4-DISC 实现USB主机(U盘)和USB设备(虚拟串口)自动切换
【银杏科技ARM+FPGA双核心应用】STM32H7系列10——ADC
STM32F4中文用户手册
【银杏科技ARM+FPGA双核心应用】STM32H7系列57——MDK_FLM
【STM32图书分享之九】—《STM32F 32位ARM微控制器应用设计与实践》
* @brief This function config usart3.! i) z$ G3 ]2 R; o
* @param None3 t- t) e) z1 f4 j% S. E3 l; X+ q0 w
* @retval None6 g8 \+ O( T) [7 ]) z
*/5 v5 {$ B% K) }
void Bsp_USART3_Config(void)
{
USART_InitTypeDef USART_InitStructure;
$ \8 a7 U: N E" @/ F8 a# r( o
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //turn on usart3 clock" A) Z) q1 q) V" a0 t
N( w; P2 c& [
USART_InitStructure.USART_BaudRate =115200 ; //波特率设置# O7 y3 g1 ` x! f) Q8 n
USART_InitStructure.USART_WordLength = USART_WordLength_8b;+ w& \9 K& U6 L# m. n
USART_InitStructure.USART_StopBits = USART_StopBits_1;9 d L9 K4 o) B2 f, E8 x! q
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;' {1 @# x0 u& v, t, R+ S0 \
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; % F& }8 j& n" Y" M/ z+ n
USART_Init(USART3, &USART_InitStructure);& F6 V+ j4 i5 W1 Q' {! L3 r
//USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
USART_Cmd(USART3,ENABLE);
USART_ClearFlag(USART3, USART_FLAG_TC); //清除发送完成标志位
}
/**
* @brief This function config nvic.) g; G& e: r$ r: O4 A7 ?
* @param None8 a3 B% h+ U) t3 C- \. e0 k
* @retval None
*/
void Bsp_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);6 N" c/ G& n4 `+ O( Y
" E1 q9 w2 ?" ^5 w
NVIC_InitStructure.NVIC_IRQChannel=TIM1_TRG_COM_TIM11_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);4 ~2 `, p% ]) n4 m5 P/ p
NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_TIM10_IRQn;9 x8 v( i( | p* t# Q
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;" H' h4 c- q3 `1 p! w0 ~- w
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;" A4 j& [9 s1 B, l2 E
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);4 V6 C! k4 s# p
}8 W/ h" Y7 X3 g2 X
/**$ _( y/ \4 v5 m7 r" E
* @brief This function config timer2.6 \/ P+ k" u7 V9 F- d6 f$ w7 t
* @param None6 I8 P G' g. r% O
* @retval None0 ]3 w0 r. h0 c- f) p7 H7 C
*/
void Bsp_TIM2_Config(void)
{; J% @8 l# T" @! X0 b( _1 a
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;6 s% f' T3 G3 c3 I
6 n. t; t: L! b1 `& k
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开定时器2的时钟
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Prescaler=0; % E: F# H q3 w/ h% e! l! [# }5 N
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //定时器2向上计数
TIM_TimeBaseStructure.TIM_Period=0xffff; ; V+ |+ u, R6 I
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);& }3 ~: B. X( m" y$ T) e8 Y4 ~5 k& u
C* c# j* R0 d% h+ X# Z. S0 C8 ^- G
TIM2->ARR|=0XFFFFFFFF; //配置
//定时器2外部时钟模式1的配置* f: ^* M) b2 F/ H' Q+ I8 d7 i$ u
TIM2->CCMR1|=0X0001; : |( ?. m0 d4 r) `1 Q5 E
TIM2->CCER&=0XFFF5;
TIM2->SMCR|=0X0057;# H9 O. M4 N+ k0 w' z
TIM_ClearFlag(TIM2,TIM_FLAG_Update); //初始化时必须将溢出中断清0必须在开溢出中断之前。5 `" ?3 q; M- f
}( z; N+ c# J9 N6 t
/**
* @brief This function config timer4.. X5 g: w9 S% R$ x0 B
* @param None0 p& K( o$ K5 \( e$ @: J
* @retval None g5 m) G2 L g( ^4 O
*/7 d+ B+ N, [/ F9 t$ N7 a7 j
void Bsp_TIM4_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
" r6 j. l U+ G+ b. ~+ I, b
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 mode3 A# Z/ L/ h0 S/ x, T0 j
TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=42000/700=60KHZ
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);7 Z }7 w6 E0 h7 v4 g
5 Z9 @/ F3 J' V: i& E- |6 M$ `
/* PWM1 Mode configuration: TIM4_Ch1 */, ]) `# p$ k( h$ ]" a. O( R
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode7 C& T$ \7 I% l% X' o$ {2 B, i
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);3 A+ e2 i% W" q8 ]
' C: e8 M5 |: ~, v4 }# X7 R' _
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc1 preload
# C5 L( O4 m: f7 C) r& R0 T
/* PWM1 Mode configuration: TIM4_Ch2 */; r4 C( ^* F1 _, j( h# _% l
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode$ t# }. \ c: N
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output 2 a! z2 m4 M3 Q
TIM_OCInitStructure.TIM_Pulse=500; //config TIM3_CCR2 vaule/ H2 }" l2 Z1 [/ P
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable4 P3 \, I, V5 k) }) o6 h% O
TIM_OC2Init(TIM4, &TIM_OCInitStructure);/ [6 r L3 N' ^ ~$ [
1 _. \2 q+ T4 ~. ^
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc2 preload 3 Y) i0 y$ q" a0 K# v( M
& A! E+ @/ J: ]
/* PWM1 Mode configuration: TIM4_CH3 */( I+ J5 F& P& k( `- \
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output 0 l& _2 e: R/ G. M" l1 K
TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable# l- b% u1 E* k4 f0 g% Z. M6 q
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc3 preload 6 y+ }; D& Y3 b0 y+ z9 `
/* PWM1 Mode configuration: TIM4_CH4 */& O7 W# H3 B& m& R
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode2 T3 l7 l& t. l2 U
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output
TIM_OCInitStructure.TIM_Pulse=600; //config TIM3_CCR1 vaule
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable4 b; {9 P: v" z+ N, h
TIM_OC4Init(TIM4, &TIM_OCInitStructure);! ], N: \6 O9 Q! A
5 |9 H. I2 h. o. u/ D
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc4 preload
s# E, T+ G, X+ Q
TIM_ARRPreloadConfig(TIM4, ENABLE); /* TIM3 enable counter */* O! y* m+ \* B7 e
TIM_Cmd(TIM4, ENABLE);1 V! u% h- J; Q9 J
}
定时器1触发中断程序如下:
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Trigger)==SET) //检查是否为触发中断; C/ G/ M) {' j1 l! B& s
{
TIM1->DIER&=0XFFBF; //清除定时器1的触发中断7 B6 Y5 Q+ d) X4 x* d/ _/ c
TIM1->DIER|=0X0001; //使能定时器1的溢出中断
TIM2->CR1|=0X0001; //打开定时器2使其对标准信号开始计数8 {% C; k# ~5 `
TIM1->SR&=0XFFBF; //在退出中断之前必须清除其中断标志位3 p& e/ n5 k8 p" l
}1 U+ H% T c6 J4 k2 K# @* ]" j0 X
}4 M+ P' S3 B7 O
定时器1溢出中断如下:) l O; m1 O z1 H
void TIM1_UP_TIM10_IRQHandler(void)/ e+ ^/ N& @7 B1 Y" C
{4 ~8 n% r; d* V. r% i6 X
if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //检查定时器1溢出标志位是否置1- P& Q# }7 s" a) H
{
n_Counter=TIM2->CNT; //读出计数器2的值
TIM1->CR1&=0XFFFE; //关闭定时器11 D5 k4 u1 O( ^! J6 e, s- J
TIM2->CR1&=0XFFFE; //关闭定时器2
TIM2->CNT&=0X0000; //清除计数器2计数寄存器的值7 V% l% t! c/ a: w
TimeFlag=1; //1s标志位置1* I& k8 Q. ~4 i. ~
TIM1->SR&=0XFFFE; //退出定时器1溢出中断之前,必须清除定时器1的溢出标志位
}
}
</i>
, i. ` v% b j7 P1 |