STM32TIM定时器(3)


前言

这部分主要介绍输入捕获,通过输入捕获捕获定时器的计数器的值,通过频率检测来获取波形频率。简单介绍主从模式,实现硬件自动化检测。


一、介绍部分

输入捕获简介

在这里插入图片描述
也就是定时器框图的这部分
在这里插入图片描述

频率测量

都是计次数越大误差越小,所以使用N相等时得到中界频率。

在这里插入图片描述

捕获比较通道

在这里插入图片描述

主从模式

通过触发触发源自动运行从模式的内容
在这里插入图片描述

输入捕获基本结构

在这里插入图片描述

PWMI基本结构

在这里插入图片描述

二、代码部分

使用输入捕获捕获另一个端口的PWM输入

使用TIM2、PA0端口用于输出PWM波形,使用TIM3、PA6端口来接收这段波形频率。使用的是测周法

线路连接

在这里插入图片描述

代码内容

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_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		// 复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 50Hz翻转速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// 使用内部时钟(默认)
	TIM_InternalClockConfig(TIM2);
	// 配置事间基础(时基单元)
	TIM_TimeBaseInitTypeDef TIM_InitStructure;
	// 时钟分频
	TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	// 计算模式
	TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	// 重载值(有1的偏差)<计数值> ARR
	TIM_InitStructure.TIM_Period = 100-1;
	// 预分频(有1的偏差)<频率> PSC
	TIM_InitStructure.TIM_Prescaler = 720-1;
	// 重复计数器(不使用)
	TIM_InitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_InitStructure);
	
	//初始化输出比较
	TIM_OCInitTypeDef TIM_OCInitStruct;
	// 初始这个结构体,以免因为没有配置高级定时器相关的值而产生问题
	TIM_OCStructInit(&TIM_OCInitStruct);
	// PWM1模式
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	// PWM高电平时有效
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	// 输出使能
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
	// CCR,用于控制占空比的值
	TIM_OCInitStruct.TIM_Pulse = 0;
	TIM_OC1Init(TIM2,&TIM_OCInitStruct);
	
	// 启动定时器
	TIM_Cmd(TIM2,ENABLE);

}

// 设置CCR
void PWM_SetCCR(uint16_t Compare){
	TIM_SetCompare1(TIM2,Compare);

}

// 设置PSC
void PWM_SetPSC(uint16_t Prescaler){
	// 单独修改TIM2的预分频,立即生效,不使用影子寄存器
	TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);
}

封装输入捕获,IC.c内容:

#include "stm32f10x.h"                  // Device header

void IC_Init(void){
	// 开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	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;		// 50Hz翻转速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// 使用内部时钟(默认)
	TIM_InternalClockConfig(TIM3);
	// 配置事间基础(时基单元)
	TIM_TimeBaseInitTypeDef TIM_InitStructure;
	// 时钟分频
	TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	// 计算模式
	TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	// 重载值(有1的偏差)<计数值> ARR
	TIM_InitStructure.TIM_Period = 65536-1;
	// 预分频(有1的偏差)<频率> PSC
	TIM_InitStructure.TIM_Prescaler = 72-1;
	// 重复计数器(不使用)
	TIM_InitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
	
	//初始化输入捕获
	TIM_ICInitTypeDef TIM_ICInitStructure;
	// 选择CH1通道
	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);
	
	// 选择从模式,重置TIM3的计数器
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	// 启动定时器
	TIM_Cmd(TIM3,ENABLE);
}

uint32_t IC_GetFreq(void){
	// 72000000/73/获取的ARR
	return 1000000 / (TIM_GetCapture1(TIM3)+1);
}

主函数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();
	PWM_SetPSC(720-1);			// f = 72MHz/(Prescaler+1)/(ARR+1)
	PWM_SetCCR(50);					// 占空比 = CRR/(ARR+1)
	OLED_ShowString(1,1,"Freq:       Hz");
	
	while (1)
	{
		OLED_ShowNum(1,8,IC_GetFreq(),5);
	}
}

PWMI获取频率占空比

和PWMI基本结构一样,在上面的基础上多加一条交叉通道,用这个通道检测下降沿,来获取占空比

线路连接与上个案例一致

代码实现

PWM.c不用修改,修改IC.c的内容

#include "stm32f10x.h"                  // Device header

void IC_Init(void){
	// 开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	
	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;		// 50Hz翻转速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	
	// 使用内部时钟(默认)
	TIM_InternalClockConfig(TIM3);
	// 配置事间基础(时基单元)
	TIM_TimeBaseInitTypeDef TIM_InitStructure;
	// 时钟分频
	TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	// 计算模式
	TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	// 重载值(有1的偏差)<计数值> ARR
	TIM_InitStructure.TIM_Period = 65536-1;
	// 预分频(有1的偏差)<频率> PSC
	TIM_InitStructure.TIM_Prescaler = 72-1;
	// 重复计数器(不使用)
	TIM_InitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
	
	//初始化输入捕获
	TIM_ICInitTypeDef TIM_ICInitStructure;
	// 选择CH1通道
	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);
	
	// 设置输入触发源
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	// 选择从模式,重置TIM3的计数器
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	// 启动定时器
	TIM_Cmd(TIM3,ENABLE);
}

uint32_t IC_GetFreq(void){
	// 72000000/73/获取的ARR
	return 1000000 / (TIM_GetCapture1(TIM3)+1);
}
// 获取占空比
uint32_t IC_GetDuty(void){
	return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);
}

主函数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();
	PWM_SetPSC(7200-1);			// f = 72MHz/(Prescaler+1)/(ARR+1)
	PWM_SetCCR(80);					// 占空比 = CRR/(ARR+1)
	OLED_ShowString(1,1,"Freq:       Hz");
	OLED_ShowString(2,1,"Duty:       %");
	while (1)
	{
		// 显示频率
		OLED_ShowNum(1,8,IC_GetFreq(),5);
		// 显示占空比
		OLED_ShowNum(2,11,IC_GetDuty(),2);
	}
}


总结

相关函数

// 初始化输入捕获
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
// 自动配置没有配置的另一条输入捕获通道
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
// 设置从模式
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
// 设置不同定时器的比较值
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
// 设置不同定时器的预分频
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);
// 获取不同定时器的捕获计数器内容
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);

PSC、ARR都有1的误差

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值