ARM嵌入式学习笔记 (六)定时器产生PWM

1.前言

上一篇文章介绍了通用定时器控制LED的闪烁,这篇文章我们来介绍一下STM32单片机中的定时器发生PWM的部分,使用定时器来产生呼吸灯的效果。同样地,我们所使用的硬件设备仍然是STM32RCT6单片机等基础设备,关于单片机的原理图以及LED灯的引脚在前文均已详细介绍,这里我们就不再赘述。

2.PWM详解

定义

PWM,是脉冲宽度调制,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于有效电平的时间占据整个信号周期的百分比。

时序

关于PWM的输入时序,在中文手册中有这样的描述:

PWM的复用引脚

这里以TIM1为例,列出了其四个通道对应的复用功能引脚,也就是说这些引脚可以直接输出PWM信号,其他定时器的四通道复用功能引脚在中文手册中均有详细说明。

PWM的原理

PWM发生的实质就是设定一个比较值,在原波形中大于该设定值的部分将其置一,小于该设定值的部分将其置零,从而能够得到周期性的矩形波,这就是PWM。

3.软件部分

引脚配置

首先是复用引脚的IO配置,这里将IO口配置成复用输出模式。

static void GENERAL_TIMx_GPIO_Config(void) 
{
  GPIO_InitTypeDef GPIO_InitStructure;
	GENERAL_TIM_APBxClock_FUN (GENERAL_TIM_CLK, ENABLE);

  GENERAL_TIM_GPIO_APBxClock_FUN(GENERAL_TIM_GPIO_CLK1|GENERAL_TIM_GPIO_CLK1, ENABLE); 

  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_PIN1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM_PORT1, &GPIO_InitStructure);
	
}

NVIC初始化配置

static void NVIC_Config_PWM(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIMx_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

通用定时器配置

因为是定时器发生PWM,所以要对定时器进行相应配置。这里我们将周期设置为255,预分频系数为1999,将定时器模式设置为PWM1模式,为向上计数,最后再使能相应的PWM输出状态和NVIC的配置。

static void GENERAL_TIMx_Configuration(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	 
  TIM_TimeBaseStructure.TIM_Period = 255; 
  TIM_TimeBaseStructure.TIM_Prescaler = 1999;

  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(GENERAL_TIMx, &TIM_TimeBaseStructure);


  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	

  TIM_OCInitStructure.TIM_Pulse = 0;

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  GENERAL_TIM_OCxInit(GENERAL_TIMx, &TIM_OCInitStructure);

  GENERAL_TIM_OCxPreloadConfig(GENERAL_TIMx, TIM_OCPreload_Enable);  

  TIM_ARRPreloadConfig(GENERAL_TIMx, ENABLE);

  TIM_Cmd(GENERAL_TIMx, ENABLE);  

  NVIC_Config_PWM();

  TIM_ITConfig(GENERAL_TIMx, TIM_IT_Update, ENABLE);
								
}

4.完整代码

main.c

int main(void)
{ 
  GENERAL_TIMx_PWM_Init();  
  while (1)
  {
    
  }
}

这里就是初始化PWM,能够自动输出PWM。

bsp_GeneralTim.c


#include "bsp/GeneralTIM/bsp_GeneralTIM.h" 


uint8_t indexWave[] = {1,1,2,2,3,4,6,8,10,14,19,25,33,44,59,80,107,143,191,255,
                       255,191,143,107,80,59,44,33,25,19,14,10,8,6,4,3,2,2,1,1};


static void GENERAL_TIMx_GPIO_Config(void) 
{
  GPIO_InitTypeDef GPIO_InitStructure;

	GENERAL_TIM_APBxClock_FUN (GENERAL_TIM_CLK, ENABLE);

  GENERAL_TIM_GPIO_APBxClock_FUN(GENERAL_TIM_GPIO_CLK1|GENERAL_TIM_GPIO_CLK1, ENABLE); 

  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_PIN1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM_PORT1, &GPIO_InitStructure);
	
}


static void NVIC_Config_PWM(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
 
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIMx_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}


/*
 * TIMxCLK/CK_PSC --> TIMxCNT --> TIMx_ARR --> TIMxCNT ÖØмÆÊý
 *                    TIMx_CCR(µçƽ·¢Éú±ä»¯)
 * ÐźÅÖÜÆÚ=(TIMx_ARR +1 ) * ʱÖÓÖÜÆÚ
 * Õ¼¿Õ±È=TIMx_CCR/(TIMx_ARR +1)
 *    _______    ______     _____      ____       ___        __         _
 * |_|       |__|      |___|     |____|    |_____|   |______|  |_______| |________|
 *
 */
static void GENERAL_TIMx_Configuration(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;	 

  TIM_TimeBaseStructure.TIM_Period = 255; 

  TIM_TimeBaseStructure.TIM_Prescaler = 1999;

  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(GENERAL_TIMx, &TIM_TimeBaseStructure);


  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	

  TIM_OCInitStructure.TIM_Pulse = 0;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  GENERAL_TIM_OCxInit(GENERAL_TIMx, &TIM_OCInitStructure);
  GENERAL_TIM_OCxPreloadConfig(GENERAL_TIMx, TIM_OCPreload_Enable);  

  TIM_ARRPreloadConfig(GENERAL_TIMx, ENABLE);
  TIM_Cmd(GENERAL_TIMx, ENABLE);  
  NVIC_Config_PWM();
  TIM_ITConfig(GENERAL_TIMx, TIM_IT_Update, ENABLE);
								
}


void GENERAL_TIMx_PWM_Init(void)
{
	GENERAL_TIMx_GPIO_Config();
	GENERAL_TIMx_Configuration();	
}

5.实验效果

呼吸灯

6.结束语

本次实验讲解了使用Stm32的定时器发生PWM产生呼吸灯的效果,这也是STM32单片机应用很多的一部分内容,希望以上内容对各位朋友有所帮助。

最后,欢迎大家在评论区留言批评指正。谢谢!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值