作者:马芷靈 | 来源:互联网 | 2023-06-02 09:01
文章目录前言1、输入捕获原理1.1、设置输入捕获滤波器1.2、设置输入捕获的极性1.3、设置输入捕获的映射通道1.4、设置输入捕获分频器1.5、捕获到有效信号可开启中断1.6、捕获
文章目录
- 前言
- 1、输入捕获原理
- 1.1、设置输入捕获滤波器
- 1.2、设置输入捕获的极性
- 1.3、设置输入捕获的映射通道
- 1.4、设置输入捕获分频器
- 1.5、捕获到有效信号可开启中断
- 1.6、捕获实现频率和占空比的获取
- 2、输入捕获功能配置流程
- 3、部分源码
前言
下载工程文件:
https://gitee.com/Joseph_Cooper/blue-bridge-embedded
1、输入捕获原理
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、捕获实现频率和占空比的获取
1、设置为上升沿捕获、定时器值清零
2、上升沿捕获成功后记录定时器中的值A再设置为下降沿捕获
3、下降沿捕获成功后记录定时器中的值B再次设置为上升沿捕获。
4、再次设置为上升沿捕获,捕获成功后记录定时器中的值C,清空定时器计数值,(C−A)⋅1fTIM(C-A)\cdot\frac1{f_{TIM}}(C−A)⋅fTIM1即为该波形的周期,其倒数即是频率,B−AC−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"
u32 TimingDelay = 0;
extern __IO uint32_t TIM2Freq;
extern u8 TIM2FreqReady;
extern __IO uint32_t TIM2Duty;void Delay_Ms(u32 nTime);
int main(void)
{uint32_t i &#61; 0;u8 Str[200];uint32_t TIM2Freq_BP &#61; 0;uint32_t TIM2Duty_BP &#61; 0;memset(Str,0x00,sizeof(Str));SysTick_Config(SystemCoreClock/1000);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Delay_Ms(200);LEDInit();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();while(1){if(TIM2FreqReady){TIM2FreqReady &#61; 0;if( (TIM2Freq!&#61;TIM2Freq_BP) || (TIM2Duty!&#61;TIM2Duty_BP) ){TIM2Freq_BP &#61; TIM2Duty;TIM2Duty_BP &#61; TIM2Freq;sprintf((char*)Str,"TIM2Freq:%dHz ", TIM2Freq);LCD_DisplayStringLine(Line2,Str);sprintf((char*)Str,"TIM2Duty:%d%% ", TIM2Duty);LCD_DisplayStringLine(Line3,Str);for(i&#61;0; i<500000; i&#43;&#43;);}}}
}
void Delay_Ms(u32 nTime)
{TimingDelay &#61; nTime;while(TimingDelay !&#61; 0);
}
stm32f10x_it.c:
#include "stm32f10x_tim.h"
#include "stm32f10x.h"
extern u32 TimingDelay;
...
__IO uint16_t IC2ReadValue1 &#61; 0, IC2ReadValue2 &#61; 0,IC2ReadValue_LOW &#61; 0;
__IO uint16_t CaptureNumber &#61; 0;
__IO uint32_t Capture &#61; 0;
__IO uint32_t TIM2Freq &#61; 0;
__IO uint32_t TIM2Duty &#61; 0;
u8 TIM2FreqReady &#61; 0;
void TIM2_IRQHandler(void)
{ if(TIM_GetITStatus(TIM2, TIM_IT_CC2) &#61;&#61; SET) {TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);if(CaptureNumber &#61;&#61; 0){IC2ReadValue1 &#61; TIM_GetCapture2(TIM2);CaptureNumber &#61; 1;TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_Low);}else if(CaptureNumber &#61;&#61; 1){IC2ReadValue_LOW &#61; TIM_GetCapture2(TIM2);CaptureNumber &#61; 2;TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_High);}else if(CaptureNumber &#61;&#61; 2){IC2ReadValue2 &#61; TIM_GetCapture2(TIM2); if (IC2ReadValue2 > IC2ReadValue1){Capture &#61; (IC2ReadValue2 - IC2ReadValue1); }else{Capture &#61; ((0xFFFF - IC2ReadValue1) &#43; IC2ReadValue2);} TIM2Duty &#61; ( (IC2ReadValue_LOW-IC2ReadValue1)*100 ) / Capture;TIM2Freq &#61; 1000000 / Capture;CaptureNumber &#61; 0;TIM2FreqReady &#61; 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;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);GPIO_InitStructure.GPIO_Pin &#61; GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed &#61; GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode &#61; GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_TimeBaseStructure.TIM_Prescaler &#61; 72 - 1 ;TIM_TimeBaseStructure.TIM_CounterMode &#61; TIM_CounterMode_Up;TIM_TimeBaseStructure.TIM_Period &#61; 0xFFFF;TIM_TimeBaseStructure.TIM_ClockDivision &#61; 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);TIM2_ICInitStructure.TIM_Channel &#61; TIM_Channel_2;TIM2_ICInitStructure.TIM_ICPolarity &#61; TIM_ICPolarity_Rising;TIM2_ICInitStructure.TIM_ICSelection &#61; TIM_ICSelection_DirectTI;TIM2_ICInitStructure.TIM_ICPrescaler &#61; TIM_ICPSC_DIV1;TIM2_ICInitStructure.TIM_ICFilter &#61; 0x00;TIM_ICInit(TIM2, &TIM2_ICInitStructure);TIM_Cmd(TIM2, ENABLE);NVIC_InitStructure.NVIC_IRQChannel &#61; TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority &#61; 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority &#61; 1;NVIC_InitStructure.NVIC_IRQChannelCmd &#61; ENABLE;NVIC_Init(&NVIC_InitStructure);TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
}
关于LCD刷新的问题&#xff1a;LCD在刷新时可能因为中断打断出现乱码的问题&#xff0c;将要显示的字符串添加&#xff08;用空格补全&#xff09;至总长度超过20位即可sprintf((char*)Str,"TIM2Freq:%dHz ", TIM2Freq);
。