6-6 TMI输入捕获演示
PWM分辨率技巧:如果是要1%,那就定ARR + 1 = 100;如果是要0.1%,那就定ARR + 1 = 1000。
1.输入捕获模拟测频率程序
主函数:
#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);
}
}
pwm.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
//1.把TIM外设与GPIO外设的时钟打开
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2); //选择内部时钟源TIM2
//4.配置GPIO,PWM对应的GPIO配置位复位推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//对于普通的开漏推挽输出,引脚的控制权来自输出数据库,如果用定时器来控制引脚,需使用复用开漏,来自片上外设控制引脚,断开输出数据寄存器
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //修改了引脚复用,这里也得进行对应修改(0-15)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//2.配置时基单元
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自动重装值(总数)
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 -1; //PSC预分频的值(一周期计多少次)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值(高级TIM才有)
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
//3.配置输出比较单元(输出比较模式,极性选择,输出使能,设置CRR的值)
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
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //PA0口对应OC1口(参考引脚定义表)
TIM_Cmd(TIM2, ENABLE);
}
//调节CCR1寄存器的值,从而控制PWM的占空比
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare);
}
//单独修改PSC
void PWM_SetPrescaler(uint16_t Prescaler)
{
TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}
ic函数:
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
//1.把TIM外设与GPIO外设的时钟打开
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//配置GPIO,PWM对应的GPIO配置位复位推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//2.GPIO初始化
GPIO_InitTypeDef GPIO_InitStructure;
//对于普通的开漏推挽输出,引脚的控制权来自输出数据库,如果用定时器来控制引脚,需使用复用开漏,来自片上外设控制引脚,断开输出数据寄存器
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);
//3.配置时基单元
TIM_InternalClockConfig(TIM3); //选择内部时钟源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自动重装值(设大值,防止溢出)
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 -1; //PSC预分频的值(一周期计多少次)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值(高级TIM才有)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
//4.配置输入捕获单元(包括滤波器,极性,直连通道)
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);
//5.选择触发源,选择TI1FP1
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
//6.配置从模式为Reset
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
//7.调用TIM_Cmd,启动定时器
TIM_Cmd(TIM3, ENABLE);
}
uint32_t IC_GetFreq(void)
{
return 1000000 / TIM_GetCapture1(TIM3);
}
显示测试结果为1001Hz
2.PWMI测量频率和占空比
主函数:
#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);
}
}
IC主函数:
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
//1.把TIM外设与GPIO外设的时钟打开
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//配置GPIO,PWM对应的GPIO配置位复位推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//2.GPIO初始化
GPIO_InitTypeDef GPIO_InitStructure;
//对于普通的开漏推挽输出,引脚的控制权来自输出数据库,如果用定时器来控制引脚,需使用复用开漏,来自片上外设控制引脚,断开输出数据寄存器
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM3 CH3
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//3.配置时基单元
TIM_InternalClockConfig(TIM3); //选择内部时钟源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自动重装值(设大值,防止溢出)
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 -1; //PSC预分频的值(一周期计多少次)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值(高级TIM才有)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
//4.配置输入捕获单元(包括滤波器,极性,直连通道)
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_PWMIConfig(TIM3, &TIM_ICInitStructure); //快捷地把电路配置为PWMI模式地标准结构(只适合通道1和通道2)
//5.选择触发源,选择TI1FP1
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
//6.配置从模式为Reset
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
//7.调用TIM_Cmd,启动定时器
TIM_Cmd(TIM3, ENABLE);
}
uint32_t IC_GetFreq(void)
{
return 1000000 / TIM_GetCapture1(TIM3); //TIM_GetCapture1读取ccr
}
uint32_t IC_GetDuty(void)
{
return TIM_GetCapture2(TIM3)*100 / TIM_GetCapture1(TIM3);
}