基于N32G45的定时器PWM输出

描述

​      PWM是一种对模拟信号电平进行​​ ​​数字编码​​​​​的方法。通过高​​ ​​分辨率​​​​计数器的使用,方波的占空比被调制用来对一个具体​​ ​​模拟信号​​​​的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。

     脉宽调制(PWM,Pulse Width Modulation)是利用微处理器的数字输出来对模拟威廉希尔官方网站 进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中 。

     ​PWM的一个优点是从处理器到​​ ​被控系统​​​信号都是数字形式的,再进行数模转换。可将噪声影响降到最低(可以跟电脑一样)。噪声只有在强到足以将逻辑1改变为逻辑0或将逻辑0改变为逻辑1时,也才能对数字信号产生影响。

1.PWM模式

      用户可以使用 PWM 模式产生一个信号,其占空比由 TIMx_CCDATx 寄存器的值决定,其频率由TIMx_AR 寄存器的值决定。 并且取决于 TIMx_CTRL1.CAMSEL 的值, TIM 可以在边沿对齐模式或中央对齐模式下产生 PWM 信号。

      用户可以通过设置 TIMx_CCMODx. OCxMD=110 或设置 TIMx_CCMODx.OCxMD=111 来设置 PWM 模式 1 或 PWM 模式 2。 要使能预加载寄存器,用户必须设置相应的 TIMx_CCMODx.OCxPEN。 然后设置 TIMx_CTRL1.ARPEN 自动重装载预加载寄存器。

      用户可以通过设置 TIMx_CCEN.CCxP 来设置 OCx 的极性。当 TIM 处于 PWM 模式时, TIMx_CNT 和 TIMx_CCDATx 的值总是相互比较。

      只有当更新事件发生时,预加载寄存器才会转移到影子寄存器。 因此,用户必须在计数器开始计数之前通过设置 TIMx_EVTGEN.UDGN 来复位所有寄存器。

1.1 PWM中央对齐模式

      如果用户设置 TIMx_CTRL1.CAMSEL 等于 01、 10 或 11, PWM 中央对齐模式将被激活。 比较标志的设置取决于 TIMx_CTRL1.CAMSEL 的值。 设置比较标志的情况有 3 种,仅当计数器向上计数时,仅当计数器向下计数时,或当计数器向上计数和向下计数时。 用户不应通过软件修改 TIMx_CTRL1.DIR,它是由硬件更新的。

      中央对齐 PWM 波形示例如下,波形设置为: TIMx_AR=8, PWM 模式 1 ,当计数器向下计数对应TIMx_CTRL1.CAMSEL=01 时设置比较标志。

n32g455

使用中央对齐模式时用户应注意的事项如下:

计数器向上或向下计数取决于 TIMx_CTRL1.DIR 的值。 注意不要同时更改 DIR 和 CAMSEL 位

用户在中央对齐模式下不要写计数器,否则会导致意想不到的结果。 例如:

如果写入计数器的值为 0 或者是 TIMx_AR 的值,则方向会被更新,但不会产生更新事件

如果写入计数器的值大于自动重载的值,则方向不会更新

为了安全起见,建议用户在启动计数器之前设置 TIMx_EVTGEN.UDGN 以通过软件生成更新,并且在计数器运行时不要写入计数器。

1.2 PWM 边沿对齐模式

      边沿对齐模式有两种配置,向上计数和向下计数

向上计数

     用户可以设置 TIMx_CTRL1.DIR=0 使计数器向上计数。

    PWM 模式 1 的示例:

    当 TIMx_CNT < TIMx_CCDATx 时, OCxREF 为高电平,否则为低电平。 如果 TIMx_CCDATx 中的比较值大于自动重载值,则 OCxREF 将保持为 1。相反,如果比较值为 0,则 OCxREF 将保持为 0。当 TIMx_AR=8 时, PWM 波形如下:

n32g455

向下计数

      用户可以设置 TIMx_CTRL1.DIR=1 使计数器向下计数。

      PWM 模式 1 的示例:

     当 TIMx_CNT > TIMx_CCDATx 时, OCxREF 为低电平,否则为高电平。 如果 TIMx_CCDATx 中的比较值大于自动重载值,则 OCxREF 将保持为 1。

     注:若第n 个PWM 周期CCDATx 影子寄存器>=AR 值,第n+1 个PWM 周期CCDATx 的影子寄存器值是0。在第n+1 个PWM周期的计数器为0 的时刻,虽然计数器 = CCDATx 影子寄存器的值 = 0, OCxREF =‘0’,但不会产生比较事件。

2.通过PWM输出呼吸灯示例

1.根据N32G45帖子介绍可知LED硬件接口:https://bbs.elecfans.com/jishu_2320004_1_1.html 

n32g455

      2.接下来我我们以D2、D3为例(D2、D3刚才处于TIM3的通道1和通道2上),实现PWM输出控制LED。

      根据参考手册第7章可以看到,我们想要实现该功能,就需要开始TIM3的部分重映射功能。

n32g455

      TIM3通道的部分重映射配置如下:

 

  RCC->APB2PCLKEN|=1<<0;//AFIO
  AFIO->RMP_CFG&=~(0x3<<10);
  AFIO->RMP_CFG|=2<<10;//开启部分重映像
  AFIO->RMP_CFG&=~(0x7<<24);
  AFIO->RMP_CFG|=1<<24;//将PB4设置为普通IO

 

      寄存器相关介绍可查看N32用户手册第7.4章节AFIO寄存器配置。

      3.配置定时器基本功能和PWM模式。

      在完成PWM模式输出时,我们需要先完成定时器的基本功能配置(开定时器时钟、设置预分频系数,设置周期时间)。

     定时器相关寄存器可参考N32用户手册12.4章节。下面列举几个常用寄存器。

控制寄存器1(TIM_CTRL1)

n32g455

      本寄存器主要实现定时器的基本功能配置:设置计数模式、开始定时器等。

预分频器(TIM_PSC)

n32g455

      本寄存器设置定时器的工作频率,例如要实现计数器+1的时长为1us,则时钟的PSC=72-1;

      注意:定时器的时钟线工作频率为72MHZ,即CK_PSC=72MHZ

重装载寄存器(TIM_AR)

n32g455

        重装载寄存器为实现定时器计数周期。

捕获比较寄存器(TIM_CCDAT1)

n32g455

        当为输出模式时,CCDAT寄存器用于设置占空比;当为输入模式时,CCDAT用于保存捕获到的电平时间;

捕获/比较寄存器(TIM_CCMOD)

n32g455

     捕获比较寄存器用于设置输入捕获模式和输出比较模式的通道参数信息。

捕获/比较使能寄存器(TIM_CCEN)

n32g455

      捕获比较使能寄存器用于启动通道、设置有效电平极性。

2.1 定时配置示例

      完成定时器基本功能配置,设置周期时间,设置分频系数,配置通道参数,输出PWM。

 

/***********************************
**
**函数功能:定时器器PWM输出
**TIM3通道引脚: 
**           没有重映射   部分重映射     完全重映射
**  TIM3_CH1    PA6           PB4             PC6
**  TIM3_CH2    PA7           PB5             PC7
**形参:
**    chx --要开启的通道(1 --通道1,2--通道2, 3 --表示开启通道1和通道2)
**    psc --预分频系数
**    ar  --重装载值(即周期时间)
**    ccr --占空比
**  注意:本示例采用部分重映射功能  
**作者:IT_阿水
************************************/
void TIM3_PWM_Out(u8 chx,u16 psc,u16 ar,u16 ccr)
{
  /*1.开时钟*/
  RCC->APB2PCLKEN|=1<<3;//PB
  RCC->APB2PCLKEN|=1<<0;//AFIO
  AFIO->RMP_CFG&=~(0x3<<10);
  AFIO->RMP_CFG|=2<<10;//开启部分重映像
  AFIO->RMP_CFG&=~(0x7<<24);
  AFIO->RMP_CFG|=1<<24;//将PB4设置为普通IO
  /*2.配置GPIO*/
  GPIOB->PL_CFG&=0xFF00FFFF;
  GPIOB->PL_CFG|=0x00BB0000;//通用复用推挽输出模式
  /*3.定时器配置*/
  RCC->APB1PCLKEN|=1<<1;//TIM3
  RCC->APB1PRST|=1<<1;//开启复位时钟
  RCC->APB1PRST&=~(1<<1);//取消复位
  TIM3->CTRL1|=1<<7;
  TIM3->PSC=psc-1;//预分频
  TIM3->AR=ar;//重装载值
  
  /*输出PWM配置*/
  if(chx&0x1)
  {
    TIM3->CCMOD1&=~(0x3<<0);//输出
    TIM3->CCMOD1|=1<<2;//快速使能
    TIM3->CCMOD1|=1<<3;//预加载
    TIM3->CCMOD1|=0x6<<4;//PWM0
    TIM3->CCDAT1=ccr;//占空比,有效电平时间
    TIM3->CCEN|=1<<0;//开启CH1
  }
  if(chx&1<<1)//CH2
  {
    TIM3->CCMOD1&=~(0x3<<8);//输出
    TIM3->CCMOD1|=1<<10;//快速使能
    TIM3->CCMOD1|=1<<11;//预加载
    TIM3->CCMOD1|=0x6<<12;//PWM0  
    TIM3->CCDAT2=ccr;//占空比,有效电平时间
    TIM3->CCEN|=1<<4;//开启CH2
  }
  TIM3->CTRL1|=1<<0;//开启定时器
}

 

2.2 呼吸灯效果实现

      通过调节PWM输出的占空比,实现LED呼吸灯效果。

 

#include "n32g45x.h"
#include 
#include 
#include "led.h"
#include "key.h"
#include "usart.h"
#include "delay.h"
#include "timer.h"
int main()
{
  u8 key_val;
  int time=0;
  u8 flag=0;
  LED_Init();
  KEY_Init();
  USART_Init(115200);
  TIM3_PWM_Out(3,72,400,0);
  printf("串口初始化完成rn");
  while(1)
  {
    key_val=Key_Scan();  
    if(key_val)
    {
      printf("串口+DMA数据发送测试示例!rn");
    }
    if(usart1_flag)
		{
			usart1_rx_buff[usart1_cnt]='�';
			printf("%s,%drn",usart1_rx_buff,usart1_cnt);
      if(strcmp((char *)usart1_rx_buff,"LED1_ON")==0)LED_D1=1;
      else if(strcmp((char *)usart1_rx_buff,"LED1_OFF")==0)LED_D1=0;
      else if(strcmp((char *)usart1_rx_buff,"LED2_ON")==0)LED_D2=1;
      else if(strcmp((char *)usart1_rx_buff,"LED2_OFF")==0)LED_D2=0;
      else if(strcmp((char *)usart1_rx_buff,"LED3_ON")==0)LED_D3=1;
      else if(strcmp((char *)usart1_rx_buff,"LED3_OFF")==0)LED_D3=0;
			usart1_flag=0;
		}  
    if(time>=400)flag=1;
    else if(time<=0)flag=0;
    if(flag)time--;
    else time++;
    TIM3->CCDAT1=time;
    TIM3->CCDAT2=time;
    Delay_Ms(10);
  }    
}
n32g455

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分