【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获

文章目录

  • 前言
  • 1、输入捕获原理
    • 1.1、设置输入捕获滤波器
    • 1.2、设置输入捕获的极性
    • 1.3、设置输入捕获的映射通道
    • 1.4、设置输入捕获分频器
    • 1.5、捕获到有效信号可开启中断
    • 1.6、捕获实现频率和占空比的获取
  • 2、输入捕获功能配置流程
  • 3、部分源码

前言

  下载工程文件:
  https://gitee.com/Joseph_Cooper/blue-bridge-embedded


1、输入捕获原理

【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第1张图片

1.1、设置输入捕获滤波器

  根据输入信号的特点,配置输入滤波器为所需的带宽(即输入为TIx时,输入滤波器控制位是TIMx_CCMRx寄存器中的ICxF位)。假设输入信号在最多5个内部时钟周期的时间内抖动,我们须配置滤波器的带宽长于5个时钟周期;因此我们可以(以fDTS频率)连续采样8次,以确认在TI1上一次真实的边沿变换,即在TIMx_CCMR1寄存器中写入IC1F=0011。
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第2张图片

1.2、设置输入捕获的极性

  改变CC1P位的值以改变上升沿触发或是下降沿触发。可通过库函数void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)来设置。

1.3、设置输入捕获的映射通道

  通道内获得的信号是可以通过设置交给不同的IC来进行处理的,比如,我们可以将通道1捕获的信号送给IC2处理。
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第3张图片

1.4、设置输入捕获分频器

  可设置多次上升沿触发一次捕获也就是相当于分频的作用。
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第4张图片

1.5、捕获到有效信号可开启中断

  捕获到一次信号可以进入相应的中断服务函数。
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第5张图片
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第6张图片

1.6、捕获实现频率和占空比的获取

【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第7张图片
1、设置为上升沿捕获、定时器值清零
2、上升沿捕获成功后记录定时器中的值A再设置为下降沿捕获
3、下降沿捕获成功后记录定时器中的值B再次设置为上升沿捕获。
4、再次设置为上升沿捕获,捕获成功后记录定时器中的值C,清空定时器计数值 ( C − A ) ⋅ 1 f T I M (C-A)\cdot\frac1{f_{TIM}} (CA)fTIM1即为该波形的周期,其倒数即是频率, B − A C − A × 100 % \frac {B-A}{C-A}\times100\% CABA×100%即为占空比。


2、输入捕获功能配置流程

1、初始化定时器和通道对应IO的时钟。
2、初始化IO口,模式为输入
  GPIO_Init();
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入
3、初始化定时器ARR,PSC
   TIM_TimeBaseInit();
4、初始化输入捕获通道
  TIM_ICInit();
5、使能定时器
  TIM_Cmd();
6、如果要开启捕获中断
  TIM_ITConfig();
  NVIC_Init();
7、编写中断服务函数
  TIMx_IRQHandler();

需要用到的函数:
  通道极性设置函数
  void TIM_OCxPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
  获取捕获值
  uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx);


3、部分源码

PWM输出:
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第8张图片

输入捕获:
【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获_第9张图片
main.c:

#include "Headfile.h"

/** 
* @file 		main.c 
* @brief 		实现PA1捕获PA9、PA10端的输出,显示频率和占空比
* @version  1.0
* @author   JosephCooper
* @date     2020.10.09
*/


/** 滴答定时器实现延时中间变量 */
u32 TimingDelay = 0;
extern __IO uint32_t TIM2Freq;
extern u8 TIM2FreqReady;
extern __IO uint32_t TIM2Duty;

void Delay_Ms(u32 nTime);

//Main Body
int main(void)
{
	uint32_t i = 0;
	u8 Str[200];
	uint32_t TIM2Freq_BP = 0;
	uint32_t TIM2Duty_BP = 0;
	memset(Str,0x00,sizeof(Str));//清空数组
	
	SysTick_Config(SystemCoreClock/1000);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	Delay_Ms(200);
	
	LEDInit();//LED初始化
	//关闭所有LED
	LEDCmd(Bit_SET);
	GPIO_Write(GPIOC,GPIO_ReadOutputData(GPIOC) | 0xFF00);
	LEDCmd(Bit_RESET);
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	BuzzerInit();//蜂鸣器初始化
	TIM2_ICInit();
	TIM1_PWMInit();//TIM1_PWM初始化
	

	while(1)
	{
		if(TIM2FreqReady)
		{
			TIM2FreqReady = 0;
			if( (TIM2Freq!=TIM2Freq_BP) || (TIM2Duty!=TIM2Duty_BP) )
			{
				TIM2Freq_BP = TIM2Duty;
				TIM2Duty_BP = TIM2Freq;
				sprintf((char*)Str,"TIM2Freq:%dHz           ", TIM2Freq);
				LCD_DisplayStringLine(Line2,Str);
				sprintf((char*)Str,"TIM2Duty:%d%%           ", TIM2Duty);
				LCD_DisplayStringLine(Line3,Str);
				for(i=0; i<500000; i++);//刷新延迟
			}
		}

	}
}

//
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

stm32f10x_it.c:

#include "stm32f10x_tim.h"
#include "stm32f10x.h"
extern u32 TimingDelay;
...
//7、编写中断服务函数
__IO uint16_t IC2ReadValue1 = 0, IC2ReadValue2 = 0,IC2ReadValue_LOW = 0;
__IO uint16_t CaptureNumber = 0;
__IO uint32_t Capture = 0;
__IO uint32_t TIM2Freq = 0;
__IO uint32_t TIM2Duty = 0;
u8 TIM2FreqReady = 0;
void TIM2_IRQHandler(void)
{ 
  if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET) 
  {
    /* Clear TIM3 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
    if(CaptureNumber == 0)
    {
      /* Get the Input Capture value */
      IC2ReadValue1 = TIM_GetCapture2(TIM2);
      CaptureNumber = 1;
			//设置下降沿捕获
			TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_Low);
    }
		else if(CaptureNumber == 1)
		{
			IC2ReadValue_LOW = TIM_GetCapture2(TIM2);
			CaptureNumber = 2;
			//设置上升沿捕获
			TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_High);
		}
    else if(CaptureNumber == 2)
    {
      /* Get the Input Capture value */
      IC2ReadValue2 = TIM_GetCapture2(TIM2); 
      
      /* Capture computation */
      if (IC2ReadValue2 > IC2ReadValue1)
      {
        Capture = (IC2ReadValue2 - IC2ReadValue1); 
      }
      else
      {
        Capture = ((0xFFFF - IC2ReadValue1) + IC2ReadValue2);
				
      }
      /* Frequency computation */ 
			TIM2Duty = ( (IC2ReadValue_LOW-IC2ReadValue1)*100 ) / Capture;
      TIM2Freq = 1000000 / Capture;//定时器经过72分频后的频率
      CaptureNumber = 0;
			TIM2FreqReady = 1;
			TIM_SetCounter(TIM2,0);
    }
		
  }
}

InputCaputer.c

#include "Headfile.h"

void TIM2_ICInit()
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_ICInitTypeDef TIM2_ICInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//1、初始化定时器和通道对应IO的时钟。
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	//2、初始化PA1,模式为输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);
	//3、初始化定时器(时基设置)
  TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1 ;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
	//4、初始化输入捕获通道
	TIM2_ICInitStructure.TIM_Channel = TIM_Channel_2;//定时器2的通道2
  TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
  TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//使用通道默认IC即IC2
  TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不分频
  TIM2_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
	//5、使能定时器
	TIM_ICInit(TIM2, &TIM2_ICInitStructure);//IC初始化
	TIM_Cmd(TIM2, ENABLE);//打开定时器
	//6、如果要开启捕获中断
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
}

  关于LCD刷新的问题:LCD在刷新时可能因为中断打断出现乱码的问题,将要显示的字符串添加(用空格补全)至总长度超过20位即可sprintf((char*)Str,"TIM2Freq:%dHz ", TIM2Freq);

你可能感兴趣的:(#,蓝桥杯嵌入式,stm32,嵌入式,arm,输入捕获)