待测PWM信号为stm32自己生成,输出脚为PA0,直接用一根线把PA0引到PA6。
在原有模板的基础上,改动PWM.h、PWM.c并添加IC.h、IC.c
输出捕获初始化
第⼀步,RCC开启时钟,把GPIO的TIM的时钟打开 第⼆步,GPIO初始化,把GPIO配置成输⼊模式,⼀般选择上拉输⼊或者浮空输⼊模式 第三步,配置时基单元,让CNT计数器在内部时钟的驱动下⾃增运⾏ 第四步,配置输⼊捕获单元,包括滤波器、极性、直连通道还是交叉通道、分频器这些参数 第五步,选择从模式的触发源,触发源选择TI1FP1,调⽤⼀个库函数即可 第六步,选择触发之后执⾏的操作,执⾏Reset操作,调⽤⼀个库函数即可 第七步,调⽤TIM_Cmd函数,开启定时器
结构体配置输⼊捕获单元的函数
输出比较和输入捕获每个通道占⽤⼀个函数,输⼊捕获4个通道是共⽤⼀个函数的,在结构体中有额外的 参数来选择通道。
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
输⼊捕获的初始化函数
与上⼀个函数类似都是⽤于初始化输⼊捕获单元的,上⼀个函数只是单⼀的配置⼀个通道, ⽽这个函数可以快速配置两个通道,把外设电路配置成PWMI的电路
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
给输⼊捕获结构体赋⼀个初始值函数
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);
选择输⼊触发源TRGI函数
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
选择输出触发源TRGO函数
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
选择从模式函数
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
单独配置通道1、2、3、4的分频器函数
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
读取四个通道的CCR函数
输出比较模式下,CCR是只写的,要⽤SetCompare写⼊,输⼊捕获模式下,CCR是只读的,要⽤GetCapture读出
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);
PWM.c
#include "stm32f10x.h" // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO时钟// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, 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; //ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//写入参数TIM_OCInitTypeDef TIM_OCInitStructure;//定义输出比较结构体TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋默认值TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM1模式TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效电平为高电平TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//使能TIM_OCInitStructure.TIM_Pulse = 0; //CCRTIM_OC1Init(TIM2, &TIM_OCInitStructure);//写入参数TIM_Cmd(TIM2, ENABLE);//开启时钟
}
//单独更改CCR的值
void PWM_SetCompare1(uint16_t Compare)//改变通道1的占空比
{TIM_SetCompare1(TIM2, Compare);
}
//单独写入PSC函数
void PWM_SetPrescaler(uint16_t Prescaler)//改变频率
{TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}
pwm.h
#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);#endif
IC.c
#include "stm32f10x.h" // Device headervoid IC_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//开启TIM2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO时钟GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //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 = 65536 - 1; //ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//写入参数pTIM_ICInitTypeDef TIM_ICInitStructure;//定义输⼊捕获结构体TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//通道1TIM_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);//选择触发源TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//从模式TIM_Cmd(TIM3, ENABLE);//开启定时器
}
//获取频率函数
uint32_t IC_GetFreq(void)
{return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
IC.h
#ifndef __IC_H
#define __IC_Hvoid IC_Init(void);
uint32_t IC_GetFreq(void);#endif
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 频率1KHzPWM_SetCompare1(50); //Duty = CCR / 100 占空比50%while (1){OLED_ShowNum(1, 6, IC_GetFreq(), 5);//不断刷新显示频率}
}
IC.c
#include "stm32f10x.h" // Device headervoid IC_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//开启TIM2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO时钟GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //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 = 65536 - 1; //ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//写入参数TIM_ICInitTypeDef TIM_ICInitStructure;//定义输入捕获结构体TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//通道1TIM_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_PWMIConfig(TIM3, &TIM_ICInitStructure);//写入参数//TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;//通道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_DirectTI;//交叉输入//TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
//或者TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);//配置为相反的函数TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//选择触发源TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//从模式 TIM_Cmd(TIM3, ENABLE);//开启定时器
}
//获取频率函数
uint32_t IC_GetFreq(void)
{return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
//获取占空比函数
uint32_t IC_GetDuty(void)
{return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}
IC.h
#ifndef __IC_H
#define __IC_Hvoid IC_Init(void);
uint32_t IC_GetFreq(void);#endif
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) / 100PWM_SetCompare1(50); //Duty = CCR / 100while (1){OLED_ShowNum(1, 6, IC_GetFreq(), 5);OLED_ShowNum(2, 6, IC_GetDuty(), 2);}
}