STM32的输入捕获

输入捕获就是常说采集,工作流程一般包括以下5个步骤:
(1)设置输入捕获滤波器
(2)设置捕获极性
(3)设置捕获通道映射
(4)设置捕获分频器
(5)开启中断
结合下图具体说明
STM32的输入捕获_第1张图片

(1)设置捕获滤波器
通过设置TIMx_CCMR1的ICF位,设置采样频率和数字滤波长度,图中fDTS是通过设置TIMx_CR1的CDK[1:0]来确定的,如果CDK[1:0]为00,则fDTS=fCK_INT,fCK_INT就是定时器的输入频率。
STM32的输入捕获_第2张图片

假如设置IC1F为0011,则采样频率和定时器输入频率一样,N则是滤波长度,如果设置上升沿触发,则其在捕获到上升沿的时候再连续采样8次,如果都是高电平则是一个有效的电平,这样就会滤除波形时常不足8*1/fCK_INT的高电平,达到滤波效果,此时就会触发捕获中断。

(2)通过设置TIMx_CCER的CC1P位来设置触发信号。

(3)设置捕获映射通道,一般通道x映射ICx

(4)分频器就是设置多少次触发一次中断,如果设置IC1PSC为00,则每一个边沿都会设置一次捕获;01,每两个边沿触发一次捕获。。。。。。

(5)开启中断。

下面结合的代码具体实现捕获实验:
① 初始化定时器和通道对应IO的时钟。
② 初始化IO口,模式为输入:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入
③初始化定时器ARR,PSC
TIM_TimeBaseInit();
④初始化输入捕获通道
TIM_ICInit();
⑤如果要开启捕获中断,
TIM_ITConfig();
NVIC_Init();
⑥使能定时器:TIM_Cmd();
⑦编写中断服务函数:TIMx_IRQHandler();

void TIM5_Cap_Init(u16 arr,u16 psc)
{  
 TIM_ICInitTypeDef  TIM5_ICInitStructure;
 GPIO_InitTypeDef GPIO_InitStructure;
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
 
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能TIM5时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
  
 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  //PA0 清除之前设置  
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入  
 GPIO_Init(GPIOA, &GPIO_InitStructure);
 GPIO_ResetBits(GPIOA,GPIO_Pin_0);       //PA0 下拉
 
 //初始化定时器5 TIM5  
 TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 
 TIM_TimeBaseStructure.TIM_Prescaler =psc;  //预分频器   
 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
 TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
 //初始化TIM5输入捕获参数
 TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01  选择输入端 IC1映射到TI1上
   TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
   TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
   TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //配置输入分频,不分频 
   TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
   TIM_ICInit(TIM5, &TIM5_ICInitStructure);
   
 //中断分组初始化
 NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  //TIM3中断
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
 NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 
 TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断 
 
    TIM_Cmd(TIM5,ENABLE );  //使能定时器5
}

中断服务函数如下:

void TIM5_IRQHandler(void)
{ 
  if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获 
 {   
  if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
  {     
   if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
   {
    if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
    {
     TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
     TIM5CH1_CAPTURE_VAL=0XFFFF;
    }
    else 
     TIM5CH1_CAPTURE_STA++;
   }  
  }
 if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
  { 
   if(TIM5CH1_CAPTURE_STA&0X40)  //捕获到一个下降沿   
   {      
    TIM5CH1_CAPTURE_STA|=0X80;  //标记成功捕获到一次高电平脉宽
    TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
      TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
   }
   else          //还未开始,第一次捕获上升沿
   {
    TIM5CH1_CAPTURE_STA=0;   //清空
    TIM5CH1_CAPTURE_VAL=0;
     TIM_SetCounter(TIM5,0);
    TIM5CH1_CAPTURE_STA|=0X40;  //标记捕获到了上升沿
      TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);  //CC1P=1 设置为下降沿捕获
   }      
  }                     
  }
    TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}

代码解释:
首先触发上升沿中断,但没有触发溢出中断,所以先执行中断函数的下半部分,此时TIM5CH1_CAPTURE_STA&0X40为0,所以执行最后一个else,然后等到下一个上升中断时候TIM5CH1_CAPTURE_STA&0X40为1,此时TIM5CH1_CAPTURE_STA&0X40最高位置为1,成功捕获一次。如果发生溢出中断则执行上半部分中断函数。如果TIM5CH1_CAPTURE_STA&0X3F<0X3F就会使溢出中断增加一次,如果超过这个就强制捕获完成
在这里插入图片描述

主函数如下:

extern u8  TIM5CH1_CAPTURE_STA;  //输入捕获状态          
extern u16 TIM5CH1_CAPTURE_VAL; //输入捕获值 
int main(void)
{  
  u32 temp=0; 
 delay_init();       //延时函数初始化   
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
 uart_init(115200);  //串口初始化为115200
  TIM5_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数 
    while(1)
 {
   delay_ms(10);   
   if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
  {
   temp=TIM5CH1_CAPTURE_STA&0X3F;
   temp*=65536;//溢出时间总和
   temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
   printf("HIGH:%d us\r\n",temp);//打印总的高点平时间
   TIM5CH1_CAPTURE_STA=0;//开启下一次捕获 
  }
 }
}

利用串口通信将捕获时间在电脑显示。

你可能感兴趣的:(STM32)