FlexPWM输出
RT1052自带了一个很强大的PWM输出模块FlexPWM,一共有4个模块,每一个模块又有4个通道,每个通道又有PWMA、PWMB和PWMX(不好配,以后有时间再研究研究,主要手上没有示波器,貌似配出来固定占空比的了,没示波器没法验证)三路构成,支持独立输出、互补输出、输入捕捉等一大堆功能,很是强大。
先上代码
引脚配置(话说飞凌的RT1052引出的脚比较少(2.0间距的排针真心没法用,没线。。。不好用),找一个能到外面的FlexPWM输出引脚,可真不容易。)
复制代码
主程序
复制代码
引脚配置复用没啥好说的。
要写程序,先配置时钟,不过这次直接用的默认配置,使用IPG_CLK作为时钟源。如果要修改分频的话,见下图
<ignore_js_op>
首先可以看到注释了一大段代码,这一段代码和 PWM1->SM[3].DISMAP[0]=0; 有一个在就行。(这一段代码暂时不提,可以看了下一篇贴子,再回来理解。大概的意思就是置位故障输出位。没有而且还没有关闭故障检测功能的话,就无法输出)DISMAP寄存器如下,作用可以控制故障检测功能的开关。
<ignore_js_op>
这里调用了PWM_GetDefaultConfig 进行快速配置,先看一下默认配置
config->enableDebugMode = false; //调试模式下暂停
config->enableWait = false; //等待模式下暂停
config->reloadSelect = kPWM_LocalReload; //使用本地再加载
config->faultFilterCount = 0; //故障过滤器计数为0
config->faultFilterPeriod = 0; //禁用故障过滤器
config->clockSource = kPWM_BusClock; //使用IPBus作为时钟
config->prescale = kPWM_Prescale_Divide_1;//分频为1
config->initializationControl = kPWM_Initialize_LocalSync;//本地同步导致初始化
config->forceTrigger = kPWM_Force_Local; //CTRL2[FORCE]信号触发强制输出
config->reloadFrequency = kPWM_LoadEveryOportunity; //重载频率
config->reloadLogic = kPWM_ReloadImmediate; //设置LDOK时,加载值
config->pairOperation = kPWM_Independent; //PWMA,PWMB各自独立输出
下面是补充的配置
pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; //全周期更新
pwmConfig.pairOperation = kPWM_Independent; //PWMA,PWMB各自独立输出
然后调用PWM_Init初始化
然后配置通道的情况
pwmSignal[0].pwmChannel = kPWM_PwmA; //配置PWMA
pwmSignal[0].level = kPWM_HighTrue; //有效电平为高
pwmSignal[0].dutyCyclePercent = 50; //占空比50%
调用PWM_SetupPwm。
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);
一共7个参数分别是,需要配置的模块,需要配置的通道,用于配置的数组地址,需要配置的数目(应该和数组的大小相同,这里只配置了PWMA),输出模式,输出PWM的频率,主时钟的频率。
这里的输出模式
typedef enum _pwm_mode
{
kPWM_SignedCenterAligned = 0U, /*!< Signed center-aligned */
kPWM_CenterAligned, /*!< Unsigned cente-aligned */
kPWM_SignedEdgeAligned, /*!< Signed edge-aligned */
kPWM_EdgeAligned /*!< Unsigned edge-aligned */
} pwm_mode_t;
有这些,对于现在配置单通道输出来说,都差不多。
调用PWM_SetPwmLdok PWM_StartTimer设置,开始计数
最后说一下PWM_UpdatePwmDutycycle
void PWM_UpdatePwmDutycycle(PWM_Type *base,
pwm_submodule_t subModule,
pwm_channels_t pwmSignal,
pwm_mode_t currPwmMode,
uint8_t dutyCyclePercent);
一共5个参数,分别是,设置的模块,设置的通道,设置是PWMA还是PWMB,设置输出模式(和上面的一样),设置占空比
实验效果见附件(没有示波器啊。。。只能用电压表来指示输出。。。。)
先上代码
引脚配置(话说飞凌的RT1052引出的脚比较少(2.0间距的排针真心没法用,没线。。。不好用),找一个能到外面的FlexPWM输出引脚,可真不容易。)
- void BOARD_InitPins(void) {
- CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
- //转换速率 0 慢 1 快
- //驱动强度 0 无 1 R0 2 R0/2 3 R0/3 4 R0/4 5 R0/5 6 R0/6 7 R0/7
- //输出速度 0 50MHz 1 100MHz 2 100MHz 3 200MHz
- //开漏输出 0 关闭 1 开启
- //拉/保持器 0 关闭 1 开启
- //拉/保持器设置 0 保持 1 拉
- //上下拉电阻 0 100K下拉 1 47K上拉 2 100K上拉 3 22K上拉
- //滞回器设置 0 关闭 1开启
- IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0); //复用为GPIO
- IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_12_LPUART1_TX, IOMUXC_SW_PAD_CTL_PAD_SRE(0) //转换速率慢
- |IOMUXC_SW_PAD_CTL_PAD_DSE(6) //驱动强度R0/6
- |IOMUXC_SW_PAD_CTL_PAD_SPEED(2) //速度100MHz
- |IOMUXC_SW_PAD_CTL_PAD_ODE(0) //关闭开漏
- |IOMUXC_SW_PAD_CTL_PAD_PKE(1) //拉/保持器开启
- |IOMUXC_SW_PAD_CTL_PAD_PUE(0) //选择为保持
- |IOMUXC_SW_PAD_CTL_PAD_PUS(0) //100K下拉
- |IOMUXC_SW_PAD_CTL_PAD_HYS(0)); //关闭滞回
- IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0); //复用为GPIO
- IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX, IOMUXC_SW_PAD_CTL_PAD_SRE(0) //转换速率慢
- |IOMUXC_SW_PAD_CTL_PAD_DSE(6) //驱动强度R0/6
- |IOMUXC_SW_PAD_CTL_PAD_SPEED(2) //速度100MHz
- |IOMUXC_SW_PAD_CTL_PAD_ODE(0) //关闭开漏
- |IOMUXC_SW_PAD_CTL_PAD_PKE(1) //拉/保持器开启
- |IOMUXC_SW_PAD_CTL_PAD_PUE(0) //选择为保持
- |IOMUXC_SW_PAD_CTL_PAD_PUS(0) //100K下拉
- |IOMUXC_SW_PAD_CTL_PAD_HYS(0)); //关闭滞回
- IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_10_FLEXPWM1_PWMA03,0); //复用为FLEXPWM1_PWMA03功能
- IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_10_FLEXPWM1_PWMA03, IOMUXC_SW_PAD_CTL_PAD_SRE(0) //转换速率慢
- |IOMUXC_SW_PAD_CTL_PAD_DSE(6) //驱动强度R0/6
- |IOMUXC_SW_PAD_CTL_PAD_SPEED(2) //速度100MHz
- |IOMUXC_SW_PAD_CTL_PAD_ODE(0) //关闭开漏
- |IOMUXC_SW_PAD_CTL_PAD_PKE(1) //拉/保持器开启
- |IOMUXC_SW_PAD_CTL_PAD_PUE(0) //选择为保持
- |IOMUXC_SW_PAD_CTL_PAD_PUS(0) //100K下拉
- |IOMUXC_SW_PAD_CTL_PAD_HYS(0)); //关闭滞回
- }
- #include "fsl_device_registers.h"
- #include "fsl_debug_console.h"
- #include "board.h"
- #include "pin_mux.h"
- #include "clock_config.h"
- #include "fsl_lpuart.h"
- #include "fsl_pwm.h"
- #include "fsl_xbara.h"
- #include "delay.h"
- #define DISPLAY_CLK(name) (PRINTF("%s:%d\r\n",#name,CLOCK_GetFreq(name))) //打印对应时钟
- int main(void)
- {
- int8_t pwmVal = 0;
- pwm_signal_param_t pwmSignal[1];
- pwm_config_t pwmConfig;
- BOARD_ConfigMPU();
- BOARD_InitPins();
- BOARD_BootClockRUN();
- BOARD_InitDebugConsole();
- delay_init(); //初始化延时
- DISPLAY_CLK(kCLOCK_AhbClk);
- DISPLAY_CLK(kCLOCK_IpgClk);
- // 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);
- PWM1->SM[3].DISMAP[0]=0;
- PWM_GetDefaultConfig(&pwmConfig); //快速配置
- pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; //全周期更新
- pwmConfig.pairOperation = kPWM_Independent; //PWMA,PWMB各自独立输出
- PWM_Init(PWM1, kPWM_Module_3, &pwmConfig); //初始化PWM1的通道3
- pwmSignal[0].pwmChannel = kPWM_PwmA; //配置PWMA
- pwmSignal[0].level = kPWM_HighTrue; //有效电平为高
- pwmSignal[0].dutyCyclePercent = 50; //占空比50%
- /*配置PWM1 通道3 有符号中心对齐 PWM信号频率为1000Hz*/
- PWM_SetupPwm(PWM1, kPWM_Module_3, pwmSignal, 1, kPWM_SignedCenterAligned, 1000, CLOCK_GetFreq(kCLOCK_IpgClk));
- PWM_SetPwmLdok(PWM1, kPWM_Control_Module_3, true); //更新有关设置
- PWM_StartTimer(PWM1, kPWM_Control_Module_3); //开始计数
- while (1)
- {
- delay_ms(50);
- pwmVal = pwmVal + 1;
- if (pwmVal >= 100)
- {
- pwmVal = 0;
- }
- PWM_UpdatePwmDutycycle(PWM1,kPWM_Module_3, kPWM_PwmA, kPWM_SignedCenterAligned, pwmVal); //更新占空比
- PWM_SetPwmLdok(PWM1, kPWM_Control_Module_3, true); //更新有关设置
- }
- }
引脚配置复用没啥好说的。
要写程序,先配置时钟,不过这次直接用的默认配置,使用IPG_CLK作为时钟源。如果要修改分频的话,见下图
<ignore_js_op>
首先可以看到注释了一大段代码,这一段代码和 PWM1->SM[3].DISMAP[0]=0; 有一个在就行。(这一段代码暂时不提,可以看了下一篇贴子,再回来理解。大概的意思就是置位故障输出位。没有而且还没有关闭故障检测功能的话,就无法输出)DISMAP寄存器如下,作用可以控制故障检测功能的开关。
<ignore_js_op>
这里调用了PWM_GetDefaultConfig 进行快速配置,先看一下默认配置
config->enableDebugMode = false; //调试模式下暂停
config->enableWait = false; //等待模式下暂停
config->reloadSelect = kPWM_LocalReload; //使用本地再加载
config->faultFilterCount = 0; //故障过滤器计数为0
config->faultFilterPeriod = 0; //禁用故障过滤器
config->clockSource = kPWM_BusClock; //使用IPBus作为时钟
config->prescale = kPWM_Prescale_Divide_1;//分频为1
config->initializationControl = kPWM_Initialize_LocalSync;//本地同步导致初始化
config->forceTrigger = kPWM_Force_Local; //CTRL2[FORCE]信号触发强制输出
config->reloadFrequency = kPWM_LoadEveryOportunity; //重载频率
config->reloadLogic = kPWM_ReloadImmediate; //设置LDOK时,加载值
config->pairOperation = kPWM_Independent; //PWMA,PWMB各自独立输出
下面是补充的配置
pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; //全周期更新
pwmConfig.pairOperation = kPWM_Independent; //PWMA,PWMB各自独立输出
然后调用PWM_Init初始化
然后配置通道的情况
pwmSignal[0].pwmChannel = kPWM_PwmA; //配置PWMA
pwmSignal[0].level = kPWM_HighTrue; //有效电平为高
pwmSignal[0].dutyCyclePercent = 50; //占空比50%
调用PWM_SetupPwm。
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);
一共7个参数分别是,需要配置的模块,需要配置的通道,用于配置的数组地址,需要配置的数目(应该和数组的大小相同,这里只配置了PWMA),输出模式,输出PWM的频率,主时钟的频率。
这里的输出模式
typedef enum _pwm_mode
{
kPWM_SignedCenterAligned = 0U, /*!< Signed center-aligned */
kPWM_CenterAligned, /*!< Unsigned cente-aligned */
kPWM_SignedEdgeAligned, /*!< Signed edge-aligned */
kPWM_EdgeAligned /*!< Unsigned edge-aligned */
} pwm_mode_t;
有这些,对于现在配置单通道输出来说,都差不多。
调用PWM_SetPwmLdok PWM_StartTimer设置,开始计数
最后说一下PWM_UpdatePwmDutycycle
void PWM_UpdatePwmDutycycle(PWM_Type *base,
pwm_submodule_t subModule,
pwm_channels_t pwmSignal,
pwm_mode_t currPwmMode,
uint8_t dutyCyclePercent);
一共5个参数,分别是,设置的模块,设置的通道,设置是PWMA还是PWMB,设置输出模式(和上面的一样),设置占空比
实验效果见附件(没有示波器啊。。。只能用电压表来指示输出。。。。)