文章目录
- 前言
- 1、输入捕获原理
-
- 1.1、设置输入捕获滤波器
- 1.2、设置输入捕获的极性
- 1.3、设置输入捕获的映射通道
- 1.4、设置输入捕获分频器
- 1.5、捕获到有效信号可开启中断
- 1.6、捕获实现频率和占空比的获取
- 2、输入捕获功能配置流程
- 3、部分源码
前言
??下载工程文件:1、输入捕获原理
??https://gitee.com/Joseph_Cooper/blue-bridge-embedded
文章图片
1.1、设置输入捕获滤波器 ??根据输入信号的特点,配置输入滤波器为所需的带宽(即输入为
TIx
时,输入滤波器控制位是TIMx_CCMRx
寄存器中的ICxF
位)。假设输入信号在最多5个内部时钟周期的时间内抖动,我们须配置滤波器的带宽长于5个时钟周期;因此我们可以(以fDTS频率)连续采样8次,以确认在TI1上一次真实的边沿变换,即在TIMx_CCMR1寄存器中写入IC1F=0011。文章图片
1.2、设置输入捕获的极性 ??改变
CC1P
位的值以改变上升沿触发或是下降沿触发。可通过库函数void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
来设置。1.3、设置输入捕获的映射通道 ??通道内获得的信号是可以通过设置交给不同的
IC
来进行处理的,比如,我们可以将通道1捕获的信号送给IC2
处理。文章图片
1.4、设置输入捕获分频器 ??可设置多次上升沿触发一次捕获也就是相当于分频的作用。
文章图片
1.5、捕获到有效信号可开启中断 ??捕获到一次信号可以进入相应的中断服务函数。
文章图片
文章图片
1.6、捕获实现频率和占空比的获取 【#|【蓝桥杯嵌入式】【STM32】10_InputCaputer之输入捕获】
文章图片
1、设置为上升沿捕获、定时器值清零
2、上升沿捕获成功后记录定时器中的值A再设置为下降沿捕获
3、下降沿捕获成功后记录定时器中的值B再次设置为上升沿捕获。
4、再次设置为上升沿捕获,捕获成功后记录定时器中的值C,清空定时器计数值, ( C ? A ) ? 1 f T I M (C-A)\cdot\frac1{f_{TIM}} (C?A)?fTIM?1?即为该波形的周期,其倒数即是频率, B ? A C ? A × 100 % \frac {B-A}{C-A}\times100\% C?AB?A?×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输出:
文章图片
输入捕获:
文章图片
main.c:
#include "Headfile.h"/**
* @filemain.c
* @brief实现PA1捕获PA9、PA10端的输出,显示频率和占空比
* @version1.0
* @authorJosephCooper
* @date2020.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】13_PWM输入捕获模式
- 笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
- ?后端|【MyBatis】ResultMap自定义映射
- #|STL迭代器详解
- 蓝桥杯|2018年第九届C/C++ A组蓝桥杯省赛真题部分题解(C语言/C++)
- #|2020年第11届蓝桥杯C++B组 第一次省赛真题
- #|<<算法很美>>——(七)——DFS典题(二):数独游戏
- #|【算法小结】尺取法及例题(Subsequence,Jessica’s Reading Problem)
- #|Python pyecharts Line折线图