STM32的定时器概念-从基本到高级定时器由底层到配置使用-基本和高级TIM使用的初始化-用通用TIM输出四路PWM波

TIM定时器

STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。

stm32定时器分类

在这里插入图片描述

基本定时器-BASIC_TIM

下面我们分开介绍 先介绍基本定时器 -BASIC-TIM
基本定时器的核心是时基,不仅基本定时器有,通用定时器和高级定时器也有。
基本定时器功能框图
在这里插入图片描述

①时钟源

定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB1(36M) 预分频器后分频提供,如果APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系
数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M。 关于这个的基本定时器的时钟源我们只需要知道是72M就行了

②计数器时钟 CK_INT

定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个
16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)=**72M/PSC+1;**预分频器PSC

③计数器

计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达
到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。

④自动重装载寄存器

自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数
值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。

定时时间的计算

定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动
下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来 记 录 中 断 的 次 数 , 那 么 就 可 以 计 算 出 我 们 需 要 的 定 时 时 间 等 于 : 1/CK_CLK * (ARR+1)time。这里官方给的优点绕 计算定时器溢出时间记住这个:Tout=(ARR+1)(PSC+1)/Tclk;Tclk=72M;

定时器初始化结构体详解

typedef struct
{
  uint16_t TIM_Prescaler;     //预分频系数  就是PSC的值      0~65535
  uint16_t TIM_CounterMode;       //计数模式
  uint16_t TIM_Period;           //自动装载的计数值 就是ARR   0~65535
  uint16_t TIM_ClockDivision;      //时钟分频  在技术模式下用不到
  uint8_t TIM_RepetitionCounter;      //重复次数
} TIM_TimeBaseInitTypeDef;    

CounterMode计数模式

#define TIM_CounterMode_Up                 ((uint16_t)0x0000)
#define TIM_CounterMode_Down               ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)

虽然定时器基本初始化结构体有 5 个成员,但对于基本定时器只需设置其中两个就可
以,想想使用基本定时器就是简单。

我们先写一个基本定时器实验
编程要点:(1) 开定时器时钟 TIMx_CLK, x[6,7];
(2) 初始化时基初始化结构体;
(3) 使能 TIMx, x[6,7] update 中断;
(4) 打开定时器;
(5) 编写中断服务程序

我们这次用的是基本定时器,通用定时器和高级定时器要比基本的功能要多 通用定时器和高级定时器的定时编程要点跟基本定时器差不多,只是还要再选择下计数器的计数模式,是向上还是向下。因为基本定时器只能向上计数,且没有配置计数模式的寄存器,默认是向上。

宏定义部分


宏定义都知道写在哪个文件内吧就不多说了
#define BASIC_TIM6 // 如果使用 TIM7,注释掉这个宏即可

 #ifdef BASIC_TIM6 // 使用基本定时器 TIM6
 #define BASIC_TIM TIM6
 #define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
 #define BASIC_TIM_CLK RCC_APB1Periph_TIM6
 #define BASIC_TIM_IRQ TIM6_IRQn
 #define BASIC_TIM_IRQHandler TIM6_IRQHandler
 
 #else // 使用基本定时器 TIM7
 #define BASIC_TIM TIM7
 #define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
 #define BASIC_TIM_CLK RCC_APB1Periph_TIM7
 #define BASIC_TIM_IRQ TIM7_IRQn
 #define BASIC_TIM_IRQHandler TIM7_IRQHandler 
18 #endif
//基本定时器有 TIM6 和 TIM7,我们可以有选择的使用,为了提高代码的可移植性,我
们把当需要修改定时器时需要修改的代码定义成宏,默认使用的是定时器 6,如果想修改
成定时器 7,只需要把宏 BASIC_TIM6 注释掉即可。

定时器配置

// 中断优先级配置
static void BASIC_TIM_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    // 设置中断组为0
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		
		// 设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ;	
		// 设置主优先级为 0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 
	  // 设置抢占优先级为3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
/*
 * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
 * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
 * 另外三个成员是通用定时器和高级定时器才有.
 *-----------------------------------------------------------------------------
 *typedef struct
 *{ TIM_Prescaler            都有
 *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
 *  TIM_Period               都有
 *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
 *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
 *}TIM_TimeBaseInitTypeDef; 
 *-----------------------------------------------------------------------------
 */
static void BASIC_TIM_Mode_Config(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
		
		// 开启定时器时钟,即内部时钟CK_INT=72M
    BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
	
		// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;	

	  // 时钟预分频数为
    TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;
	
		// 时钟分频因子 ,基本定时器没有,不用管
    //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
		
		// 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
    //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 
		
		// 重复计数器的值,基本定时器没有,不用管
		//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
	
	  // 初始化定时器
    TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
		
		// 清除计数器中断标志位
    TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
	  
		// 开启计数器中断
    TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
		
		// 使能计数器
    TIM_Cmd(BASIC_TIM, ENABLE);	
}

void BASIC_TIM_Init(void)
{
	BASIC_TIM_NVIC_Config();
	BASIC_TIM_Mode_Config();
}

中断回调函数

如果不清楚中断回调函数 可以看我另一篇文章STM32的中断概念-从EXTI到NVIC由外到内一文搞清中断概念-EXTI的初始化和NVIC的初始化-按键中断实验

void  BASIC_TIM_IRQHandler (void)
{
	if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) 
	{	
		time++;// time为一个全局变量  每触发一次中断 time++      
		//可以实现定时时间=定时器溢出时间*溢出次数
		TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);  		 
	}		 	
}

我们把定时器设置自动重装载寄存器 ARR 的值为 1000,设置时钟预分频器为 71,则
驱动计数器的时钟:CK_CNT = CK_INT / (71+1)=1M,则计数器计数一次的时间等于:
1/CK_CNT=1us,当计数器计数到 ARR 的值 1000 时,产生一次中断,则中断一次的时间为:1/CK_CNT*ARR=1ms 然后time时中断的次数

主函数


 int main(void)
 {
 /* led 端口配置 */
 LED_GPIO_Config();
 
 /* 基本定时器 TIMx,x[6,7] 定时配置 */
 BASIC_TIM_Config();

 /* 配置基本定时器 TIMx,x[6,7]的中断优先级 */
 BASIC_TIM_NVIC_Config(); 
/* 基本定时器 TIMx,x[6,7] 重新开时钟,开始计时 */
 BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);

while (1) {
if ( time == 1000 ) { /* 1000 * 1 ms = 1s 时间到 */
 time = 0;
 /* LED1 取反 */
LED1_TOGGLE;
 } 
 }
 
 }

TIM—高级定时器

高级控制定时器(TIM1 和 TIM8)和通用定时器在基本定时器的基础上引入了外部引脚,
可以实现输入捕获和输出比较功能。高级控制定时器比通用定时器增加了可编程死区互补
输出、重复计数器、带刹车(断路)功能。

高级控制定时器时基单元包含一个 16 位自动重装载寄存器 ARR,一个 16 位的计数器
CNT,可向上/下计数,一个 16 位可编程预分频器 PSC,预分频器时钟源有多种可选,有内部的时钟、外部时钟。还有一个 8 位的重复计数器 RCR,这样最高可实现 40 位的可编程定时。

STM32ZET6(VET6)的高级/通用定时器的IO分配

在这里插入图片描述

高级定时器功能框图

在这里插入图片描述

①时钟源

高级控制定时器有四个时钟源可选:
 内部时钟源 CK_INT
 外部时钟模式 1:外部输入引脚 TIx(x=1,2,3,4)
 外部时钟模式 2:外部触发输入 ETR
 内部触发输入(ITRx)
各时钟源不多介绍了 非常复杂

②控制器

高级控制定时器控制器部分包括触发控制器、从模式控制器以及编码器接口。触发控
制器用来针对片内外设输出触发信号,比如为其它定时器提供时钟和触发 DAC/ADC 转换。
编码器接口专门针对编码器计数而设计。从模式控制器可以控制计数器复位、启动、递增/
递减、计数。有关控制器部分只需熟练阅读寄存器描述即可。

③时基单元

高级控制定时器时基单元功能包括四个寄存器,分别是计数器寄存器(CNT)、预分频
器寄存器(PSC)、自动重载寄存器(ARR)和重复计数器寄存器(RCR)。其中重复计数器 RCR是高级定时器独有,通用和基本定时器没有。前面三个寄存器都是 16 位有效,TIMx_RCR寄存器是 8 位有效。

预分频器 PSC

预分频器 PSC,有一个输入时钟 CK_PSC 和一个输出时钟 CK_CNT。输入时钟
CK_PSC 就是上面时钟源的输出,输出 CK_CNT 则用来驱动计数器 CNT 计数。通过设置
预分频器 PSC 的值可以得到不同的 CK_CNT ,实际计算为: fCK_CNT 等于fCK_PSC/(PSC[15:0]+1),可以实现 1 至 65536 分频。

计数器 CNT

高级控制定时器的计数器有三种计数模式,分别为递增计数模式、递减计数模式和递
增/递减(中心对齐)计数模式。
(1) 递增计数模式下,计数器从 0 开始计数,每来一个 CK_CNT 脉冲计数器就增加 1,直
到计数器的值与自动重载寄存器 ARR 值相等,然后计数器又从 0 开始计数并生成计数
器上溢事件,计数器总是如此循环计数。如果禁用重复计数器,在计数器生成上溢事
件就马上生成更新事件(UEV);如果使能重复计数器,每生成一次上溢事件重复计数
器内容就减 1,直到重复计数器内容为 0 时才会生成更新事件。
(2) 递减计数模式下,计数器从自动重载寄存器 ARR 值开始计数,每来一个 CK_CNT 脉
冲计数器就减 1,直到计数器值为 0,然后计数器又从自动重载寄存器 ARR 值开始递
减计数并生成计数器下溢事件,计数器总是如此循环计数。如果禁用重复计数器,在
计数器生成下溢事件就马上生成更新事件;如果使能重复计数器,每生成一次下溢事
件重复计数器内容就减 1,直到重复计数器内容为 0 时才会生成更新事件。
(3) 中心对齐模式下,计数器从 0 开始递增计数,直到计数值等于(ARR-1)值生成计数器上溢事件,然后从 ARR 值开始递减计数直到 1 生成计数器下溢事件。然后又从 0 开始计
数,如此循环。每次发生计数器上溢和下溢事件都会生成更新事件。

自动重载寄存器 ARR

自动重载寄存器 ARR 用来存放与计数器 CNT 比较的值,如果两个值相等就递减重复
计数器。可以通过 TIMx_CR1 寄存器的 ARPE 位控制自动重载影子寄存器功能,如果
ARPE 位置 1,自动重载影子寄存器有效,只有在事件更新时才把 TIMx_ARR 值赋给影子寄存器。如果 ARPE 位为 0,则修改 TIMx_ARR 值马上有效。

重复计数器 RCR

在基本/通用定时器发生上/下溢事件时直接就生成更新事件,但对于高级控制定时器
却不是这样,高级控制定时器在硬件结构上多出了重复计数器,在定时器发生上溢或下溢
事件是递减重复计数器的值,只有当重复计数器为 0 时才会生成更新事件。在发生 N+1 个上溢或下溢事件(N 为 RCR 的值)时产生更新事件。
输入捕获和输出比较不多介绍了

总结

基本定时器和高级定时器介绍完了,通用定时器再此不多介绍,除外通用定时器还有定时,脉冲计数,输入捕获和输出比较等功能,但我们目前都用不到 ,我们最需要的是PWM的输出 ,在我们的学习中对于PWM的学习很重要,在做一些智能小车和幻彩灯时就要用到PWM波的技术了。

TIM输出比较模式

我们像输出PWM波时,就要用到定时器的输出功能定义一个输出的结构体TIM_OCInitTypeDef;

typedef struct
{
  uint16_t TIM_OCMode;        /*!< Specifies the TIM mode.
                                   This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */

  uint16_t TIM_OutputState;   /*!< Specifies the TIM Output Compare state.
                                   This parameter can be a value of @ref TIM_Output_Compare_state */

  uint16_t TIM_OutputNState;  /*!< Specifies the TIM complementary Output Compare state.
                                   This parameter can be a value of @ref TIM_Output_Compare_N_state
                                   @note This parameter is valid only for TIM1 and TIM8. */

  uint16_t TIM_Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register. 
                                   This parameter can be a number between 0x0000 and 0xFFFF */

  uint16_t TIM_OCPolarity;    /*!< Specifies the output polarity.
                                   This parameter can be a value of @ref TIM_Output_Compare_Polarity */

  uint16_t TIM_OCNPolarity;   /*!< Specifies the complementary output polarity.
                                   This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
                                   @note This parameter is valid only for TIM1 and TIM8. */

  uint16_t TIM_OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
                                   This parameter can be a value of @ref TIM_Output_Compare_Idle_State
                                   @note This parameter is valid only for TIM1 and TIM8. */

  uint16_t TIM_OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
                                   This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
                                   @note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;

TIM_OCInitTypeDef输出结构体变量的取值

我们使用输出模式只用到 TIM_OCMode、TIM_OutPutState、TIM_Pulse、TIM_OCPolarity这四个变量

TIM_OCMode输出模式取值

#define TIM_OCMode_Timing                  ((uint16_t)0x0000)
#define TIM_OCMode_Active                  ((uint16_t)0x0010)
#define TIM_OCMode_Inactive                ((uint16_t)0x0020)
#define TIM_OCMode_Toggle                  ((uint16_t)0x0030)
#define TIM_OCMode_PWM1                    ((uint16_t)0x0060)
#define TIM_OCMode_PWM2                    ((uint16_t)0x0070)

TIM_OutputState输出比较状态

#define TIM_OutputState_Disable            ((uint16_t)0x0000)
#define TIM_OutputState_Enable             ((uint16_t)0x0001)

TIM_OCPolarity输出极性

#define TIM_OCPolarity_High                ((uint16_t)0x0000)
#define TIM_OCPolarity_Low                 ((uint16_t)0x0002)

TIM_Pulse占空比

between 0x0000 and 0xFFFF

其他的值不多介绍了 ,可以去官方固件库里找。

TIM输出PWM波实验

用通用定时器输出四路PWM波

static void GENERAL_TIM_GPIO_Config(void) 
{
  GPIO_InitTypeDef GPIO_InitStructure;

  // 输出比较通道1 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
	
	// 输出比较通道2 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH2_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
	
	// 输出比较通道3 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH3_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);
	
	// 输出比较通道4 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH4_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}


///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有
// *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
// *  TIM_Period               都有
// *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef; 
// *-----------------------------------------------------------------------------
// */

/* ----------------   PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)

static void GENERAL_TIM_Mode_Config(void)
{
  // 开启定时器时钟,即内部时钟CK_INT=72M
	GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);

/*--------------------时基结构体初始化-------------------------*/
	// 配置周期,这里配置为100K
	
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
	TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;	
	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
	TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;	
	// 时钟分频因子 ,配置死区时间时需要用到
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
	// 计数器计数模式,设置为向上计数
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		
	// 重复计数器的值,没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	// 初始化定时器
	TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);

	/*--------------------输出比较结构体初始化-------------------*/	
	// 占空比配置
	uint16_t CCR1_Val = 5;
	uint16_t CCR2_Val = 4;
	uint16_t CCR3_Val = 3;
	uint16_t CCR4_Val = 2;
	
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	// 配置为PWM模式1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	// 输出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	// 输出通道电平极性配置	
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	
	// 输出比较通道 1
	TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
	TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
	
	// 输出比较通道 2
	TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
	TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
	
	// 输出比较通道 3
	TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
	TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
	
	// 输出比较通道 4
	TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
	TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
	//自动重装载
	TIM_ARRPreloadConfig(TIM3,ENABLE);
	// 使能计数器
	TIM_Cmd(GENERAL_TIM, ENABLE);
}

void GENERAL_TIM_Init(void)
{
	GENERAL_TIM_GPIO_Config();
	GENERAL_TIM_Mode_Config();		
}

宏定义

#define            GENERAL_TIM                   TIM3
#define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM3
#define            GENERAL_TIM_Period            9
#define            GENERAL_TIM_Prescaler         71
// TIM3 输出比较通道1
#define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM_CH1_PORT          GPIOA
#define            GENERAL_TIM_CH1_PIN           GPIO_Pin_6

// TIM3 输出比较通道2
#define            GENERAL_TIM_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM_CH2_PORT          GPIOA
#define            GENERAL_TIM_CH2_PIN           GPIO_Pin_7

// TIM3 输出比较通道3
#define            GENERAL_TIM_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM_CH3_PORT          GPIOB
#define            GENERAL_TIM_CH3_PIN           GPIO_Pin_0

// TIM3 输出比较通道4
#define            GENERAL_TIM_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM_CH4_PORT          GPIOB
#define            GENERAL_TIM_CH4_PIN           GPIO_Pin_1

/**************************函数声明********************************/

void GENERAL_TIM_Init(void);

有示波器的小伙伴可以检测一下,没有示波器的小伙伴也可以通过keil5Debug一下,就不多介绍啦

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值