STM32HAL定时器PWM输出呼吸灯

 

  1. STM32定时器区别

     基本定时器主要特征:

     ●16位自动重装载累加计数器 

    ●16位可编程(可实时修改)预分频器,用于对输入的时钟按系数为1~65536之间的任意数值分频 

    ●在更新事件(计数器溢出)时产生中断/DMA请求 

高级与通用定时器功能包括(红色字体为高级定时器与通用定时器区别)
    ● 16位向上、向下、向上/向下自动装载计数器
    ● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536 之间的任意数值
    ● 4个独立通道:
    ─ 输入捕获
   ─ 输出比较
   ─ PWM生成(边缘或中间对齐模式)
   ─ 单脉冲模式输出
  ● 使用外部信号控制定时器和定时器互连的同步电路
  ● 如下事件发生时产生中断/DMA:
  ─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
  ─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
  ─ 输入捕获
  ─ 输出比较
  ● 支持针对定位的增量(正交)编码器和霍尔传感器电路
  ● 触发输入作为外部时钟或者按周期的电流管理 

  ● 死区时间可编程的互补输出 

  ● 允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器
  ● 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态 

2.STM32L051定时器只有通用定时器(TIM2/3,TIM21/22),基本定时器(TIM6/7),使用通用定时器2四个通道输出PWM波。

·   计数器寄存器 (TIMx_CNT)计数器的时钟可通过预分频器进行分频。 计数器由预分频器输出 CK_CNT 提供时钟,仅当 TIMx_CR1 寄存器中的计数器启动位(CEN) 1 时,才会启动计数器实际的计数器使能信号 CNT_EN CEN 1 的一个时钟周期后被置 1  
  · 预分频器寄存器 (TIMx_PSC)预分频器可对计数器时钟频率进行分频,分频系数介于 1 65536 之间。该预分频器基于16 /32 位寄存器(TIMx_PSC 寄存器)所控制的 16 位计数器。由于该控制寄存器具有缓冲功能,因此预分频器可实现实时更改。而新的预分频比将在下一更新事件发生时被采用。 
·   自动重载寄存器 (TIMx_ARR)自动重载寄存器是预装载的。对自动重载寄存器执行写入或读取操作时会访问预装载寄存器。预装载寄存器的内容既可以直接传送到影子寄存器,也可以在每次发生更新事件 (UEV)时传送到影子寄存器,这取决于 TIMx_CR1 寄存器中的自动重载预装载使能位 (ARPE)。当计数器达到上溢值(或者在递减计数时达到下溢值)并且 TIMx_CR1 寄存器中的 UDIS 位为0 时,将发送更新事件。该更新事件也可由软件产生。

·  计数器模式  递增计数模式,计数器从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始计数并生成计数器上溢事件。

  递减计数模式下,计数器从自动重载值(TIMx_ARR 寄存器的内容)开始递减计数到 0,然后重新从自动重载值开始计数并生成计数器下溢事件。  

  中心对齐模式(递增/递减计数下,计数器从 0 开始计数到自动重载值(TIMx_ARR 寄存器的内容) – 1,生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从0 开始重新计数。 

  占空比:高低电平所占的时间的比率,占空比越大,电路开通时间就越长。通过改变占空比来控制高低电平在一个周期内所占的时间。

 

3.PWM实现呼吸灯

 

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)

{

  GPIO_InitTypeDef   GPIO_InitStruct;

  

  __HAL_RCC_TIM2_CLK_ENABLE();  //TIM2时钟使能

  __HAL_RCC_GPIOA_CLK_ENABLE(); //GPIOA时钟使能

  

//引脚配置 定时器对应引脚去datasheet查找

配置PA0 1 2 3对应定时器2 通道1 2 3 4

  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  

  GPIO_InitStruct.Pull = GPIO_PULLUP;

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

  GPIO_InitStruct.Alternate = GPIO_AF2_TIM2;

  

  GPIO_InitStruct.Pin = GPIO_PIN_0;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  

  GPIO_InitStruct.Pin = GPIO_PIN_1;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  

  GPIO_InitStruct.Pin = GPIO_PIN_2;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  

  GPIO_InitStruct.Pin = GPIO_PIN_3;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

 

/**************************************************************************/

TIM_HandleTypeDef    TimHandle; //结构体变量

TIM_OC_InitTypeDef sConfig;     //结构体变量

 

TimHandle.Instance = TIM2;  //定时器2 

TimHandle.Init.Prescaler    = (SystemCoreClock / 16000000) -1;//预分频  定时器时钟频率= 系统时钟频率(32Mhz) / (分频系数(32Mhz/16Mhz)-1+1) = 16Mhz

TimHandle.Init.Period       = 1600-1; //1600从0到1600为一个计数周期

TimHandle.Init.ClockDivision = 0;//设置时钟分割

TimHandle.Init.CounterMode   = TIM_COUNTERMODE_UP; //计数模式:向上计数

if(HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)   

{

    /* Initialization Error */

    ErrorHandler();

}

/*********************************************/

//配置PWM通道  多有通道的通用配置

  sConfig.OCMode     = TIM_OCMODE_PWM1;

  sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfig.OCFastMode = TIM_OCFAST_DISABLE;

 

 

  sConfig.Pulse = 1200;  //设置通道1的脉冲值  1200/1600 = 75%

 if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)

  {

     ErrorHandler();

  }

 sConfig.Pulse = 800;  //设置通道2的脉冲值  800/1600 = 50%

 if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_2) != HAL_OK)

  {

     ErrorHandler();

  }

 

 sConfig.Pulse = 400;  //设置通道3的脉冲值  400/1600 = 25%

 if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK)

  {

     ErrorHandler();

  }

 

 sConfig.Pulse = 400;  //设置通道4的脉冲值  400/1600 = 25%

 if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_4) != HAL_OK)

  {

     ErrorHandler();

  }

HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1);//通道1开始生成PWM信号

HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_2);//通道2开始生成PWM信号

HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_3);//通道3开始生成PWM信号

HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_4);//通道4开始生成PWM信号

 

/******************************************************************/

  while (1)

  {

  int i;

  for(i=0; i<1600; i+=4)  //1600/4 = 400个亮度梯度  

  {

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_1,i); //修改占空比 逐渐变亮

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_2,i);

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_3,i);

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_4,i);   

 HAL_Delay(10);

 }

  for(i=1600; i>0; i-=4)

  {

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_1,i);  //逐渐变暗

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_2,i);

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_3,i);

__HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_4,i);

 HAL_Delay(10);

 }

HAL_Delay(1000);   //延迟1秒 一个呼吸灯周期

  }

 

你可能感兴趣的:(STM32HAL库学习)