STM32 TIM1输入捕获测试输入信号的频率

测试芯片STM32F103C8T6,外部时钟

1、输入捕获通道测试

     TIM1的CH1N,无法进行输入捕获(估计是没找到其他原因,测试就也没有测试出来效果),直接改用TIM1的CH1通道进行测试,可以进行捕获中断测试;

在用CH1的通道输入捕获配置时,必须TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;对此初始化,第一次测试发现这个参数默认是10,不知道什么原因,后来加上这句好就好了,意思代表的是多少次计数周期更新一次中断事件;

2、输入捕获中断中不要做太多事情,尽量用寄存器操作

初始配置采用的上升沿配置,在捕获中断中更改捕获中断的沿方式;

一进入捕获中断,先对TIM1->CNT = 0;,然后再是其他操作,注意操作顺序,顺序不同会导致误差不同,见代码;

3、设置的存储计数器的值,采用的变量类型是volatile,否则会导致偶尔数据不对;

4、在用串口显示测试信号的信息时,会关闭总中断,执行结束后,再打开,否则会导致偶尔数据不对;

5、实际用捕获中断进行捕获时,总会存在误差的,在此我在串口输出显示时,做了矫正处理,每个处理器不同,矫正的大小也不同,尤其在TIM1更新中断发生时,产生的误差更大;

6、用PB0(输出PWM)和PA8(检测信号频率)进行测试的

  当PB0输出较低频率时,会导致TIM_Period超过65535,实际测试好像超过也没什么问题;

//
/*************************1---main函数串口信息打印********************************/
	while(1)
	{
    if(delayFlag == 1)//定时1s
    {
       delayFlag = 0; 
       if(IC_OccurFlag == 1)
       {
         __disable_irq();
         CheckNoSignalCount = 0;
         IC_OccurFlag = 0;
        // LED_On_OFF();
         PWM_OverFlow_temp1 = PWM_OverFlow_temp11;
         PWM_OverFlow_temp2 = PWM_OverFlow_temp22;
         IC1_High_temp = IC1_High;
         IC1_Low_temp =  IC1_Low+81;//矫正,只需矫正这一个,高电平不用矫正
         printf("高电平溢出次数:%d \r\n",PWM_OverFlow_temp1);
         printf("低电平溢出次数:%d \r\n",PWM_OverFlow_temp2);
         while(PWM_OverFlow_temp1--)
         {
            IC1_High_temp += (65536-5528);//矫正
         }
         while(PWM_OverFlow_temp2--)
         {
            IC1_Low_temp += (65536-5528);//矫正
         }
         printf("高电平时间:%.1f us\r\n",IC1_High_temp/Calc_PWM_TimerFreq_M);
         printf("低电平时间:%.1f us\r\n",IC1_Low_temp/Calc_PWM_TimerFreq_M);
         TestPWM_Period = (float)((float)IC1_High_temp+IC1_Low_temp)/Calc_PWM_TimerFreq_M;
         printf("测试信号周期:%.1f us\r\n",TestPWM_Period);
        
         TestPWM_Freq =  (float)(1000000.0f)/TestPWM_Period;
         printf("测试信号频率:%.2f HZ\r\n",(TestPWM_Freq));
         printf("-----------------------------------------\r\n");
         IC1_High_temp = IC1_Low_temp = 0;
         
         __enable_irq();
         
       }
       else
       {
         if(CheckNoSignalCount++ >= 3)
         {
            CheckNoSignalCount = 3;
            printf("没有检测到测试信号\r\n"); 
         }
        
       }
    }                                                          
    
    if(EXTIFlag == 1)
    {
       EXTIFlag = 0;
       printf("外部中断进入");
    }
    

	}

/*************************2---PWM输出信号********************************/
#ifndef __PWM_OUT_H
#define __PWM_OUT_H
#include "stm32f10x.h"

#define PWM_Out_GPIO        GPIOB
#define PWM_Out_Pin         GPIO_Pin_0
#define PWM_Out_Timer       TIM3
#define PWM_Out_TimerFreq   (u32)(72000000)
#define PWM_Out_TimerPre    (u16)(72)
#define PWM_Out_Freq        (u16)(1200)//
#define PWM_Out_TimerPeriod (u16)(PWM_Out_TimerFreq/PWM_Out_TimerPre/PWM_Out_Freq)

void PWM_OUT_Config(void);
#endif





#include "PWM_Out.h"

void PWM_OUT_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  GPIO_InitTypeDef         GPIO_InitStructure;
  TIM_OCInitTypeDef        TIM_OCInitStructure;//定义结构体
  
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE );
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
  
  GPIO_InitStructure.GPIO_Pin   = PWM_Out_Pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;	// 上拉输入
	GPIO_Init(PWM_Out_GPIO, &GPIO_InitStructure);
  
  TIM_TimeBaseStructure.TIM_Period        = PWM_Out_TimerPeriod; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值     计数到5000为500ms
  TIM_TimeBaseStructure.TIM_Prescaler     = PWM_Out_TimerPre-1; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
  TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
  TIM_TimeBaseInit(PWM_Out_Timer, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式,TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//输出比较极性低
  TIM_OC3Init(PWM_Out_Timer, &TIM_OCInitStructure);//根据结构体信息进行初始化
  TIM_OC3PreloadConfig(PWM_Out_Timer, TIM_OCPreload_Enable);  //使能定时器TIM2在CCR2上的预装载值
  
  TIM_Cmd(PWM_Out_Timer, ENABLE); 
  
  TIM_SetCompare3(PWM_Out_Timer,(u32)PWM_Out_TimerPeriod*3/4);//得到占空比为50%的pwm波形
}


/*************************3---检测信号的频率********************************/
#ifndef __CALC_PWM_H
#define __CALC_PWM_H
#include "stm32f10x.h"

#define Calc_PWM_GPIO        GPIOA
#define Calc_PWM_Pin         GPIO_Pin_8
#define Calc_PWM_Timer       TIM1
#define Calc_PWM_TimerFreq   (u32)(72000000)
#define Calc_PWM_TimerFreq_M (u32)(Calc_PWM_TimerFreq/1000000)
#define Calc_PWM_TimerPre    (u16)(1)
#define Calc_PWM_Freq        (u16)(1200)//测试最小PWM频率
#define Calc_PWM_TimerPeriod (u16)(Calc_PWM_TimerFreq/Calc_PWM_TimerPre/Calc_PWM_Freq)//此值最大65535 ;833us的周期时间


extern volatile float IC1_High,IC1_Low,IC1_Period;
extern volatile float IC1_High_temp,IC1_Low_temp;
extern volatile u8 IC_OccurFlag;
extern volatile u8 Control_OccurFlag;
extern volatile u16 PWM_OverFlow,PWM_OverFlow_temp1,PWM_OverFlow_temp11,PWM_OverFlow_temp2,PWM_OverFlow_temp22;
void Calc_PWM_Config(void);
#endif










#include "Calc_PWM.h"

volatile float IC1_High,IC1_Low,IC1_Period;
volatile float IC1_High_temp,IC1_Low_temp;
volatile u8 IC_OccurFlag;
volatile u8 Control_OccurFlag;
volatile u16 PWM_OverFlow=0,PWM_OverFlow_temp1,PWM_OverFlow_temp11,PWM_OverFlow_temp2,PWM_OverFlow_temp22;
void Calc_PWM_Config(void)
{
  GPIO_InitTypeDef          GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
  TIM_ICInitTypeDef         TIM_ICInitStructure;
  NVIC_InitTypeDef          NVIC_InitStructure;
  TIM_OCInitTypeDef        TIM_OCInitStructure;//定义结构体
  
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE );
  
  GPIO_InitStructure.GPIO_Pin   = Calc_PWM_Pin;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING; //GPIO_Mode_IN_FLOATING  GPIO_Mode_Out_PP GPIO_Mode_AF_PP
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_Init(Calc_PWM_GPIO, &GPIO_InitStructure);
  
  TIM_TimeBaseStructure.TIM_Period    = Calc_PWM_TimerPeriod;    
  TIM_TimeBaseStructure.TIM_Prescaler = Calc_PWM_TimerPre-1;       
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(Calc_PWM_Timer, &TIM_TimeBaseStructure);
  
  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;       
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;
  TIM_PWMIConfig(Calc_PWM_Timer, &TIM_ICInitStructure);

  TIM_SelectInputTrigger(Calc_PWM_Timer, TIM_TS_TI1FP1);
  TIM_SelectSlaveMode(Calc_PWM_Timer, TIM_SlaveMode_Reset);
  TIM_SelectMasterSlaveMode(Calc_PWM_Timer,TIM_MasterSlaveMode_Enable);
  
  
  
//  
//  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式,TIM脉冲宽度调制模式2
//  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
//  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//输出比较极性低
//  TIM_OC1Init(Calc_PWM_Timer, &TIM_OCInitStructure);//根据结构体信息进行初始化
//  TIM_OC1PreloadConfig(Calc_PWM_Timer, TIM_OCPreload_Enable);  //使能定时器TIM2在CCR2上的预装载值
  
  
  
 
  
  
  TIM_ClearITPendingBit(Calc_PWM_Timer,TIM_IT_Update);
  TIM_ITConfig(Calc_PWM_Timer, TIM_IT_CC1, ENABLE);
  TIM_ITConfig(Calc_PWM_Timer, TIM_IT_Update, ENABLE);
  
  TIM_Cmd(Calc_PWM_Timer, ENABLE);
//  TIM_SetCompare1(Calc_PWM_Timer,Calc_PWM_TimerPeriod/3);//得到占空比为50%的pwm波形
  //TIM_CtrlPWMOutputs(TIM1, ENABLE);                             //pwm输出
  
  NVIC_InitStructure.NVIC_IRQChannel                    = TIM1_CC_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_IRQn;//更新中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority         = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
}

extern void Test_PA1_HighLow(void);
extern void Test_PA1_High(void);
extern void Test_PA1_Low(void);

void TIM1_UP_IRQHandler(void)  
{
  if(TIM_GetITStatus(Calc_PWM_Timer,TIM_IT_Update) != RESET)
	{
     //Test_PA1_HighLow();
     
     TIM_ClearITPendingBit(Calc_PWM_Timer, TIM_IT_Update);
     PWM_OverFlow++;
  }
  
}

void TIM1_CC_IRQHandler(void)  
{
  if (TIM_GetITStatus(Calc_PWM_Timer, TIM_IT_CC1) != RESET) 
  {
    // Calc_PWM_Timer->SR = ~(TIM_IT_CC1);
    
//    if(Control_OccurFlag == 1)
//    {
//      if(IC1_High>14200)//
//      {
//      Calc_PWM_Timer->CNT = 0;  
//      }
//    }
      Calc_PWM_Timer->CNT = 0;
    
    //
    if(TIM1->CCER & 0X0002)//判断下降沿
    {
      
      //TIM_OC1PolarityConfig(Calc_PWM_Timer,TIM_OCPolarity_High);
      IC1_High = Calc_PWM_Timer->CCR1;//TIM_GetCapture1(Calc_PWM_Timer);
      PWM_OverFlow_temp11 = PWM_OverFlow;
      PWM_OverFlow = 0;
      TIM1->CCER &= 0XFFFD;
      IC_OccurFlag = 1;
    }
    else
    {
      
     // TIM_OC1PolarityConfig(Calc_PWM_Timer,TIM_OCPolarity_Low);
      IC1_Low = Calc_PWM_Timer->CCR1;//TIM_GetCapture1(Calc_PWM_Timer);
      //Calc_PWM_Timer->CNT = 0;
      PWM_OverFlow_temp22 = PWM_OverFlow;
      PWM_OverFlow = 0;
      TIM1->CCER |= 0X0002;
      
    }
    TIM_ClearITPendingBit(Calc_PWM_Timer, TIM_IT_CC1|TIM_IT_Update);
    //
    //Calc_PWM_Timer->CNT = 0;//加上这句,实际测试信号周期时间偏小;
  }
}

 

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值