16.【NXP 号令者RT1052】开发——实战-FlexPWM 输出

16.【NXP 号令者RT1052】开发------实战-FlexPWM 输出

我们之前介绍了如何使用 RT1052 的四定时器 QTMR4 的通道 3 来产生 PWM 输出。RT1052 内部有一个非常牛逼的 PWM 模块:eFlexPWM(也叫 FlexPWM),其功能非常多,本章我们将向大家介绍如何使用 FlexPWM2 的模块 3 来产生 PWM 输出。在本章中,我们将使用 FlexPWM2 的模块 3 产生 PWM 来控制 DS1 的亮度。

16.1 FlexPWM 简介

FlexPWM 全称是:Enhanced Flex Pulse Width Modulator,也叫 eFlexPWM,即增强型灵活的脉宽调制器。RT1052 内部有 4 个这种脉宽调制器(FlexPWM)模块,每个脉宽调制器模块有有 4 个子模块,每个子模块可以用于控制单个半桥功率计,且提供故障保护通道。脉宽调制器(FlexPWM)模块可以组成多种开关组合方式,可生成高度复杂的波形,它可以用于控制各种类型的电机,也是各种开关电源(SMPS)拓扑模型的理想控制器。

FlexPWM 脉宽调制器的主要特点如下:

  1. 每个脉宽调制器(FlexPWM)有 4 个子模块;
  2. 16 位精度,支持中央对齐、边沿对齐和非对称 PWM 输出;
  3. 分数 PWM 时钟生成器可生成高精度 PWM 周期和占空比;
  4. 可工作在互补输出模式或独立工作模式;
  5. 每个 PWM 输出双沿(上升沿/下降沿)可独立控制;
  6. 可与外部硬件或其他 PWM 子模块同步;
  7. 双缓冲 PWM 寄存器,可设置 1~16 的整数重载率或半周期重载;
  8. 支持 PWM 输出的双切换(周期和占空比);
  9. 故障输入可以指定连接控制多个 PWM 输出
  10. 独立的可编程 PWM 输出极性设置;
  11. 独立的死区时间设置;
  12. 增强 型双沿(上升沿/下降沿)捕获功能;

由图可知,FlexPWM 的每个子模块由 1 个预分频器、1 个 16 位计数器和 6 个 16 位比较器等部分组成,主要有 3 个输出信号:PWM_X、PWM_A 和 PWM_B,其中 PWM_A 和 PWM_B可以用来输出 PWM/做输入捕获,而 PWM_X 是一个辅助输出,可以独立的用作 PWM 信号,也可以用作输入捕获,我们一般使用 PWM_A 或 PWM_B 来输出 PWM 波形。

图中①处,是故障信号输入,来自模块总线,由 XBAR1 的输出通道来控制,要想正常输出 PWM,必须设置合适的故障状态,或者禁止故障检测功能,否则将无法正常输出 PWM!下图是 FlexPWM 子模块的输出逻辑:

图中 PWM23 和 PWM45 分别由 VAL2/VAL3 和 VAL4/VAL5 控制占空比,来自经过死区处理后的信号,本例程没用到死区控制,所以在这里对死区不做介绍。由图可知,PWM23和PWM45的输出处理路径是一样的,只是控制信号不同而已,我们以 PWM23 为例,介绍其具体的输出过程:
,用于选择输出到下一级的是 PWM23 还是 PWMAFS[0]的值,由 Disable PWM_A 信号控制,当该信号为 0 的时候,PWM23 输出到下一级,否则 PWMAFS[0]的值输出到下一级。很明显,要正常输出 PWM,必须 Disable PWM_A 信号必须为 0。PWMAFS[0]来自 SMx_OCTRL(x=0~3)寄存器。

,用于设置是否屏蔽 PWM 输出,当 MASKA=0 时,可以正常输出;当 MASKA=1 时,屏蔽 PWM 输出。MASKA 来自 PWMx_MASK(x=0~3)寄存器。

,用于设置输出有效信号极性。当 POLA=0 时,输出信号不反相;当 POLA=1 时,输出信号反相;POLA 来自 SMx_OCTRL(x=0~3)寄存器。

,用于控制 PWM 最终是否输出到 PWM_A,由 PWM_A_EN、PWMAFS[1]和 Disable PWM_A 三个信号共同控制。PWM_A_EN 由 PWMx_OUTEN(x=0~3)寄存器设置,PWMAFS[1]来自 SMx_OCTRL(x=0~3)寄存器。

,Disable PWM_A 来自故障保护单元,它由 FAULT0~3 和 Wait Mode、Debug Mode 和Stop Mode 等信号控制。我们待会重点介绍。

因此可知,PWM_A 要像正常输出来自 PWM23 的 PWM 信号,就必须设置好相应的控制位/信号:Disable PWM_A 必须为 0,MASKA 必须为 1,PWM_A_EN 必须为 1。对于 PWM_B的输出,同样也要设置类似的位/信号。

Disable PWM_A 信号来源如图:

由图可知 Disable PWM_A 主要来自两个方向:

1,故障输出(FAULT0~3);

2,MCU 工作模式(Wait/Debug/Stop)。正常工作时,我们只需要考虑故障输出,因此我们重点介绍下图中标注的①~⑥。

①,二或门,只要故障输出或 MCU 工作模式输出有效,则 Disable PWM_A 有效(=1)。

②,四或门,来自四个故障信号:FAULT0~FAULT3,只要任意一个故障信号有效(=1),则输出有效。

③,故障 0(FAULT0)屏蔽位(DISA0),用于设置是否屏蔽来自故障 0(FAULT0)的信号,如果我们不想让故障 0 控制我们的 PWM 输出,则可以设置该位为 0。DISA0 来自 SMx_DISMAP0(x=0~3),同样的 DISA1~DISA3 也是由该寄存器控制,分别控制 FAULT1~FAULT3 的屏蔽。注意:这些位默认都是 1 的!

④,故障输入 0 到 Disable PWM_A 输出组合路径屏蔽位,当 NOCOMB0 为 0 时,FAULT0 有两条路径可以输出到 Disable PMW_A:1,通过 NOCOMB0 与门;2,通过 FILT 过滤器;当 NOCOMB0 为1 时,则只能通过 FLIT 这条路径输出到 Disable PWM_A。NOCOMB0 来自 PWMx_FCTRL2(x=03)寄存器。同样的,NOCOMB13 也是来自该寄存器。

⑤,故障信号 0(FAULT0),来自 XBAR1 的输出。这些故障信号可以通过 XBAR1 映射到相关外部 IO 口,从而实现故障检测。具体的映射关系,详见《RT1050 参考手册》第 246 页,Table 3-6。

本章,我们通过 PWM2 的子模块 3 来产生 PWM 控制 DS1 的亮度,并不需要用到故障检测功能,所以,我们需要屏蔽故障(通过 SMx_DISMAP0 或 PWMx_FCTRL20 寄存器设置),或者设置故障值为正常(通过 XBAR1 设置)。一般我们通过设置 SMx_DISMAP0 寄存器(全 0)来屏蔽故障检测功能。

接下来,我们介绍一下 FlexPWM 子模块的时钟部分

此图比较简单,我们重点介绍图中标注的①~③,这三个部分。

①,时钟源选择器,由 CLK_SEL[1:0]位设置,我们一般选择 IPBus 时钟作为时钟源,IPBus时钟来自 IPG_CLK_ROOT(150Mhz)。CLK_SEL[1:0]来自 SMx_CTRL2(x=0~3)寄存器。

②,时钟预分频器,这是 8 位预分频器,但是只能设置固定的几个分频值,不能随意设置!其分频值可以是:1/2/4/8/16/32/64/128 等 7 个值,通过 PSRC[2:0]设置。PSRC[2:0]来自SMx_CTRL(x=0~3)寄存器。

③,时钟使能开关,由 RUN 位控制,如果 RUN 位为 1,则可以正常输出时钟;如果 RUN 位

为 0,则禁止输出时钟;RUN 位来自 PWMx_MCTRL(x=0~3)寄存器。

通过图中的①~③,我们就可以自由设置和选择子模块时钟,具体的设置,需要根据实际使用需求来确定。

经过以上学习,我们了解了 FlexPWM 的时钟设置、输出逻辑、故障管理和整体组成等,接下来,我们看看 FlexPWM 子模块产生 PWM 的具体过程,如图所示:

FlexPWM 子模块的计数器(CNT),只能工作在向上计数模式(图中类似三角波的波形),上图是 FlexPWM 子模块生成中央对齐 PWM 的时序图,因为计数方向是不可改变的,只能修改图中的③~⑨来实现中央对齐 PWM 的输出。事实上中央对齐、边沿对齐和非对称 PWM 的输出,都是通过修改这几个寄存器来实现的。注意:FlexPWM 是支持有符号操作的,如果 INIT 的值刚好和 VAL1 的值相反(值相同,符号相反),则表示是有符号模式,否则表示是无符号模式。

我们重点分析下图 17.1.5 的实现原理,为了方便说明,我们在图中标注了①~⑨。

①,PWM_A 波形,其波形是以 VAL0 的值中心对称的。PWM_A 波形由 VAL2 控制上升沿,由VAL3 控制下降沿,只要 VAL0-VAL2=VAL3-VAL0,则是中心对称模式。

②,PWM_B 波形,其波形也是以 VAL0 的值中心对称的。PWM_B 波形由 VAL4 控制上升沿,由VAL5 控制下降沿,只要 VAL0-VAL4=VAL5-VAL0,则是中心对称模式。

③,INIT 寄存器,用于设置 CNT 的初始值。这是一个有符号 16 位寄存器,它可以设置成负数或者正数,图 17.1.5 种设置的 INIT 值为 0XFF00,即-256,是负数。该寄存器用于在每个PWM 周期的启动时初始化 CNT 值(也就是 CNT 达到 VAL1 溢出后,都会将 INIT 的值重新赋值到CNT)。该寄存器和 VAL1 共同决定是否工作在有符号模式,只要这两个寄存器的值不刚好相反,则是工作在无符号模式,一般建议用无符号模式。

④,VAL0 寄存器,用于设置 CNT 的中间值。这是一个有符号 16 位寄存器,该寄存器的值介于 INIT 和 VAL1 之间,一般等于(VAL1-INIT)/2。

⑤,VAL1 寄存器,用于设置 CNT 计数器的最大值。这是一个有符号 16 位寄存器,该寄存器和 INIT 寄存器共同决定是否工作在有符号模式。

⑥,VAL2 寄存器,用于控制 PWM_A 的上升沿。这是一个有符号 16 位寄存器,通过它可以决定 PWM_A 波形高电平的起始时间。

⑦,VAL3 寄存器,用于控制 PWM_A 的下降沿。这是一个有符号 16 位寄存器,通过它可以决定PWM_A 波形高电平的结束时间。INIT、VAL1、VAL2 和 VAL3 共同决定了 PWM_A 的波形。

⑧,VAL4 寄存器,用于控制 PWM_B 的上升沿。这是一个有符号 16 位寄存器,通过它可以决定 PWM_B 波形高电平的起始时间。

⑨,VAL5 寄存器,用于控制 PWM_B 的下降沿。这是一个有符号 16 位寄存器,通过它可以决定 PWM_B 波形高电平的结束时间。INIT、VAL1、VAL4 和 VAL5 共同决定了 PWM_B 的波形。注意:INIT、VAL0~VAL5 等七个寄存器都是有缓冲的,我们写入这些寄存器的值并不会立即生效,必须设置 PWMx_MCTRL(x=0~3)寄存器的 LDOK 位,然后在下一个 PWM 周期开始的时候,会将写入这些寄存器的值加载到缓冲寄存器里面,然后设置的值才会生效。

上图 中是中央对齐模式的设置,如果我们调整 INIT 和 VAL0~VAL5 的值,则可以实现很多种不同模式的 PMW 波形输出。详见《RT1050 参考手册》第 1425 页 28.5.1 节。

本章,我们将使用 PWM2 子模块 3 的 PWM_B 输出来控制 DS1 的亮度,实现类似第 15 章的控制效果,即:DS1 不停的由暗变到亮,然后又从亮变到暗。

好的,我来帮你把这部分内容整理成 Markdown 格式,保持代码原样不动,仅仅排版清晰:


RT1052 FlexPWM2 配置步骤

1. 设置 GPIO3_IO03 复用功能

c 复制代码
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_03_FLEXPWM2_PWMB03,0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_FLEXPWM2_PWMB03,0x10B0);

2. 使能 FlexPWM2 时钟

c 复制代码
CLOCK_EnableClock(kCLOCK_Pwm2)

此函数会被 PWM_Init 调用,无需显式调用。


3. 初始化 FlexPWM2

c 复制代码
status_t PWM_Init(PWM_Type *base, 
                  pwm_submodule_t subModule, 
                  const pwm_config_t *config)
  • base :指定 PWM,本例为 PWM2
  • subModule :子模块选择,本例为 kPWM_Module_3
  • config :配置结构体 pwm_config_t
示例配置
c 复制代码
pwm_config_t pwm2sm3_config; //PWM2 模块 3 配置结构体
//初始化 PWM2 模块 3 的通道 B
PWM_GetDefaultConfig(&pwm2sm3_config); //先初始化为默认配置
pwm2sm3_config.clockSource = kPWM_BusClock; //时钟源为 IP BUS=150MHz
pwm2sm3_config.prescale = kPWM_Prescale_Divide_128; //设置 128 分频
pwm2sm3_config.reloadLogic = kPWM_ReloadPwmFullCycle; //全周期更新
pwm2sm3_config.pairOperation = kPWM_Independent; //PMWA PWMB 独立模式
PWM_Init(PWM2, kPWM_Module_3, &pwm2sm3_config); //初始化 PWM2 模块 3

4. 关闭故障检测功能

c 复制代码
PWM2->SM[3].DISMAP[0] = 0; 

5. 配置 PWM2 的 PWMB 通道

c 复制代码
status_t PWM_SetupPwm(PWM_Type * base,
                      pwm_submodule_t subModule,
                      const pwm_signal_param_t * chnlParams,
                      uint8_t numOfChnls,
                      pwm_mode_t mode,
                      uint32_t pwmFreq_Hz,
                      uint32_t srcClock_Hz)
示例配置:10KHz,50% 占空比
c 复制代码
u32 sourceclock;
//设置 PWM2_PWMB 通道
sourceclock = CLOCK_GetFreq(kCLOCK_IpgClk);
//PWMB
pwm_ignal.pwmChannel = kPWM_PwmB; //PWM 通道 B
pwm_ignal.level = kPWM_HighTrue; //高电平有效
pwm_ignal.dutyCyclePercent = 50; //50%占空比
//设置 PWM2,中央对齐模式
PWM_SetupPwm(PWM2, //PWM2
             kPWM_Module_3, //PWM2 的子模块 3
             &pwm_ignal, //PWM 通道配置参数结构体
             1, //配置一个 PWM 通道
             kPWM_CenterAligned, //无符号中央对齐模式
             10000, //PWM 频率为 10KHz
             sourceclock); //PWM 时钟源为 150MHz
 
PWM_SetPwmLdok(PWM2, kPWM_Control_Module_3, true); //设置 PWM 的 load ok 位

6. 开启 PWM2

c 复制代码
PWM_StartTimer(PWM2, kPWM_Control_Module_3); //开启 PWM

7. 动态更新占空比

c 复制代码
void PWM_UpdatePwmDutycycle(PWM_Type * base,
                            pwm_submodule_t subModule,
                            pwm_channels_t pwmSignal,
                            pwm_mode_t currPwmMode,
                            uint8_t dutyCyclePercent)
  • pwmSignal:选择通道 (kPWM_PwmB / kPWM_PwmA / kPWM_PwmX)
  • currPwmMode:当前 PWM 对齐模式
  • dutyCyclePercent:占空比百分比 (0~100)

16.2 硬件设计

本实验用到的硬件资源有:

  1. 指示灯 DS1
    本章将通过 PWM2 子模块 3 的 PWM_B 来控制 DS1 的亮度,DS1 是连接到 GPIO3_IO03(P303)上的,这个前面已经有介绍了。而 PWM2 子模块 3 的 PWM_B 的输出是可以连接在GPIO3_IO03(P303)上的,刚好和 DS1 是同一个脚,所以硬件不需要做任何变化,直接写代码即可。

16.3 软件设计

本章,我们依旧是在前一章的基础上修改代码,先打开之前的工程,在 HARDWARE 文件夹下新建 FLEXPWM 文件夹。然后打开 USER 文件夹下的工程,新建一个 flexpwm.c 的文件和flexpwm.h 的头文件,保存在 FLEXPWM 文件夹下,并将 FLEXPWM 文件夹加入头文件包含路径。

flexpwm.c

c 复制代码
#include "flexpwm.h"
#include "lpuart.h"

pwm_config_t pwm2sm3_config;    //PWM2模块3配置结构体

//初始化FLEXPWM,PWM2的模块3的通道A和B
//通过PWM2的模块3在通道A和B上面产生2路PWM输出.
//即在GPIO3_IO02和GPIO3_IO03上面输出PWM.
//psc : 预分频器,0~7,表示2^psc分频.
//fre : 频率
//duty:占空比
void PWM2_SM3_PWMAB_Init(u16 psc,u32 fre,u8 duty)
{
    u32 sourceclock;
    pwm_signal_param_t pwm_ignal;
    pwm_clock_prescale_t pwm_prescale=(pwm_clock_prescale_t)psc; //分频
    
	//IO功能设置
	IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_03_FLEXPWM2_PWMB03,0);   
  IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_02_FLEXPWM2_PWMA03,1);   
    
	//配置IO引脚GPIO_SD_B1_02和GPIO_SD_B1_03的功能
	//低转换速度,驱动能力为R0/6,速度为100Mhz,关闭开路功能,使能pull/keepr
	//选择keeper功能,下拉100K Ohm,关闭Hyst
    IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_FLEXPWM2_PWMB03,0x10B0);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_02_FLEXPWM2_PWMA03,0x10B0);
    
    //初始化PWM2 模块3的通道B
    PWM_GetDefaultConfig(&pwm2sm3_config);              //先初始化为默认配置
    pwm2sm3_config.clockSource=kPWM_BusClock;           //时钟源为IP BUS=IPG_CLK_ROOT=150MHz
    pwm2sm3_config.prescale=pwm_prescale;               //设置分频
    pwm2sm3_config.reloadLogic=kPWM_ReloadPwmFullCycle; //全周期更新
    pwm2sm3_config.pairOperation=kPWM_Independent;      //PMWA PWMB独立模式
    PWM_Init(PWM2,kPWM_Module_3,&pwm2sm3_config);       //初始化PWM2模块3

    //屏蔽故障检测功能
    PWM2->SM[3].DISMAP[0]=0;     
    
    //设置PWM2B通道
    sourceclock=CLOCK_GetFreq(kCLOCK_IpgClk);
    //PWMB
    pwm_ignal.pwmChannel=kPWM_PwmB;                     //PWM通道B
    pwm_ignal.pwmChannel=kPWM_PwmA;                     //PWM通道A
    pwm_ignal.level=kPWM_HighTrue;                      //高电平有效
    pwm_ignal.dutyCyclePercent=duty;                    //占空比


    
    //设置PWM2,中央对齐模式
    PWM_SetupPwm(PWM2,kPWM_Module_3,&pwm_ignal,2,kPWM_CenterAligned,fre,sourceclock);//使用了两个通道
    
    PWM_SetPwmLdok(PWM2,kPWM_Control_Module_3,true);    //设置PWM的load ok位
    PWM_StartTimer(PWM2,kPWM_Control_Module_3);         //开启定时器

}

//更新PWM2占空比
//duty:占空比
void PWM2_SM3_DutySet(u8 duty) 
{
    PWM_UpdatePwmDutycycle(PWM2,kPWM_Module_3,kPWM_PwmA,kPWM_CenterAligned,duty); //更新PWMB占空比
    PWM_UpdatePwmDutycycle(PWM2,kPWM_Module_3,kPWM_PwmB,kPWM_CenterAligned,duty); //更新PWMB占空比
    PWM_SetPwmLdok(PWM2,kPWM_Control_Module_3,true);    //设置PWM的load ok位
}

此部分代码就二个函数:PWM2_SM3_PWMAB_Init 和 PWM2_SM3_DutySet,先来看一下函数 PWM2_SM3_PWMAB_Init,此函数有 3 个参数:
psc :用于设置预分频系数,取值范围:0~7,代表 1~128 分频。
fre :PWM 的频率,单位为 Hz,如要设置频率为 10KHz 的 PWM,此参数就设置为 10000。
duty:要设置的占空比(百分比),0~100 表示 0%~100%。函数 PWM2_SM3_DutySet 用来修改 PWM2 子模块 3 的 PWMB 通道的占空比,所以此函数只有一个参数:duty,此参数就是要设置的占空比(百分比),0~100 表示占空比 0%~100%。

flexpwm.h

c 复制代码
#ifndef _FLEXPWM_H
#define _FLEXPWM_H
#include "sys.h"

void PWM2_SM3_PWMAB_Init(u16 psc,u32 fre,u8 duty);	//PWM2 SM3 PWM输出初始化函数
void PWM2_SM3_DutySet(u8 duty);     //设置PWM2_SM3两个通道的占空比
#endif

main.c

c 复制代码
#include "sys.h"
#include "lpuart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdog.h"
#include "rtwdog.h"
#include "gptimer.h"
#include "pitimer.h"
#include "qtimer.h"
#include "pwm.h"
#include "xbar.h"
#include "flexpwm.h"

int main(void)
{
    u8 key=0;
	MPU_Memory_Protection();    //初始化MPU
	RT1052_Clock_Init();	    //配置系统时钟
	DELAY_Init(600);		    //延时函数初始化
	LPUART1_Init(115200);       //初始化串口1
    RT1052_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//优先级分组4
#ifdef LED_DEBUG
	u8 led0sta=1,led1sta=1;     //LED0,LED1的当前状态
	LED_Init();				    //初始化LED
#endif
#ifdef KEY_DEBUG
	KEY_Init();                 //初始化KEY
#endif
#ifdef LPUART_DEBUG
    u8 len;					//接收数据长度
    u16 times=0;            //延时计数器
    LED0(0);					//先点亮红灯 
#endif
#ifdef EXTIX_DEBUG
    EXTIX_Init();			    //初始化外部中断
#endif
#ifdef WDOG_DEBUG
    WDOG1_Init(3,2);		    //初始化看门狗1,2秒溢出,提前1秒进入中断,方便喂狗
	LED0(0);               	    //先点亮LED灯
    delay_ms(300);				//延时300ms再初始化看门狗,LED0的变化"可见"
#endif
#ifdef RTWDOG_DEBUG
    LED_Init();				    //初始化LED 
    KEY_Init();                 //初始化KEY
    delay_ms(100);         	    //延时100ms再初始化看门狗,LED0的变化"可见"
	MYRTWDOG_Init(1,0,32768,0);	//初始化RT看门狗,1秒溢出,非窗口模式
	LED0(0);               	    //先点亮LED灯
#endif
#ifdef GPT1_DEBUG
    LED_Init();				    //初始化LED  
    KEY_Init();                 //初始化按键
	GPT1_Int_Init(3750-1,10000); //设置GPT1 0.5秒钟产生一次中断
#endif
#ifdef PIT_DEBUG
    LED_Init();				    //初始化LED  
	PIT_CH0_Int_Init(75000000/2);	//设置PIT 0.5秒钟产生一次中断
#endif
#ifdef QTMR_DEBUG
    KEY_Init();                 //初始化按键
	LED_Init();				            //初始化LED
	QTMR1_CH0_Int_Init(15,46875);	//设置QTMR1 0.04秒钟产生一次中断
#endif
#ifdef QTMR_PWM_DEBUG
    u8 dir=1; 
	u16 led1pwmval=0;    
    gpio_pin_config_t led_config;

    LED_Init();				    //初始化LED  
    KEY_Init();                 //初始化按键
    
    //初始化PWM,定时器时钟为:150/64=2.34375Mhz,设置频率为5Khz,50%占空比
	QTMR4_CH3_PWM_Init(14,5000,0);

    //设置P103为输入模式,防止干扰PWM
    led_config.direction=kGPIO_DigitalInput;	//输出
	led_config.interruptMode=kGPIO_NoIntmode;	//不使用中断功能
	led_config.outputLogic=0;					//默认高电平,LED灯关闭
	GPIO_PinInit(GPIO1,3,&led_config); 	        //初始化GPIO1_3
#endif
#ifdef XBAR_DEBUG
    u8 dir=1; 
	u16 led1pwmval=0;  
    
    //初始化PWM,定时器时钟为:150/64=2.34375Mhz,设置频率为5Khz,50%占空比
	QTMR4_CH3_PWM_Init(14,5000,50); 
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_03_XBAR1_INOUT17,0);	//GPIO_AD_B0_03配置为ALT1,即XBAR1_INOUT17
    XBARA1_Signal_Set(kXBARA1_InputQtimer4Tmr3Output,kXBARA1_OutputIomuxXbarInout17);   //QTMR4_CH3输出到XBARA1_INOUT17上面.
                                                                                        //即:通过GPIO_AD_B0_03(GPIO1_IO03)输出QMR4_CH3的波形.
#endif
    u8 dir=1; 
	u16 led1pwmval=0;  

    LED_Init();				    //初始化LED  
    KEY_Init();                 //初始化按键
	PWM2_SM3_PWMAB_Init(7,1000,50);    //初始化PWM2,128分频,1K频率,50%占空比
    while(1)
    {
        delay_ms(10);	 
		if(dir)led1pwmval++;
		else led1pwmval--;	 
 		if(led1pwmval>=100)dir=0;
		if(led1pwmval==0)dir=1;	 
        PWM2_SM3_DutySet(led1pwmval); 
#ifdef XBAR_DEBUG
        delay_ms(10);	 
		if(dir)led1pwmval++;
		else led1pwmval--;	 
        if(led1pwmval>=100)dir=0;
		if(led1pwmval==0)dir=1;	 
        QTMER4CH3_PWM_DutySet(14,5000,led1pwmval);
#endif
#ifdef QTMR_PWM_DEBUG
        delay_ms(10);	 
		if(dir)led1pwmval++;
		else led1pwmval--;	 
        if(led1pwmval>=100)dir=0;
		if(led1pwmval==0)dir=1;	 
        QTMER4CH3_PWM_DutySet(14,5000,led1pwmval);
#endif
#ifdef QTMR_DEBUG
        LED0_Toggle;
		delay_ms(1000);
#endif
#ifdef PIT_DEBUG
        LED0_Toggle;
		delay_ms(1000);
#endif
#ifdef GPT1_DEBUG
        LED0_Toggle;
		delay_ms(1000);
#endif
#ifdef RTWDOG_DEBUG
        key=KEY_Scan(0);
		if(key==WKUP_PRES)		//如果按键按下,则喂狗.
		{
			RTWDOG_Feed();
		} 
		delay_ms(10);
#endif
#ifdef WDOG_DEBUG
        LED0(1);				//关闭DS0,如不复位,DS0将一直处于关闭状态.
		delay_ms(100);
#endif
#ifdef EXTIX_DEBUG
        printf("Int example driver!\r\n");
		delay_ms(1000);
#endif
#ifdef KEY_DEBUG
        key=KEY_Scan(0); 		    //得到键值
        if(key)
        {	
            switch(key)
            {				 
                case WKUP_PRES:	//控制LED0,LED1互斥点亮
                    led1sta=!led1sta;
                    led0sta=!led1sta;
                    break;
                case KEY2_PRES:	//控制LED0翻转
                    led0sta=!led0sta;
                    break;
                case KEY1_PRES:	//控制LED1翻转	 
                    led1sta=!led1sta;
                    break;
                case KEY0_PRES:	//同时控制LED0,LED1翻转 
                    led0sta=!led0sta;
                    led1sta=!led1sta;
                    break;
            }
            LED0(led0sta);		//控制LED0状态
            LED1(led1sta);		//控制LED1状态
        }else delay_ms(10);
#endif // KEY_DEBUG
#ifdef LPUART_DEBUG
        if(LPUART_RX_STA&0x8000)
		{					   
			len=LPUART_RX_STA&0x3fff;//得到此次接收到的数据长度
			printf("\r\n发送的消息为:\r\n");
			LPUART_WriteBlocking(LPUART1,LPUART_RX_BUF,len);//发送接收到的数据
			printf("\r\n\r\n");//插入换行
			LPUART_RX_STA=0;
		}else
		{
			times++;
			if(times%5000==0)
			{
				printf("\r\nALIENTEK RT1052开发板 串口实验\r\n");
			}
			if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
			if(times%30==0)LED0_Toggle;//闪烁LED,提示系统正在运行.
			delay_ms(10);   
		}
#endif // LPUART_DEBUG
	}
}

main 函数和之前的代码类似,通过 PWM2_SM3_PWMAB_Init 设置 PWM2 子模块 3 的相关参数,完成初始化设置,这里我们设置 PWM 频率为 1KHz,占空比为 50%。在死循环里面,我们通过 led1pwmval 的值来控制 DS1 的亮度。led1pwmval 的值从 0 变到300,然后又从 300 变到 0,如此循环,因此 DS1 的亮度也会跟着从暗变到亮,然后又从亮变到暗。至此,我们的软件设计就完成了。

总结

FlexPWM(eFlexPWM)是 RT1052 内部增强型的脉宽调制器模块,专门用于产生高精度、灵活的 PWM 波形。它支持中央对齐、边沿对齐和非对称输出,具备故障保护、死区控制、双缓冲寄存器、独立或互补输出等功能,可用于电机控制、开关电源等复杂应用场景。本章通过配置 FlexPWM2 子模块 3 的 PWMB 通道输出 PWM,动态调整占空比来控制 DS1 的亮度,实现 LED 从暗到亮再从亮到暗的循环变化。

OK!谢谢大家!

相关推荐
猫猫的小茶馆1 小时前
【ARM】ARM的介绍
c语言·开发语言·arm开发·stm32·单片机·嵌入式硬件·物联网
猫猫的小茶馆1 小时前
【PCB工艺】数模电及射频电路基础
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·pcb工艺
点灯小铭2 小时前
基于单片机的智能药物盒设计与实现
数据库·单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
梓德原2 小时前
【基础】详细分析带隙型稳压电路的工作原理
单片机·嵌入式硬件·物联网
国科安芯3 小时前
航天医疗领域AS32S601芯片的性能分析与适配性探讨
大数据·网络·人工智能·单片机·嵌入式硬件·fpga开发·性能优化
小李做物联网4 小时前
【物联网毕业设计】60.1基于单片机物联网嵌入式项目程序开发之图像厨房监测系统
stm32·单片机·嵌入式硬件·物联网
贝塔实验室5 小时前
新手如何使用Altium Designer创建第一张原理图(三)
arm开发·单片机·嵌入式硬件·fpga开发·射频工程·基带工程·嵌入式实时数据库
@good_good_study5 小时前
STM32 ADC多通道采样实验
stm32·单片机·嵌入式硬件
Darken035 小时前
什么是“位带”?;在STM32单片机中有什么作用?
stm32·单片机·嵌入式硬件
清风6666666 小时前
基于单片机的智能豆浆机设计(加热打浆熬煮自动控制与防干溢保护)
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业