STM32-蓝桥杯嵌入式之PWM输出

STM32-蓝桥杯嵌入式之PWM输出

PWM的配置可以参考官方固件库种STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\PWM_Output例程来进行改写。

下面来分析一下PWM输出的配置步骤:

  1. 首先配置时钟,由于开发板只将PA1~PA7这几个GPIO口引出,所以我们在配置PWM的时候,也只能使用这几个脚,那么查看芯片的数据手册可知,可以输出PWM的引脚与对应的通道如下表:
PA1 TIM2_CH2
PA2 TIM2_CH3
PA3 TIM2_CH4
PA6 TIM3_CH1
PA7 TIM3_CH2
  1. 配置GPIO,根据使用的PWM通道,来配置相应的GPIO引脚,模式配置为模拟输入
  2. 初始化基本定时器,这里需要初始化基本定时器初始化结构体,里面的成员的含义在下图中有详细的解释在这里插入图片描述
    下面举一个例子,代码如下,来计算一下定时器的周期应该是多少???
    首先我们需要知道定时器的时钟频率对吧,STM32时钟树中有提到如果APB1预分频系数等于1则频率不变,否则频率要乘以2,由于默认把APB1的频率二分频即PCLK1=36MHz,所以到定时器的频率要乘以2,即为72MHz。如果这里不清楚的话,我总结了一个关于STM32时钟的博客,可以参考一下。
    现在我们知道定时器时钟的频率是72MHz,SystemCoreClock是72MHz,则PrescalerValue计算出来是71,我们将预分频器设置为71,查看数据手册,如下图,可以知道会对时钟的频率进行72分频,得到的频率是1MHz。然后把TIM_Period 设置为1000-1,即设置ARR(自动重装载寄存器)为999,即定时器计数器从0开始,计数到999,则会自动重新装载,前面我们得到了频率为1MHz,那么定时器每进行一次重转载的周期是1MHz/1000=1kHz,也就是1ms。
    在这里插入图片描述
	/* Compute the prescaler value */
  PrescalerValue = (uint16_t) (SystemCoreClock / 1000000) - 1;
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 1000 - 1;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  1. 其实上面也都是基本定时器的内容,但是产生PWM的基础,这一步就是真正配置PWM了,主要就是对定时器的输出比较模式进行初始化,配置定时器输出比较结构体TIM_OCInitTypeDef,下面是主要的代码,里面对定时器的极性以及PWM的模式进行了详细的说明,参考的是这位博主的说明,解释的特别清楚,一看就能懂。应该是一看就能懂得。
	// OC:Output Compare 输出比较
	
	//	输出比较模式时的TIM_OCMode_PWM1和TIM_OCMode_PWM2区别
	
	// 现在假定TIM_OCInitTypeDef.TIM_OCPolarity = TIM_OCPolarity_High,则起始波形为高电位。

  // 若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:

  // 当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。

  // 当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。

  // 若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:

  //   当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。

  //   当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位。
  
	/* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;	// Polarity:极性
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

  TIM_OC2Init(TIM3, &TIM_OCInitStructure);
  // 输出比较预装载使能
  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
  1. 上面的步骤就已经配置完了,下面我们再使能一下自动重转载,将定时器打开即可。
TIM_ARRPreloadConfig(TIM2, ENABLE);
	/* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);

两个很重要的函数

// 用于设置ARR的值,通过设置ARR的值来改变定时器的频率
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload)
// 设置输出比较寄存器的值,用于改变PWM的占空比。
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)

最后附上详细的代码:

void PWM_GPIO_Configuration(void)
{
    
    
  GPIO_InitTypeDef GPIO_InitStructure;
  /* GPIOA Configuration:TIM2 Channel2, 3 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void PWM_RCC_Configuration(void)
{
    
    
  /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO, ENABLE);
}
void PWM_Init(void)
{
    
    
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	uint16_t CCR2_Val = 100;
	uint16_t CCR3_Val = 900;
	uint16_t PrescalerValue = 0;
	PWM_RCC_Configuration();
	PWM_GPIO_Configuration();
	
	/* Compute the prescaler value */
  PrescalerValue = (uint16_t) (SystemCoreClock / 1000000) - 1;
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 1000 - 1;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

	// OC:Output Compare 输出比较
	
	//	输出比较模式时的TIM_OCMode_PWM1和TIM_OCMode_PWM2区别
	
	// 现在假定TIM_OCInitTypeDef.TIM_OCPolarity = TIM_OCPolarity_High,则起始波形为高电位。

  // 若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:

  // 当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。

  // 当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。

  // 若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:

  //   当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。

  //   当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位。
  
	/* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;	// Polarity:极性
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

  TIM_OC2Init(TIM3, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;

  TIM_OC3Init(TIM2, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
	
	TIM_ARRPreloadConfig(TIM2, ENABLE);
	/* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);
}

猜你喜欢

转载自blog.csdn.net/qq_43715171/article/details/113186823