你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 7499|回复: 1

STM32F4定时器应用--等精度测频法

[复制链接]

36

主题

89

回帖

2

蝴蝶豆

金牌会员

最后登录
2020-12-9
发表于 2013-2-21 12:55:40 | 显示全部楼层 |阅读模式
等精度测量法:定时器1对被测信号计数65536个周期作为闸门时间,在这个闸门时间内定时器2对标准信号进行计数。假定在这个闸门时间内标准信号的计数值为M。则有:65536/fc=M/fb通过这个公式就可以算出被测信号:fc=65536*fb/M。
本程序利用定时器3产生30KHZ的被测信号。定时器1对被测信号进行65536个周期计数。
定时器4产生60KHZ的标准信号。定时器2对标准信号在定时器1产生的闸门时间内计数。
主程序如下:

/**
  ******************************************************************************
  * @file    app.c
  * @author  wangfei
  * @date    13-April-2012
  * @e-mail  
wfmjj@hotmail.com
  * @brief   Initialize peripherals.
  *****************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "app.h"
#include "bsp.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern uint8_t TimeFlag;
extern uint32_t n_Counter;
uint16_t Counterh,Counterl;
uint8_t Data[5];
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*//**
* @brief   This function handles NMI exception.
  * @param  None
  * @retval None
  */
int main(void)
{
GPIO_ResetBits(GPIOE,(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3));  //可以通过观察LED口高电平时间
Bsp_Init();
while(1)
{
   uint8_t i;
   TIM_ITConfig(TIM1,TIM_IT_Trigger,ENABLE);  //允许定时器1的触发中断
   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溢出中断
   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位
   Data[0]=Counterh>>8;
   Data[1]=Counterh;
   Data[2]=Counterl>>8;
   Data[3]=Counterl;
  for(i=0;iCCMR1|=0X0100;  //配置定时器1为外部时钟模式1
TIM1->CCER&=0XFF5F;
TIM1->SMCR|=0X0067;
TIM_ClearFlag(TIM1,(TIM_FLAG_Update|TIM_FLAG_Trigger));
}
/**
  * @brief   This function config timer3.
  * @param  None
  * @retval None
  */
void Bsp_TIM3_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
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 */
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(TIM3, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);         // turn on oc1 preload

/* PWM1 Mode configuration: TIM3_Ch2 */
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;               //select PWM1 mode
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
TIM_OC2Init(TIM3, &TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);         // turn on oc2 preload
/* 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
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);

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
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);

TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);         // turn on oc4 preload
TIM_ARRPreloadConfig(TIM3, ENABLE);  /* TIM3 enable counter */
  TIM_Cmd(TIM3, ENABLE);
}
/**
  * @brief   This function config usart3.
  * @param  None
  * @retval None
  */
void Bsp_USART3_Config(void)
{
USART_InitTypeDef USART_InitStructure;
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //turn on usart3 clock
  
  USART_InitStructure.USART_BaudRate =115200 ;         //波特率设置
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  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);
  
  //USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
  USART_Cmd(USART3,ENABLE);
  USART_ClearFlag(USART3, USART_FLAG_TC);   //清除发送完成标志位
}
/**
  * @brief   This function config nvic.
  * @param  None
  * @retval None
  */
void Bsp_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  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);

  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);
}
/**
  * @brief   This function config timer2.
  * @param  None
  * @retval None
  */
void Bsp_TIM2_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  //打开定时器2的时钟
  TIM_DeInit(TIM2);

TIM_TimeBaseStructure.TIM_Prescaler=0;                       
  TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;      //定时器2向上计数
  TIM_TimeBaseStructure.TIM_Period=0xffff;                        
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM2->ARR|=0XFFFFFFFF;   //配置
//定时器2外部时钟模式1的配置
TIM2->CCMR1|=0X0001;   
TIM2->CCER&=0XFFF5;
TIM2->SMCR|=0X0057;

TIM_ClearFlag(TIM2,TIM_FLAG_Update);    //初始化时必须将溢出中断清0必须在开溢出中断之前。
}
/**
  * @brief   This function config timer4.
  * @param  None
  * @retval None
  */
void Bsp_TIM4_Config(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
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
TIM_TimeBaseStructure.TIM_Period=699;         //Fout_clk=Fclk_cnt/(ARR+1)=42000/700=60KHZ
TIM_TimeBaseStructure.TIM_ClockDivision=0;   

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

/* PWM1 Mode configuration: TIM4_Ch1 */
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);

TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);         // turn on oc1 preload

/* PWM1 Mode configuration: TIM4_Ch2 */
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;               //select PWM1 mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //config oc2 as output
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);

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
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(TIM4, &TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);         // turn on oc3 preload
/* PWM1 Mode configuration: TIM4_CH4 */
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
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);

}
</em>

定时器1触发中断程序如下:
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Trigger)==SET)  //检查是否为触发中断
{
  TIM1->DIER&=0XFFBF;    //清除定时器1的触发中断
  TIM1->DIER|=0X0001;    //使能定时器1的溢出中断
  TIM2->CR1|=0X0001;    //打开定时器2使其对标准信号开始计数
  TIM1->SR&=0XFFBF;     //在退出中断之前必须清除其中断标志位
}
}
定时器1溢出中断如下:
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET)  //检查定时器1溢出标志位是否置1
{
  n_Counter=TIM2->CNT;  //读出计数器2的值
  TIM1->CR1&=0XFFFE;    //关闭定时器1
  TIM2->CR1&=0XFFFE;    //关闭定时器2
  TIM2->CNT&=0X0000;    //清除计数器2计数寄存器的值
  TimeFlag=1;          //1s标志位置1
  TIM1->SR&=0XFFFE;    //退出定时器1溢出中断之前,必须清除定时器1的溢出标志位
}
}
140941mfeccpttst9kcit9.jpg
1411509sn93npyvhynj0gz.jpg
14100947u75hr84s4ls4zu.jpg
<
回复

使用道具 举报

7

主题

14

回帖

0

蝴蝶豆

初级会员

最后登录
1970-1-1
发表于 2014-3-24 10:49:46 | 显示全部楼层

回复: STM32F4定时器应用--等精度测频法

 敢问楼主,您的这个工程测试是否真的是成功了,还有,你用的UASRT中断貌似木有配置NVIC,还有我用的F407,在修改相应的管脚之后,提示这个,希望楼主帮忙看看 QQ截图20140324101347.png
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版