|
等精度测量法:定时器1对被测信号计数65536个周期作为闸门时间,在这个闸门时间内定时器2对标准信号进行计数。假定在这个闸门时间内标准信号的计数值为M。则有:65536/fc=M/fb通过这个公式就可以算出被测信号:fc=65536*fb/M。9 V$ K- F6 h/ D7 _1 p 本程序利用定时器3产生30KHZ的被测信号。定时器1对被测信号进行65536个周期计数。 定时器4产生60KHZ的标准信号。定时器2对标准信号在定时器1产生的闸门时间内计数。# ]3 O! x) g0 h( t 主程序如下:' `! D& k( y0 Q E0 f+ N1 @ /**0 S7 A" b4 d5 @5 k' L# Q0 B- m ******************************************************************************: b5 m# k7 h6 v% P" ? * @file app.c 7 l& l, z+ o* j( [) w * @author wangfei; {% ?. I$ l, M e. z * @date 13-April-2012% z, v" @5 L3 e z * @e-mail wfmjj@hotmail.com * @brief Initialize peripherals. *****************************************************************************/8 p; o. c. N8 Q /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx.h" #include "app.h" #include "bsp.h"! y$ K, H: l Z6 y0 s* l /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/5 i0 k9 {# l0 ]% ?8 g& y0 ^ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/% W6 d+ R6 ^3 m% X# d: e extern uint8_t TimeFlag;# U& B+ ^0 [ V7 D/ R extern uint32_t n_Counter;0 s" Y9 Q2 T K+ e! L uint16_t Counterh,Counterl;# n, a. ?: |' Y2 f- a! K* P3 T uint8_t Data[5];" R: r' u) k; A7 j2 N! V2 s /* Private function prototypes -----------------------------------------------*/) H& u5 f& y' ?. q2 ^6 u /* Private functions ---------------------------------------------------------*//** * @brief This function handles NMI exception.* w5 T0 A1 m. Y * @param None7 s% V1 @2 _/ d * @retval None */, S2 H* g/ g; o4 O, `! q5 s9 l int main(void)7 W' B6 q0 L" W Z2 ^4 T {0 B2 w! Z5 L4 B" B, f! S# b! K GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间( j" S) M( @# _+ X7 i9 }2 i Bsp_Init();+ B( p" L4 i. x( c2 u. o( i" S while(1). F3 x# Y+ M' C$ |* D; G( {: r {6 B4 \) _! @: m6 U7 c1 h& j uint8_t i; TIM_ITConfig(TIM1,TIM_IT_Trigger,ENABLE); //允许定时器1的触发中断+ T0 `2 Q/ @- O5 K8 m GPIO_SetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); TIM_Cmd(TIM1,ENABLE); //打开定时器1,当检测到TIM1_CH1通道的上升沿后立即触发中断( T! d o- o; M0 x while(TimeFlag==0); //等待定时器1溢出中断 TIM1->DIER&=0X0000; //失能定时器1的所有中断 GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3)); //可以通过观察LED口高电平时间 TimeFlag=0; //定时器1溢出标志置0 Counterh=n_Counter>>16; //得到32位数据中的高16位 Counterl=n_Counter; //得到32位数据中的低16位# H# n. V! k, H" Q Data[0]=Counterh>>8;. r4 O7 B' w! X" B Data[1]=Counterh;+ B6 M" i- P! {4 W- x/ L: z 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 TIM1->CCER&=0XFF5F; TIM1->SMCR|=0X0067; TIM_ClearFlag(TIM1,(TIM_FLAG_Update|TIM_FLAG_Trigger)); } /**9 `* c* s& R. I' x * @brief This function config timer3. T" `; ]2 }( J" b" Y; [& i * @param None * @retval None$ s) p6 K; ?& B- m7 @$ O4 o+ B */# i; A# J# M0 T2 f9 B6 J/ j void Bsp_TIM3_Config(void)% r+ R: x! k4 r8 j! ~; Z9 h0 h! L* h { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Open TIM3 Clock( ^% J$ ]; c- Y / H' L2 Z- L- S% S TIM_TimeBaseStructure.TIM_Prescaler=3; //clk_cnt prescale% o, L) F3 `4 K5 |# r% L TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM3 Count mode j L. n- L) p- w: v( X& B, @ TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=21000000/700=30KHZ TIM_TimeBaseStructure.TIM_ClockDivision=0; ; J* Y; k3 O* |" H: b7 m 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 / q) t0 v2 K9 R# E4 `4 X- ]% i+ G* S TIM_OCInitStructure.TIM_Pulse=350; //config TIM3_CCR1 vaule1 _9 _7 \0 }$ q TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc1 high level avaliable. H; ~* U# a2 G5 X" k TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc1 preload 4 b/ e/ T3 b/ } 4 Y* [ C8 U/ R4 X /* PWM1 Mode configuration: TIM3_Ch2 */ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode# }3 _9 U! x% b* m( b$ }8 ^) p" w# f+ I( ? 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 avaliable, e* [/ r& |# H4 p$ a TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc2 preload - f. Z! i9 w2 \1 I/ o! R1 p3 E /* PWM1 Mode configuration: TIM3_CH3 */ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode' }& T* T( y; e, S8 g5 W 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 TIM_OC3Init(TIM3, &TIM_OCInitStructure);* P) K& [" I/ l# o : y% m8 y) Z. w& `# t TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc3 preload /* PWM1 Mode configuration: TIM3_CH4 */ TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output 3 L" i7 ~3 c# i" O( 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);& i5 R' W+ H" m/ [6 y TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); // turn on oc4 preload TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE); }: Q( m% Q( {) |; t$ O! H* p+ d 8 J, v4 Q1 I+ K& f$ ?. U |
【福利三:雨露均沾·逢7狂欢】之四:用一个定时器同步另外两个定时器输出PWM
【逢7发帖赢大礼】STM32开发之WIFI实时时钟
【逢7发帖赢大礼】STM32开发之指纹识别!
【逢7发帖赢大礼】STM32开发之环境空气质量监测
【逢7发帖赢大礼】STM32开发之人体实时运动信息监测!
【逢7发帖赢大礼】STM32开发之IC门禁卡UID读取方法!
【逢7发帖赢大礼】全网最简单的Arduino_STM32开发环境搭建教程!
STM32F4中文用户手册
STM32F400、STM32F402 Cortex-M4超值单片机
SPI 高温读错最后一位?STM32F42xx 官方根治方案
微信公众号
手机版
* @brief This function config usart3.6 Y2 L# v1 ]7 o" S
* @param None
* @retval None4 L! `- T* {) E! W
*/4 W3 M4 x0 ]7 }- `: E+ A
void Bsp_USART3_Config(void)7 }0 J, y8 l6 ^: k( _9 W
{
USART_InitTypeDef USART_InitStructure; K) {; P: ]/ R; ^3 M5 O$ ^4 r
$ Q. ^7 K, L4 r4 [% o, }2 M4 ?3 T
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //turn on usart3 clock
# c8 n: p0 a4 t. F/ Z
USART_InitStructure.USART_BaudRate =115200 ; //波特率设置9 f: b1 [, }2 `. c) J! A
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;. a* o- }8 j( p9 ~. z! u
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; ]( S1 h B5 ~% C- l* Y2 d
USART_Init(USART3, &USART_InitStructure); Y" ^7 j, i) x! |' h. r1 r/ a
//USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
USART_Cmd(USART3,ENABLE);
USART_ClearFlag(USART3, USART_FLAG_TC); //清除发送完成标志位
}
/**
* @brief This function config nvic.8 B0 @; X y0 g
* @param None
* @retval None
*/
void Bsp_NVIC_Config(void)9 {% ?4 J( R! z8 I- \9 Y! C
{. \: ^& W G7 T: N$ W( d
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);7 U, ]% U6 B- ?2 Y' ^" f# Y. B
NVIC_InitStructure.NVIC_IRQChannel=TIM1_TRG_COM_TIM11_IRQn;; i' t8 m& Q( S. U8 ]
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;' o) F1 V: |. o5 h
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;; D* r" X& V3 q% Z
NVIC_Init(&NVIC_InitStructure);( ~; b- G& C5 T
7 [' m B- r- v
NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_TIM10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;% s; n1 x! O6 ~6 p/ A. P& D: U
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;2 t3 m" D! _% [
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}7 l; D' _$ b2 L/ l$ O) C% C9 N+ M
/**& ~+ _$ a* `, Q8 {) u& u
* @brief This function config timer2.
* @param None$ G8 N) l- U6 |7 |: w
* @retval None7 Y! ?) a2 a# w
*/
void Bsp_TIM2_Config(void)) z9 |# E8 c! \
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开定时器2的时钟
TIM_DeInit(TIM2);( u0 i2 M9 V1 T( k+ @& C! R0 J
- B( G' o0 D; D; l$ O
TIM_TimeBaseStructure.TIM_Prescaler=0; $ Q' e, b6 c& ?* F0 g- }" h) p
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //定时器2向上计数) n4 h% J0 e; O& _
TIM_TimeBaseStructure.TIM_Period=0xffff; , v. ^/ W1 ?. |) O* ?6 A! K# i) t
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM2->ARR|=0XFFFFFFFF; //配置' d5 Q* j6 L* H
//定时器2外部时钟模式1的配置9 B) [3 [: g5 V+ a
TIM2->CCMR1|=0X0001; : o5 T, K( i" b1 F C
TIM2->CCER&=0XFFF5; r: s$ u; o; n4 v' Y6 Q# s
TIM2->SMCR|=0X0057;& z0 i& Y2 N+ S4 P- ^
) T3 [$ }$ [* T5 }8 [2 S( U
TIM_ClearFlag(TIM2,TIM_FLAG_Update); //初始化时必须将溢出中断清0必须在开溢出中断之前。
}
/**9 f$ k/ _( L) i. t* i) M: {
* @brief This function config timer4.
* @param None# G4 |4 O7 ]$ I. J
* @retval None
*/
void Bsp_TIM4_Config(void). I* K! E0 [3 v& \. Z; h* I
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
2 y- A' V" }, a, L; [9 B/ X8 V
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //turn on TIM4 clock TIM_TimeBaseStructure.TIM_Prescaler=1; //Fck_cnt=84MHZ/2=42MHZ; r, \6 @- P% p; L' T
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM3 Count mode9 Y* x9 w5 Y+ @' F/ l
TIM_TimeBaseStructure.TIM_Period=699; //Fout_clk=Fclk_cnt/(ARR+1)=42000/700=60KHZ5 @+ b) p) s6 m% C5 }
TIM_TimeBaseStructure.TIM_ClockDivision=0;
- I% N L( \& L+ p* w
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);% Z' J- ?5 O/ _8 d, h
' T+ [5 c' m8 k: K y( ?' p( O
/* PWM1 Mode configuration: TIM4_Ch1 */1 }2 e. Z c" J- `* Z2 W0 Y) X2 u/ ~
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode( ^) T5 d5 y# b. p
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc1 as output & M v; C( V Y6 o. E8 X7 }+ {
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);2 m- W: d- E% u) b; A4 S3 a
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc1 preload : w+ X( u$ l% ^+ z
: U1 } O/ X) w- q
/* PWM1 Mode configuration: TIM4_Ch2 */' w% c9 l) Y* e p# r. k
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output E5 x; Z( {0 }5 H
TIM_OCInitStructure.TIM_Pulse=500; //config TIM3_CCR2 vaule4 ?) |/ [! m; A2 ~
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc2 high level avaliable8 ~, s0 z1 C0 x' @
TIM_OC2Init(TIM4, &TIM_OCInitStructure);% Y* [8 K/ X0 o* @$ d. ^% E
$ r* k; s! O7 ^- \- n8 c0 s
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc2 preload 0 i, O- g& I; `( J! W! ~
4 z0 Y @* s7 ^; a- g) Q4 d0 Y
/* PWM1 Mode configuration: TIM4_CH3 */1 W, h" V3 s. b& k% p2 i0 _; z
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc3 as output & Z2 s* ?# y/ w( G/ B8 S4 w/ l/ E6 T6 K1 G
TIM_OCInitStructure.TIM_Pulse=100; //config TIM3_CCR1 vaule- }2 j) Y9 b8 l
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc3 high level avaliable F- k3 {7 ]& B- |9 d/ F8 x
TIM_OC3Init(TIM4, &TIM_OCInitStructure);8 C% k* h P8 Y1 I% M2 v8 [
$ Q. O9 y! x" f1 s4 }: c
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc3 preload 1 ?' w. h8 q/ w( i, V" u7 h
/* PWM1 Mode configuration: TIM4_CH4 */
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //select PWM1 mode( C3 q/ X: r, d3 r2 v3 V H6 C8 W
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc4 as output
TIM_OCInitStructure.TIM_Pulse=600; //config TIM3_CCR1 vaule- V, t9 ]- k7 V( _
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //config oc4 high level avaliable4 _; K: ~- ^, }2 m1 X" Z
TIM_OC4Init(TIM4, &TIM_OCInitStructure);
, G" e( a5 \7 M, [& s$ u
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); // turn on oc4 preload
TIM_ARRPreloadConfig(TIM4, ENABLE); /* TIM3 enable counter */
TIM_Cmd(TIM4, ENABLE);
}
定时器1触发中断程序如下:
void TIM1_TRG_COM_TIM11_IRQHandler(void). J- ~9 I) B4 H+ f& f9 T8 m; b* R% I! Z
{/ t" c9 ?! t6 q
if(TIM_GetITStatus(TIM1,TIM_IT_Trigger)==SET) //检查是否为触发中断
{
TIM1->DIER&=0XFFBF; //清除定时器1的触发中断
TIM1->DIER|=0X0001; //使能定时器1的溢出中断) m$ j" {0 H1 v: d L
TIM2->CR1|=0X0001; //打开定时器2使其对标准信号开始计数* f# K3 E; R$ ` e, z
TIM1->SR&=0XFFBF; //在退出中断之前必须清除其中断标志位# k$ Y9 I' q5 R6 C
}! |2 ]/ E: J- l3 t$ G
}
定时器1溢出中断如下:
void TIM1_UP_TIM10_IRQHandler(void)
{4 y( [" w3 s9 _' o4 [2 m7 E
if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) //检查定时器1溢出标志位是否置1
{
n_Counter=TIM2->CNT; //读出计数器2的值4 C7 e# k( K& x+ D ?4 t/ A
TIM1->CR1&=0XFFFE; //关闭定时器1
TIM2->CR1&=0XFFFE; //关闭定时器2
TIM2->CNT&=0X0000; //清除计数器2计数寄存器的值5 y' t. T5 f0 i6 ~7 y3 }
TimeFlag=1; //1s标志位置11 t( E- s1 K; S' I, {- g
TIM1->SR&=0XFFFE; //退出定时器1溢出中断之前,必须清除定时器1的溢出标志位* U7 Y2 ?: P7 Z
}
}
</i>