NXP RT1052 eFlexPWM—灵活的增强型 PWM例程

 

参考IMX+RT开发实战指南

eFlexPWM 初始化结构体详解

结构体成员用于设置PWM 基本工作参数,并由 FLEXPWM 初始化配置函数调用,初始化结构体中设定的参数将会设置定时器相应的寄存器,达到配置定时器工作环境的目的。
 

/*!
 * @brief PWM config structure
 *
 * This structure holds the configuration settings for the PWM peripheral. To initialize this
 * structure to reasonable defaults, call the PWM_GetDefaultConfig() function and pass a
 * pointer to your config structure instance.
 *
 * The config struct can be made const so it resides in flash
 */
typedef struct _pwm_config
{
    bool enableDebugMode;                    /*!< true: PWM continues to run in debug mode;
                                                  false: PWM is paused in debug mode */
    bool enableWait;                         /*!<true: PWM 在等待模式下正常运行6 false: PWM 在等待模式下停止运行 true: PWM continues to run in WAIT mode;
                                                  false: PWM is paused in WAIT mode */
    uint8_t faultFilterCount;                /*!< 设置故障过滤计数值Fault filter count */
    uint8_t faultFilterPeriod;               /*!< 故障滤波周期;值为 0 不进行滤波Fault filter period;value of 0 will bypass the filter */
    pwm_init_source_t initializationControl; /*!< 选择 PWM 初始化信号Option to initialize the counter */
    pwm_clock_source_t clockSource;          /*!< 选择 PWM 计数器的时钟源 Clock source for the counter */
    pwm_clock_prescale_t prescale;           /*!< 选择时钟分频Pre-scaler to divide down the clock */
    pwm_chnl_pair_operation_t pairOperation; /*!<PWM_A 与 PWM_B 工作模式选择,互补或者独立 Channel pair in indepedent or complementary mode */
    pwm_register_reload_t reloadLogic;       /*!< 选择何时将新值加载到内部寄存器PWM Reload logic setup */
    pwm_reload_source_select_t reloadSelect; /*!< 选择 PWM 加载信号Reload source select */
    pwm_load_frequency_t reloadFrequency;    /*当 reloadLogic 不等于kPWM_ReloadImmediate 时,用于设置加载频率!< Specifies when to reload, used when user's choice
                                                  is not immediate reload */
    pwm_force_output_trigger_t forceTrigger; /*选择强制输出信号源!< Specify which signal will trigger a FORCE_OUT */
} pwm_config_t;

 enableDebugMode 与 enableWait 用于设置在调试模式(DebugMode)或者等待模式(Wait Mode)是否使能 PWM 输出。通过配置寄存器决定在调试模式下或等待模式下是否使能 PWM 输出。我们在配置结构体中根据需要选择即可,无需关心具体操作了那个寄存器的那些位。


 faultFilterCount 与 faultFilterPeriod 如果使用了 FLEXPWM 故障检测功能,并且选择使用故障滤波功能,则需要设置滤波周期与滤波计数值。故障滤波周期(faultFilterPeriod), 以 IPBus 时钟周期为单位,如果设置为 0,表示不使用故障滤波功能。 每个输入按此字段指定的值进行多次采样, 采样次数 由 faultFilterCount 指定,可选范围 0 到 7,代表 3 到 10 个样本。例如 faultFilterPeriod = 100, faultFilterCount = 7,检测到故障信号之后,故障滤波器每 100 个 IPBus 时钟周期检测一次是否存在故障信号,这样连续检测 10 次,如果这 10 次全都检测到了故障信号的存在则表示故障确实存在,之后禁止相应的PWM 输出。

 initializationControl,用于选择 FLEXPWM 子模块的计数器初始化信号(也可称为同步信号), 4 个 FLEXPWM ,每个 FLEXPWM 拥有4 个子模块(0 到 3),其中模块 0 可以作为主模块(master)控制其他子模块。如何实现控制?其中一个重要的方式就是将主模块的产生的一些信号作为被控模块的计数器初始化信号。


 clockSource 与 prescale, clockSource 用于选择时钟源, Prescale 用于设置时钟分频。选择的时钟源经过分频之后才能作为 PWM 计数频率。


 pairOperation, 选择 PWM_A 与 PWM_B 的工作模式,大致分为独立模式与互补输出模式,在独立模式下 PWM_A 与PWM_B 可以独立调节各自的占空比。在互补输出模式下 PWM_A 与 PWM_B 输出互补对,并且互补对的占空比由其中一个PWM 配置寄存器决定,修改另外一个无效。通过软件可以选择。


 reloadLogic, 当收到重载信号后,选择何时进行重装载,在FLEXPWM 中某些寄存分为外部寄存和内部寄存,我们在程序中只能修改外部寄存器的值,修改后的值只有加载到内部寄存器才真正的起作用。该配置项的作用就是选择何时将修改后的值加载到内部寄存器。有四个选择,第一,立即加载(kPWM_ReloadImmediate),当加载控制位 LDOK 为 1 时立即将外部寄存器的值加载到内部寄存。第二, PWM 半周期加载(kPWM_ReloadPwmHalfCycle)PWM 计数寄存器的值与比较寄存器 0 设定值相等的时刻称为 PWM 的半周期。第三, PWM 全周期(kPWM_ReloadPwmFullCycle), PWM 计数寄存器的值与比较寄存器 1 的是相等的时刻称为 PWM 的全周期。第四, PWM 半周期或者全周期。


 reloadSelect ,重装载信号选择,寄存器重载信号可以来自主模块(子模块 0)也可以来本身产生的重载信号。 Mod Compare,与 Half Compare 都是由本模块产生,在这里对应 kPWM_LocalReload 选项。


 reloadFrequency 重装载频率, 当 reloadLogic 不选择 kPWM_ReloadImmediate 时该选项用于设置加载频率。如果reloadLogic 我们选择了半周期或者全周期加载, 则reloadFrequency 选项用于设置多少个半周期或者全周期执行加载。 例如
reloadLogic 选择全周期加载, reloadFrequency = 10,则受到加载信号后经过 10 个全周期之后才执行从装载操作。

 forceTrigger 强制输出信号选择,每个子模块拥有 8 个可供选择的强制输出信号,如代码 所示。
 

/*! @brief Options that can trigger a PWM FORCE_OUT */
typedef enum _pwm_force_output_trigger
{
    kPWM_Force_Local = 0U,   /*本地强制输出控制寄存器 CTRL2[FORCE]!< The local force signal, CTRL2[FORCE], from the submodule is used to force updates */
    kPWM_Force_Master,       /*来自主模块的强制输出信号!< The master force signal from submodule 0 is used to force updates */
    kPWM_Force_LocalReload,  /*本地重装载(Reload) 信号!< The local reload signal from this submodule is used to force updates without regard to
                                the state of LDOK */
    kPWM_Force_MasterReload, /*!<主模块重装载(Reload) 信号 The master reload signal from submodule 0 is used to force updates if LDOK is set */
    kPWM_Force_LocalSync,    /*!<本地同步信号信号 The local sync signal from this submodule is used to force updates */
    kPWM_Force_MasterSync,   /*!<主模块同步信号 The master sync signal from submodule0 is used to force updates */
    kPWM_Force_External,     /*!<外部信号 The external force signal, EXT_FORCE, from outside the PWM module causes updates */
    kPWM_Force_ExternalSync  /*!<外部同步信号 The external sync signal, EXT_SYNC, from outside the PWM module causes updates */
} pwm_force_output_trigger_t;

(1) 来自主模块, kPWM_Force_Master、 kPWM_Force_MasterReload、kPWM_Force_MasterSync, 分别表示当主模块发生强制输出时触发本地强制输出、主模块发生重装载时时触发本地强制输出、主模块发生同步时子模块执行强制输出。
(2) 第二类,来自本地, kPWM_Force_Local、 kPWM_Force_LocalReload 、kPWM_Force_LocalSync,分别表示设置本地强制输出控制寄存器 CTRL2[FORCE]触发本地强制输出、本地重装载信号触发强制输出,本地同步信号触发强制输出。
(3) 第三类,来自外部, kPWM_Force_External、 kPWM_Force_ExternalSync, 分别表示来自外部的强制输出信号 EXT_FORCE 触发本地强制输出、来自外部同步信号EXT_SYNC 触发本地强制输出。
 

eFlexPWM 输出互补 PWM 实验
eFlexPWM1 的子模块 0 输出互补 PWM 波,通过示波器观察输出。通过修改宏定义的值来修改 PWM 的频率、占空比、死区时间。
1. 编程要点
 初始化系统时钟。
 初始化 eFlexPWM 时钟源。
 初始化 PWM 输出相关 GPIO
 禁止错误检测或者使用 XBAR 设置 PWM 输出无错误。
 初始化 eFlexPWM 子模块配置参数
 初始化 PWM 输出属性,频率、占空比、等。
 设置重载并开启 PWM
 

 

/******************************第一部分*****************************/
/* eFlexPWM1_PWMA00 */
#define PWM1_PWMA00_GPIO GPIO3
#define PWM1_PWMA00_GPIO_PIN (12U)
#define PWM1_PWMA00_IOMUXC IOMUXC_GPIO_SD_B0_00_FLEXPWM1_PWMA00
/*eFlexPWM1_PWMB00 */
#define PWM1_PWMB00_GPIO GPIO3
#define PWM1_PWMB00_GPIO_PIN (13U)
 #define PWM1_PWMB00_IOMUXC IOMUXC_GPIO_SD_B0_01_FLEXPWM1_PWMB00

 /*******************************第二部分*****************************/
 /* 宏定义, 定义 PWM 基地址 */
 #define BOARD_PWM_BASEADDR PWM1
 /*宏定义, 得到 IpgCLK 时钟频率*/
 #define PWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_IpgClk)

 /*****************************第三部分****************************/

 /*能够设置的 PWM 范围与时钟源的选择、时钟分频有关,以本实验为例:
 * IPG 时钟频率: 132MHz
 *时钟分频: 128 , 计数频率: 132MHz/128 约为 1.03MHz
 *计数寄存器是 16 位,最大计数约为 65535
 *输出 PWM 最低频率 =1030000/65535 约 16Hz
 */

 #define PWM_frequency_Hz 3000
 #define PWM_duty_Cycle_Percent 50 //50 表示占空比 50%

 /*能够设置的死区时间范围与 IpgClk 时钟频率有关,以本实验为例
 * IPG 时钟频率: 132MHz
 *在本程序中死区寄存器第 11 位保存死区计数值,最大为: 2047
 *能够设置的最大死区时间 = 2047 / 132000000 约为 15us
 *
 */
 #define PWM_deadtime 15000 // 单位 ns(为了便于在示波器上观察死区时间设置较大)

 /*******************************第四部分******************************/
 /************************************************************
 * PWM1_PWMA00/PWM1_PWMB00 引脚配置
 **********************************************************/
 #define PWM_PAD_CONFIG_DATA (SRE_0_SLOW_SLEW_RATE| \
 DSE_6_R0_6| \
 SPEED_1_MEDIUM_100MHz| \
 ODE_0_OPEN_DRAIN_DISABLED| \
 PKE_1_PULL_KEEPER_ENABLED| \
 PUE_0_KEEPER_SELECTED| \
 PUS_0_100K_OHM_PULL_DOWN| \
 HYS_0_HYSTERESIS_DISABLED)
 /* 配置说明 : */
 /* 转换速率: 转换速率慢
 驱动强度: R0/6
 带宽配置 : medium(100MHz)
 开漏配置: 关闭
 拉/保持器配置: 使能上下拉/保持器
 拉/保持器选择: 保持器
 上拉/下拉选择: 100K 欧姆下拉(选择了保持器此配置无效)
 滞回器配置: 禁止 */

 

 

 


void PWM_config(void)
{
	/*********************************第一部分************************/
	uint32_t pwmSourceClockInHz; //用于保存计数频率
	uint16_t deadTimeVal = 0; //用于保存死区计数值
	pwm_signal_param_t pwmSignal[2]; //用于设置 pwm 的参数,频率、周期等
	pwm_config_t pwmConfig; //定义 pwm 配置结构体

	/*********************************第二部分************************/
	 /* 设置 IPG clock 时钟频率,最高只能实现四分频*/
	 CLOCK_SetDiv(kCLOCK_IpgDiv, 0x3); /* Set IPG PODF to 3, divede by 4 */


	 /**********************************第三部分************************/
	 /*第三部分,设置错误输入电平。 eFlexPWM 具有故障检测模块如果有错误存在则
	会禁止输出 PWM,在本实验中我们并不需要错误检测功能,我们可以通过配置
	相应寄存器将错误检测功能关闭,或者采用本实验的方法将正常电平通过 XBAR
	映射到错误输入,这样就不会检测到错误, PWM 也就可以输出了。在实际应用
	中我们可以将一个输入引脚通过 XBAR 映射到 PWM 的故障检测输入,当外部输
	入引脚的电平与设定的故障电平相同时会禁止相应的 PWM 输出,并将 PWM 输
	出引脚电平锁定为预先设定好的电平。在整流或者逆变电路中起到保护作用。*/
	 /*设置 pwm 错误输入为高电平,表示没有错误, \
	 只有当 pwm 没有错误输入或者禁止错误检测才能正常输出 pwm 波*/
	 XBARA_Init(XBARA1);
	 XBARA_SetSignalsConnection(XBARA1, \
	 kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault0);
	 XBARA_SetSignalsConnection(XBARA1,\
	 kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault1);
	 XBARA_SetSignalsConnection(XBARA1, \
	 kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault2);
	 XBARA_SetSignalsConnection(XBARA1, \
	 kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault3);

	 /*******************************第四部分****************************/
	 PWM_GetDefaultConfig(&pwmConfig);

	 /* 修改默认配置参数 */
	 /*新值在上一个 pwm 周期输出结束之后加载到缓冲寄存器中*/
	 pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
	 /*PwmA 和 PwmB 作为互补通道, PwmA 作为主通道*/
	 pwmConfig.pairOperation = kPWM_ComplementaryPwmA;
	 pwmConfig.prescale = kPWM_Prescale_Divide_128;
	 pwmConfig.enableDebugMode = true; // 使能 DebugMode

	 /* 初始化 PWM 并且判断初始化是否成功*/
	 if (PWM_Init(BOARD_PWM_BASEADDR, kPWM_Module_0,&pwmConfig)==kStatus_Fail)
	 {
	 PRINTF("PWM initialization failed\n");
	 }

	 /*************************第五部分******************************/
	 /*获得当前计数频率*/
	 pwmSourceClockInHz = PWM_SRC_CLK_FREQ;
	 /* 将死区时间转换为 pwm 时钟源的时钟个数*/
	 deadTimeVal = ((uint64_t)pwmSourceClockInHz * PWM_deadtime) / 1000000000;

	 /*配置 pwm 参数*/
	 pwmSignal[0].pwmChannel = kPWM_PwmA; //指定 pwm 通道
	 pwmSignal[0].level = kPWM_HighTrue; //设置输出极性
	 pwmSignal[0].dutyCyclePercent=PWM_duty_Cycle_Percent;//设置 pwm 的占空比
	 pwmSignal[0].deadtimeValue = deadTimeVal; //设定死区值

	 pwmSignal[1].pwmChannel = kPWM_PwmB;
	 pwmSignal[1].level = kPWM_HighTrue;
	 pwmSignal[1].dutyCyclePercent = PWM_duty_Cycle_Percent;
	 pwmSignal[1].deadtimeValue = deadTimeVal;
	 /*设置 pwm 参数,包括 pwm 的频率 占空比,死区时间等*/
	 PWM_SetupPwm(BOARD_PWM_BASEADDR, kPWM_Module_0, pwmSignal, 2,\
	 kPWM_SignedEdgeAligned, PWM_frequency_Hz,pwmSourceClockInHz);

	 /*************************第六部分****************************/
	 /*设置 Set LDOK 位,将初始化参数加载到相应的寄存器*/
	 PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0 , true);
	 /*开启 pwm1 子模块 0(Submodules 0) 的 pwm 输出*/
	 PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0 );
 }

 

 

 

 

 

 

以下是 NXP RT1011 串口 4 中断方式的示例代码: ```c #include "fsl_common.h" #include "fsl_iomuxc.h" #include "fsl_debug_console.h" #include "fsl_uart.h" #include "board.h" #include "pin_mux.h" /******************************************************************************* * Definitions ******************************************************************************/ #define DEMO_UART UART4 #define DEMO_UART_CLK_FREQ CLOCK_GetFlexCommClkFreq(4U) #define DEMO_UART_IRQn UART4_IRQn #define DEMO_UART_IRQHandler UART4_IRQHandler /******************************************************************************* * Prototypes ******************************************************************************/ /******************************************************************************* * Variables ******************************************************************************/ uint8_t txbuff[] = "UART polling example\r\nBoard will send back received characters\r\n"; uint8_t rxbuff[20] = {0}; volatile bool rxBufferEmpty = true; /******************************************************************************* * Code ******************************************************************************/ void DEMO_UART_IRQHandler(void) { uint8_t data; if ((kUART_RxDataRegFullFlag | kUART_RxOverrunFlag) & UART_GetStatusFlags(DEMO_UART)) { data = UART_ReadByte(DEMO_UART); rxBufferEmpty = false; UART_WriteByte(DEMO_UART, data); } } /*! * @brief Main function */ int main(void) { uart_config_t config; BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); PRINTF("UART example start\r\n"); /* attach 12 MHz clock to FLEXCOMM4 (UART4) */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); /* reset FLEXCOMM for UART */ RESET_PeripheralReset(kFC4_RST_SHIFT_RSTn); /* Initialize UART with configuration. */ UART_GetDefaultConfig(&config); config.baudRate_Bps = 115200U; config.enableTx = true; config.enableRx = true; UART_Init(DEMO_UART, &config, DEMO_UART_CLK_FREQ); UART_WriteBlocking(DEMO_UART, txbuff, sizeof(txbuff) - 1); /* Enable RX interrupt. */ UART_EnableInterrupts(DEMO_UART, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); EnableIRQ(DEMO_UART_IRQn); while (1) { if (!rxBufferEmpty) { rxBufferEmpty = true; memset(rxbuff, 0, sizeof(rxbuff)); UART_ReadBlocking(DEMO_UART, rxbuff, sizeof(rxbuff) - 1); PRINTF("Data received: %s\r\n", rxbuff); } } } ``` 该示例代码演示了如何在 NXP RT1011 上使用串口 4 实现中断方式的数据收发。代码中首先配置了串口 4 的中断,然后通过中断方式接收数据,并在接收到数据后进行打印输出。您可以根据实际需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值