一、IC(Input Capture)输入捕获
1、输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
2、每个高级定时器和通用定时器都拥有4个输入捕获通道
3、可配置为PWMI模式,同时测量频率和占空比
4、可配合主从触发模式,实现硬件全自动测量
5、频率测量
测频法:在闸门时间T内,对上升沿计次,得到N,则频率 fx=N / T
测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率 fx=fc / N
中界频率:测频法与测周法误差相等的频率点
6、输入捕获通道
7、主从触发模式
8、输入捕获基本结构
9、PWMI基本结构
二、输入捕获模式测频率
1、按照以下接线方式连接,并将STLINK插到电脑上
2、输入捕获驱动函数模块
(1)输入捕获库函数功能
(2)输入捕获驱动函数模块
IC.c
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启时钟 TIM2:需要输出PWM 通道1引脚为PA0 TIM3:输入捕获 通道1引脚为PA6
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; //配置GPIO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //配置时基单元
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=65536 - 1; //ARR 设置大一些,防止计数溢出 PWM频率=更新频率=72M/(PSC+1)/(ARR+1)
TIM_TimeBaseInitStructure.TIM_Prescaler=72 -1; //PSC 决定测周法的标准频率fc 通过PSC调节频率,不会影响占空比
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure; //配置输入捕获
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter=0xF;
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInit(TIM3,&TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1); //配置TRGI的触发源为TI1FP1
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset); //配置从模式为Reset
TIM_Cmd(TIM3,ENABLE); //启动定时器
}
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1); //返回一个最新一个周期的频率值 fc=72M/(PSC+1),N=读取CCR的值 fx=fc/N
}
IC.h
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
#endif
(3)PWM驱动函数模块
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; //配置GPIO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //GPIO_Pin_15
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=100 - 1; //ARR PWM频率=更新频率=72M/(PSC+1)/(ARR+1)
TIM_TimeBaseInitStructure.TIM_Prescaler=720 - 1; //PSC 通过PSC调节频率,不会影响占空比
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure); //给所有参数赋初始值
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //输出模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //输出比较极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_Pulse=0; //设置CCR寄存器值 占空比=CCR/(ARR+1)
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
TIM_Cmd(TIM2,ENABLE);
}
/*
改变占空比
*/
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare);
}
/*
改变频率
*/
void PWM_SetPrescaler(uint16_t Prescaler)
{
TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);
}
PWM.h
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);
#endif
3、编写main.c代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main(void)
{
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1,1,"Freq:00000Hz");
PWM_SetPrescaler(720 - 1); //Freq=72M / (psc + 1) / 100
PWM_SetCompare1(50); //Duty= CCR / 100
while(1)
{
OLED_ShowNum(1,6,IC_GetFreq(),5);
}
}
4、实现效果
三、PWMI模式测频率占空比
1、输入捕获驱动函数模块
(1)输入捕获驱动函数模块
IC.c
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启时钟 TIM2:需要输出PWM 通道1引脚为PA0 TIM3:输入捕获 通道1引脚为PA6
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; //配置GPIO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //配置时基单元
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=65536 - 1; //ARR 设置大一些,防止计数溢出 PWM频率=更新频率=72M/(PSC+1)/(ARR+1)=1M/65536=15Hz 测频范围15Hz~1MHz
TIM_TimeBaseInitStructure.TIM_Prescaler=72 -1; //PSC 决定测周法的标准频率fc 通过PSC调节频率,不会影响占空比
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure; //配置输入捕获
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter=0xF;
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
// TIM_ICInit(TIM3,&TIM_ICInitStructure);
//
// TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;
// TIM_ICInitStructure.TIM_ICFilter=0xF;
// TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;
// TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
// TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_IndirectTI;
// TIM_ICInit(TIM3,&TIM_ICInitStructure);
TIM_PWMIConfig(TIM3,&TIM_ICInitStructure); //可以快捷的把电路配置成PWMI模式的标准结构 只支持通道1和通道2的配置
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1); //配置TRGI的触发源为TI1FP1
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset); //配置从模式为Reset
TIM_Cmd(TIM3,ENABLE); //启动定时器
}
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1); //返回一个最新一个周期的频率值 fc=72M/(PSC+1),N=读取CCR的值 fx=fc/N
}
uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3) + 1)*100 / (TIM_GetCapture1(TIM3) + 1);
}
IC.h
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);
#endif
(2)PWM驱动函数模块
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; //配置GPIO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //GPIO_Pin_15
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=100 - 1; //ARR PWM频率=更新频率=72M/(PSC+1)/(ARR+1)
TIM_TimeBaseInitStructure.TIM_Prescaler=720 - 1; //PSC 通过PSC调节频率,不会影响占空比
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure); //给所有参数赋初始值
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //输出模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //输出比较极性
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_Pulse=0; //设置CCR寄存器值 占空比=CCR/(ARR+1)
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
TIM_Cmd(TIM2,ENABLE);
}
/*
改变占空比
*/
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare);
}
/*
改变频率
*/
void PWM_SetPrescaler(uint16_t Prescaler)
{
TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);
}
PWM.h
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);
#endif
2、编写main.c代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main(void)
{
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1,1,"Freq:00000Hz");
OLED_ShowString(2,1,"Duty:00%");
PWM_SetPrescaler(720 - 1); //Freq=72M / (psc + 1) / 100
PWM_SetCompare1(50); //Duty= CCR / 100
while(1)
{
OLED_ShowNum(1,6,IC_GetFreq(),5);
OLED_ShowNum(2,6,IC_GetDuty(),2);
}
}
3、实现效果