STM32入门笔记06_TIM输入捕获+案例: TIM输入测量信号频率 PWMI模式测量信号频率和占空比

文章介绍了STM32中TIM模块的输入捕获功能,用于测量信号的频率和占空比。通过配置TIM的IC单元,可以选择上升沿或下降沿触发,并通过滤波器和分频器来精确测量信号参数。此外,还展示了如何使用TIM的PWMI模式同时测量频率和占空比。在代码示例中,详细说明了TIM3的配置过程,包括时基单元、IC单元和从模式的设置,以及频率和占空比的计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TIM输入捕获

输入捕获简介

  • IC(Input Capture) 输入捕获
  • 输入捕获模式下, 当通道输入引脚出现指定电平跳变时, 当前CNT的值将被锁存到CCR中, 可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
  • 每个高级定时器和通用定时器都拥有四个输入捕获通道
  • 可配置为PWMI模式, 同时测量频率和占空比
  • 可配合主从触发模式, 实现硬件全自动测量

频率测量

在这里插入图片描述

  • 测频法: 在闸门时间T内, 对上升沿计次, 得到N, 则频率fx = N / T(适用于测高频信号)

  • 测周法: 两个上升沿内, 以标准频率fc计次, 得到N, 则频率fx = fc / N(适用于测低频信号s)

  • 中界频率: 测频法与测周法误差相等的频率点, fm = sqrt(fc / T)

输入捕获通道

在这里插入图片描述

  • fDTS: 滤波器采样时钟来源
  • TI1F: 滤波后的信号
  • CCMR1寄存器里的ICF位可以控制滤波器的参数
  • 通道2部分电路未画出

主从触发模式

在这里插入图片描述

主模式: 将定时器内部的信号, 映射到TRGO引脚, 用于触发别的外设

从模式: 接受其他外设或者自身外设的信号, 用于控制自身定时器的运行

输入捕获基本结构

在这里插入图片描述

  • 工作流程: 设边沿检测极性为高电平, 信号沿通道GPIO->滤波器->边沿检测, 当检测到高电平后, 发出TI1FP1信号;TI1FP1有两条通道, 第一条通道继续向下到分频器, 最后到CCR捕获/比较寄存器, CCR接受到信号后, 捕获CNT的计次N; 另一条通道, 则通过从模式将CNT置零。
  • 用得到的计次N可得频率 f = fc / N, fc是标准频率, 通过配置时基单元设置, 这里用的是测周法测频率的原理

PWMI基本结构

在这里插入图片描述

  • 与输入捕获结构相似, 但开启了第二条通道, 第二条通道在下降沿(与第一条通道触发方式相反), 触发CCR2寄存器捕获CNT的值得到N1,第一条通道则还是在上升沿捕获CNT的值得到N2
  • 如图所示: 易得占空比 = (N1+1)*100 / (N2+1) %

案例1: TIM输入捕获测量信号频率(对应输入捕获基本机构)

说明

  • 用PA0 的定时器 生成测试信号, PA6的定时器 捕获信号测量频率
  • 由于配置过程类似, 这里仅对IC单元的配置和从模式配置进行详细说明, 其余过程在注释中可以大致了解。

硬件接线

在这里插入图片描述

配置IC单元

	// 配置IC单元
	TIM_ICInitTypeDef TIM_InitStructure;
	TIM_InitStructure.TIM_Channel=TIM_Channel_1;  // 定时器通道
	TIM_InitStructure.TIM_ICFilter=0xF;  // 滤波器
	TIM_InitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;  // 边沿极性选择
	TIM_InitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;  // 分频器
	TIM_InitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;  // 配置选择器模式
	TIM_ICInit(TIM3, &TIM_InitStructure);
TIM_ICInitTypeDef
typedef struct
{

  uint16_t TIM_Channel;      /*!< Specifies the TIM channel.
                                  This parameter can be a value of @ref TIM_Channel */

  uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.
                                  This parameter can be a value of @ref TIM_Input_Capture_Polarity */

  uint16_t TIM_ICSelection;  /*!< Specifies the input.
                                  This parameter can be a value of @ref TIM_Input_Capture_Selection */

  uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
                                  This parameter can be a value of @ref TIM_Input_Capture_Prescaler */

  uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                  This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;
TIM_Channel
#define TIM_Channel_1                      ((uint16_t)0x0000)
#define TIM_Channel_2                      ((uint16_t)0x0004)
#define TIM_Channel_3                      ((uint16_t)0x0008)
#define TIM_Channel_4                      ((uint16_t)0x000C)
TIM_ICPolarity
#define  TIM_ICPolarity_Rising             ((uint16_t)0x0000)
#define  TIM_ICPolarity_Falling            ((uint16_t)0x0002)
#define  TIM_ICPolarity_BothEdge           ((uint16_t)0x000A)
TIM_ICSelection
#define TIM_ICSelection_DirectTI           ((uint16_t)0x0001) /*!< TIM Input 1, 2, 3 or 4 is selected to be 
                                                                   connected to IC1, IC2, IC3 or IC4, respectively */
#define TIM_ICSelection_IndirectTI         ((uint16_t)0x0002) /*!< TIM Input 1, 2, 3 or 4 is selected to be
                                                                   connected to IC2, IC1, IC4 or IC3, respectively. */
#define TIM_ICSelection_TRC                ((uint16_t)0x0003) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */
TIM_ICPrescaler
#define TIM_ICPSC_DIV1                     ((uint16_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input. */
#define TIM_ICPSC_DIV2                     ((uint16_t)0x0004) /*!< Capture performed once every 2 events. */
#define TIM_ICPSC_DIV4                     ((uint16_t)0x0008) /*!< Capture performed once every 4 events. */
#define TIM_ICPSC_DIV8                     ((uint16_t)0x000C) /*!< Capture performed once every 8 events. */

TIM_ICFilter
uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                  This parameter can be a number between 0x0 and 0xF */

配置从模式

// 配置从模式
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);  // 选择输入触发
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);  // 选择从模式
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
/**
  * @brief  Selects the Input Trigger source
  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
  * @param  TIM_InputTriggerSource: The Input Trigger source.
  *   This parameter can be one of the following values:
  *     @arg TIM_TS_ITR0: Internal Trigger 0
  *     @arg TIM_TS_ITR1: Internal Trigger 1
  *     @arg TIM_TS_ITR2: Internal Trigger 2
  *     @arg TIM_TS_ITR3: Internal Trigger 3
  *     @arg TIM_TS_TI1F_ED: TI1 Edge Detector
  *     @arg TIM_TS_TI1FP1: Filtered Timer Input 1
  *     @arg TIM_TS_TI2FP2: Filtered Timer Input 2
  *     @arg TIM_TS_ETRF: External Trigger input
  * @retval None
  */
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode)
/**
  * @brief  Selects the TIMx Slave Mode.
  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
  * @param  TIM_SlaveMode: specifies the Timer Slave Mode.
  *   This parameter can be one of the following values:
  *     @arg TIM_SlaveMode_Reset: Rising edge of the selected trigger signal (TRGI) re-initializes
  *                               the counter and triggers an update of the registers.
  *     @arg TIM_SlaveMode_Gated:     The counter clock is enabled when the trigger signal (TRGI) is high.
  *     @arg TIM_SlaveMode_Trigger:   The counter starts at a rising edge of the trigger TRGI.
  *     @arg TIM_SlaveMode_External1: Rising edges of the selected trigger (TRGI) clock the counter.
  * @retval None
  */

整体代码

IC.c
#include "stm32f10x.h"

/*
初始化TIM3_IC
*/
void TIM3_IC_Init(void)
{
	// RCC使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	// 配置GPIO口 A6 TIM3_CH1
	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);
	
	// 配置时钟源
	TIM_InternalClockConfig(TIM3);
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;  // 向上计数
	TimeBase_InitStructure.TIM_Period=65536-1;  // ARR
	TimeBase_InitStructure.TIM_Prescaler=72-1;  // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM3, &TimeBase_InitStructure);
	
	// 配置IC单元
	TIM_ICInitTypeDef TIM_InitStructure;
	TIM_InitStructure.TIM_Channel=TIM_Channel_1;  // 定时器通道
	TIM_InitStructure.TIM_ICFilter=0xF;  // 滤波器
	TIM_InitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;  // 边沿极性选择
	TIM_InitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;  // 分频器
	TIM_InitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;  // 配置选择器模式
	TIM_ICInit(TIM3, &TIM_InitStructure);
	
	// 配置从模式
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	// 开启定时器
	TIM_Cmd(TIM3, ENABLE);
}

/*
获取TIM3_CH1 输入波形频率
*/
uint16_t Get_TIM3_CH1_Freq(void)
{
	return 72000000/(TIM_GetPrescaler(TIM3)+1)/ (TIM_GetCapture1(TIM3)+1);
}
PWM.c
#include "stm32f10x.h"

/*
初始化TIM2的PWM模式
*/
void TIM2_PWM_Init(void)
{
	// RCC使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置GPIO口
	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;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置内部时钟作为TIM的时钟源
	TIM_InternalClockConfig(TIM2);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;  // 向上计数
	TimeBase_InitStructure.TIM_Period=100-1;  // ARR
	TimeBase_InitStructure.TIM_Prescaler=720-1;  // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2, &TimeBase_InitStructure);
	
	// 配置OC单元
	TIM_OCInitTypeDef OC1_InitStructure;
	TIM_OCStructInit(&OC1_InitStructure);
	OC1_InitStructure.TIM_OutputState=TIM_OutputState_Enable;
	OC1_InitStructure.TIM_OCMode=TIM_OCMode_PWM1;  // 设置模式
	OC1_InitStructure.TIM_OCPolarity=TIM_OCPolarity_High;  // 设置有效电平
	OC1_InitStructure.TIM_Pulse=50;  // CCR
	TIM_OC1Init(TIM2, &OC1_InitStructure);
	
	// 开启时钟
	TIM_Cmd(TIM2, ENABLE);
}

/*
初始化TIM3的PWM模式
*/
void TIM3_PWM_Init(void)
{
	// RCC使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置内部时钟作为TIM的时钟源
	TIM_InternalClockConfig(TIM3);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TimeBase_InitStructure.TIM_Period=100-1; // ARR
	TimeBase_InitStructure.TIM_Prescaler=720-1; // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM3, &TimeBase_InitStructure);
	
	// 配置OC单元
	TIM_OCInitTypeDef OC1_InitStructure;
	TIM_OCStructInit(&OC1_InitStructure);
	OC1_InitStructure.TIM_OCMode=TIM_OCMode_PWM1;  // 设置模式
	OC1_InitStructure.TIM_OCPolarity=TIM_OCPolarity_High;  // 设置有效电平
	OC1_InitStructure.TIM_OutputState=TIM_OutputState_Enable;  
	OC1_InitStructure.TIM_Pulse=50;  // CCR
	TIM_OC1Init(TIM3, &OC1_InitStructure);
	
	// 开启时钟
	TIM_Cmd(TIM3, ENABLE);
}

/*
设置TIM2的CRR1寄存器
*/
void TIM2_PWM_Set_Compare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);  // 设置OC1 CCR寄存器
}

/*
设置TIM3的CRR1寄存器
*/
void TIM3_PWM_Set_Compare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM3, Compare);
}
main.c
#include "stm32f10x.h" 
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

// TIM输入测频率
// 2023年3月25日11:11:15

int main(void)
{
	TIM2_PWM_Init();
	TIM3_IC_Init();
	OLED_Init();
	OLED_ShowString(1, 1, "Freq:00000Hz");

	while(1)
	{
		
		OLED_ShowNum(1, 6, Get_TIM3_CH1_Freq(), 5);
	}

}

案例2: PWMI模式下测量信号频率和占空比(对应PWMI基本结构)

整体代码

IC.c
#include "stm32f10x.h"

/*
初始化TIM3_IC
*/
void TIM3_IC_Init(void)
{
	// RCC使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	// 配置GPIO口 A6 TIM3_CH1
	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);
	
	// 配置时钟源
	TIM_InternalClockConfig(TIM3);
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;  // 向上计数
	TimeBase_InitStructure.TIM_Period=65536-1;  // ARR
	TimeBase_InitStructure.TIM_Prescaler=72-1;  // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM3, &TimeBase_InitStructure);
	
	// 配置IC单元
	TIM_ICInitTypeDef TIM_InitStructure;
	TIM_InitStructure.TIM_Channel=TIM_Channel_1;  // 定时器通道
	TIM_InitStructure.TIM_ICFilter=0xF;  // 滤波器
	TIM_InitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;  // 边沿极性选择
	TIM_InitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;  // 分频器
	TIM_InitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI; // 选择器
	TIM_PWMIConfig(TIM3, &TIM_InitStructure); // 区别在这里
	
	// 配置从模式
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);  // 选择TI1FP1通道
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);  // 选择Reset模式
	// 开启定时器
	TIM_Cmd(TIM3, ENABLE);
}

/*
获取TIM3_CH1 输入波形频率
*/
uint32_t Get_TIM3_CH1_Freq(void)
{
	return 72000000/(TIM_GetPrescaler(TIM3)+1)/ (TIM_GetCapture1(TIM3)+1);
}

/*
获取TIM3_PWMI 模式下占空比
*/

uint32_t Get_TIM3_Duty(void)
{
	return (TIM_GetCapture2(TIM3) + 1)*100 / (TIM_GetCapture1(TIM3) + 1);
}
TIM_PWMIConfig函数原型
/**
  * @brief  Configures the TIM peripheral according to the specified
  *         parameters in the TIM_ICInitStruct to measure an external PWM signal.
  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
  * @param  TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure
  *         that contains the configuration information for the specified TIM peripheral.
  * @retval None
  */
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
{
  uint16_t icoppositepolarity = TIM_ICPolarity_Rising;
  uint16_t icoppositeselection = TIM_ICSelection_DirectTI;
  /* Check the parameters */
  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
  /* Select the Opposite Input Polarity */
  if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising)
  {
    icoppositepolarity = TIM_ICPolarity_Falling;
  }
  else
  {
    icoppositepolarity = TIM_ICPolarity_Rising;
  }
  /* Select the Opposite Input */
  if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI)
  {
    icoppositeselection = TIM_ICSelection_IndirectTI;
  }
  else
  {
    icoppositeselection = TIM_ICSelection_DirectTI;
  }
  if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1)
  {
    /* TI1 Configuration */
    TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
               TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
    /* TI2 Configuration */
    TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
  }
  else
  { 
    /* TI2 Configuration */
    TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
               TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
    /* TI1 Configuration */
    TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
  }
}
PWM.c
#include "stm32f10x.h"

/*
初始化TIM2的PWM模式
*/
void TIM2_PWM_Init(void)
{
	// RCC使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置GPIO口
	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;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置内部时钟作为TIM的时钟源
	TIM_InternalClockConfig(TIM2);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;  // 向上计数
	TimeBase_InitStructure.TIM_Period=100-1;  // ARR
	TimeBase_InitStructure.TIM_Prescaler=720-1;  // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2, &TimeBase_InitStructure);
	
	// 配置OC单元
	TIM_OCInitTypeDef OC1_InitStructure;
	TIM_OCStructInit(&OC1_InitStructure);
	OC1_InitStructure.TIM_OutputState=TIM_OutputState_Enable;
	OC1_InitStructure.TIM_OCMode=TIM_OCMode_PWM1;  // 设置模式
	OC1_InitStructure.TIM_OCPolarity=TIM_OCPolarity_High;  // 设置有效电平
	OC1_InitStructure.TIM_Pulse=50;  // CCR
	TIM_OC1Init(TIM2, &OC1_InitStructure);
	
	// 开启时钟
	TIM_Cmd(TIM2, ENABLE);
}

/*
初始化TIM3的PWM模式
*/
void TIM3_PWM_Init(void)
{
	// RCC使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置内部时钟作为TIM的时钟源
	TIM_InternalClockConfig(TIM3);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TimeBase_InitStructure.TIM_Period=100-1; // ARR
	TimeBase_InitStructure.TIM_Prescaler=720-1; // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM3, &TimeBase_InitStructure);
	
	// 配置OC单元
	TIM_OCInitTypeDef OC1_InitStructure;
	TIM_OCStructInit(&OC1_InitStructure);
	OC1_InitStructure.TIM_OCMode=TIM_OCMode_PWM1;  // 设置模式
	OC1_InitStructure.TIM_OCPolarity=TIM_OCPolarity_High;  // 设置有效电平
	OC1_InitStructure.TIM_OutputState=TIM_OutputState_Enable;  
	OC1_InitStructure.TIM_Pulse=50;  // CCR
	TIM_OC1Init(TIM3, &OC1_InitStructure);
	
	// 开启时钟
	TIM_Cmd(TIM3, ENABLE);
}

/*
设置TIM2的CRR1寄存器
*/
void TIM2_PWM_Set_Compare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);  // 设置OC1 CCR寄存器
}

/*
设置TIM2的PSC寄存器
*/
void TIM2_PWM_Set_PSC(uint16_t PSC)
{
	TIM_PrescalerConfig(TIM2, PSC, TIM_PSCReloadMode_Update);
}

/*
设置TIM3的CRR1寄存器
*/
void TIM3_PWM_Set_Compare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM3, Compare);
}
main.c
#include "stm32f10x.h" 
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
// PWMI模式下测量信号频率和占空比
// 2023年3月25日11:13:10
int main(void)
{
	TIM2_PWM_Init();
	TIM3_IC_Init();
	OLED_Init();
	OLED_ShowString(1, 1, "Freq:00000Hz");
	OLED_ShowString(2, 1, "Duty:00%");
	
	// 设置占空比
	TIM2_PWM_Set_Compare1(30);  // Duty = CCR / ARR + 1
	// 设置频率  
	TIM2_PWM_Set_PSC(72-1);  	// Freq = 72M / (ARR + 1) / (PSC + 1)
	while(1)
	{
		OLED_ShowNum(1, 6, Get_TIM3_CH1_Freq(), 5);
		OLED_ShowNum(2, 6, Get_TIM3_Duty(), 2);
	}

}

TIM3_PWM_Set_Compare1(uint16_t Compare)
{
TIM_SetCompare1(TIM3, Compare);
}


#### main.c

```C
#include "stm32f10x.h" 
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
// PWMI模式下测量信号频率和占空比
// 2023年3月25日11:13:10
int main(void)
{
	TIM2_PWM_Init();
	TIM3_IC_Init();
	OLED_Init();
	OLED_ShowString(1, 1, "Freq:00000Hz");
	OLED_ShowString(2, 1, "Duty:00%");
	
	// 设置占空比
	TIM2_PWM_Set_Compare1(30);  // Duty = CCR / ARR + 1
	// 设置频率  
	TIM2_PWM_Set_PSC(72-1);  	// Freq = 72M / (ARR + 1) / (PSC + 1)
	while(1)
	{
		OLED_ShowNum(1, 6, Get_TIM3_CH1_Freq(), 5);
		OLED_ShowNum(2, 6, Get_TIM3_Duty(), 2);
	}

}

参考资料

https://www.bilibili.com/video/BV1th411z7sn?p=18&vd_source=722e2c21f78eecf154c5c9d24c2841b3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值