查看: 11724|回复: 4

RT1052——10.FlexPWM输出

[复制链接]
  • TA的每日心情
    慵懒
    2025-5-7 08:45
  • 签到天数: 279 天

    连续签到: 1 天

    [LV.8]以坛为家I

    114

    主题

    1314

    帖子

    29

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    11056

    热心会员

    最后登录
    2025-8-17
    发表于 2018-11-4 15:45:26 | 显示全部楼层 |阅读模式
    RT1052自带了一个很强大的PWM输出模块FlexPWM,一共有4个模块,每一个模块又有4个通道,每个通道又有PWMA、PWMB和PWMX(不好配,以后有时间再研究研究,主要手上没有示波器,貌似配出来固定占空比的了,没示波器没法验证)三路构成,支持独立输出、互补输出、输入捕捉等一大堆功能,很是强大。

    先上代码
    引脚配置(话说飞凌的RT1052引出的脚比较少(2.0间距的排针真心没法用,没线。。。不好用),找一个能到外面的FlexPWM输出引脚,可真不容易。)
    1. void BOARD_InitPins(void) {
    2.   CLOCK_EnableClock(kCLOCK_Iomuxc);           /* iomuxc clock (iomuxc_clk_enable): 0x03u */
    3.         
    4. //转换速率       0 慢     1 快
    5. //驱动强度       0 无     1 R0     2 R0/2   3 R0/3    4 R0/4    5 R0/5    6 R0/6    7 R0/7
    6. //输出速度       0 50MHz  1 100MHz   2 100MHz   3 200MHz
    7. //开漏输出       0 关闭   1 开启
    8. //拉/保持器      0 关闭   1 开启
    9. //拉/保持器设置  0 保持    1 拉
    10. //上下拉电阻     0 100K下拉   1 47K上拉   2 100K上拉   3 22K上拉
    11. //滞回器设置     0 关闭       1开启                                                                                                                                                                                    
    12. IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0);         //复用为GPIO
    13. IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_12_LPUART1_TX, IOMUXC_SW_PAD_CTL_PAD_SRE(0)   //转换速率慢
    14.                                                      |IOMUXC_SW_PAD_CTL_PAD_DSE(6)    //驱动强度R0/6
    15.                                                      |IOMUXC_SW_PAD_CTL_PAD_SPEED(2)  //速度100MHz
    16.                                                      |IOMUXC_SW_PAD_CTL_PAD_ODE(0)    //关闭开漏
    17.                                                      |IOMUXC_SW_PAD_CTL_PAD_PKE(1)    //拉/保持器开启
    18.                                                      |IOMUXC_SW_PAD_CTL_PAD_PUE(0)    //选择为保持
    19.                                                      |IOMUXC_SW_PAD_CTL_PAD_PUS(0)    //100K下拉
    20.                                                      |IOMUXC_SW_PAD_CTL_PAD_HYS(0));  //关闭滞回
    21.                                                                                                                
    22. IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0);         //复用为GPIO
    23. IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX, IOMUXC_SW_PAD_CTL_PAD_SRE(0)    //转换速率慢
    24.                                                       |IOMUXC_SW_PAD_CTL_PAD_DSE(6)    //驱动强度R0/6
    25.                                                       |IOMUXC_SW_PAD_CTL_PAD_SPEED(2)  //速度100MHz
    26.                                                       |IOMUXC_SW_PAD_CTL_PAD_ODE(0)    //关闭开漏
    27.                                                       |IOMUXC_SW_PAD_CTL_PAD_PKE(1)    //拉/保持器开启
    28.                                                       |IOMUXC_SW_PAD_CTL_PAD_PUE(0)    //选择为保持
    29.                                                       |IOMUXC_SW_PAD_CTL_PAD_PUS(0)    //100K下拉
    30.                                                       |IOMUXC_SW_PAD_CTL_PAD_HYS(0));  //关闭滞回  

    31. IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_10_FLEXPWM1_PWMA03,0);         //复用为FLEXPWM1_PWMA03功能
    32. IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_10_FLEXPWM1_PWMA03, IOMUXC_SW_PAD_CTL_PAD_SRE(0)    //转换速率慢
    33.                                                        |IOMUXC_SW_PAD_CTL_PAD_DSE(6)    //驱动强度R0/6
    34.                                                        |IOMUXC_SW_PAD_CTL_PAD_SPEED(2)  //速度100MHz
    35.                                                        |IOMUXC_SW_PAD_CTL_PAD_ODE(0)    //关闭开漏
    36.                                                        |IOMUXC_SW_PAD_CTL_PAD_PKE(1)    //拉/保持器开启
    37.                                                        |IOMUXC_SW_PAD_CTL_PAD_PUE(0)    //选择为保持
    38.                                                        |IOMUXC_SW_PAD_CTL_PAD_PUS(0)    //100K下拉
    39.                                                        |IOMUXC_SW_PAD_CTL_PAD_HYS(0));  //关闭滞回        
    40.                                                                                                                
    41. }
    复制代码
    主程序
    1. #include "fsl_device_registers.h"
    2. #include "fsl_debug_console.h"
    3. #include "board.h"

    4. #include "pin_mux.h"
    5. #include "clock_config.h"

    6. #include "fsl_lpuart.h"
    7. #include "fsl_pwm.h"
    8. #include "fsl_xbara.h"

    9. #include "delay.h"

    10. #define DISPLAY_CLK(name) (PRINTF("%s:%d\r\n",#name,CLOCK_GetFreq(name)))    //打印对应时钟

    11. int main(void)
    12. {
    13.     int8_t pwmVal = 0;        
    14.     pwm_signal_param_t pwmSignal[1];
    15.     pwm_config_t pwmConfig;

    16.     BOARD_ConfigMPU();
    17.     BOARD_InitPins();
    18.     BOARD_BootClockRUN();
    19.     BOARD_InitDebugConsole();
    20.     delay_init();     //初始化延时
    21.         
    22.         
    23.      DISPLAY_CLK(kCLOCK_AhbClk);
    24.      DISPLAY_CLK(kCLOCK_IpgClk);        
    25.         
    26. //    XBARA_Init(XBARA1);
    27. //    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault0);
    28. //    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault1);
    29. //    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault2);
    30. //    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault3);
    31.         
    32.     PWM1->SM[3].DISMAP[0]=0;
    33.         
    34.         
    35.     PWM_GetDefaultConfig(&pwmConfig);                     //快速配置
    36.     pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; //全周期更新
    37.     pwmConfig.pairOperation = kPWM_Independent;      //PWMA,PWMB各自独立输出
    38.     PWM_Init(PWM1, kPWM_Module_3, &pwmConfig);       //初始化PWM1的通道3

    39.     pwmSignal[0].pwmChannel = kPWM_PwmA;             //配置PWMA
    40.     pwmSignal[0].level = kPWM_HighTrue;              //有效电平为高
    41.     pwmSignal[0].dutyCyclePercent = 50;              //占空比50%
    42.         
    43.     /*配置PWM1 通道3 有符号中心对齐 PWM信号频率为1000Hz*/
    44.     PWM_SetupPwm(PWM1, kPWM_Module_3, pwmSignal, 1, kPWM_SignedCenterAligned, 1000, CLOCK_GetFreq(kCLOCK_IpgClk));        

    45.     PWM_SetPwmLdok(PWM1, kPWM_Control_Module_3, true);    //更新有关设置
    46.     PWM_StartTimer(PWM1, kPWM_Control_Module_3);              //开始计数
    47.         

    48.     while (1)
    49.     {
    50.         delay_ms(50);
    51.         pwmVal = pwmVal + 1;
    52.         if (pwmVal >= 100)
    53.         {
    54.             pwmVal = 0;
    55.         }

    56.         PWM_UpdatePwmDutycycle(PWM1,kPWM_Module_3, kPWM_PwmA, kPWM_SignedCenterAligned, pwmVal); //更新占空比
    57.         PWM_SetPwmLdok(PWM1, kPWM_Control_Module_3, true);    //更新有关设置
    58.     }
    59. }
    复制代码


    引脚配置复用没啥好说的。
    要写程序,先配置时钟,不过这次直接用的默认配置,使用IPG_CLK作为时钟源。如果要修改分频的话,见下图

    QQ截图20181104141343.png

    首先可以看到注释了一大段代码,这一段代码和 PWM1->SM[3].DISMAP[0]=0; 有一个在就行。(这一段代码暂时不提,可以看了下一篇贴子,再回来理解。大概的意思就是置位故障输出位。没有而且还没有关闭故障检测功能的话,就无法输出)DISMAP寄存器如下,作用可以控制故障检测功能的开关。

    QQ截图20181104151129.png

    这里调用了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,设置输出模式(和上面的一样),设置占空比

    实验效果见附件(没有示波器啊。。。只能用电压表来指示输出。。。。)

    最后附上工程和效果
      MDK版本:5.22
      pack:NXP.MIMXRT1052_DFP.10.0.1.pack
      下载算法:飞凌嵌入式提供的 MIMXRT_QSPIFLASH.FLM
      启动方式:spi flash启动  
      下载方式:STlink
    10.pwm.zip (1.46 MB, 下载次数: 98)
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    2

    帖子

    0

    新手上路

    Rank: 1

    积分
    17
    最后登录
    2018-12-16
    发表于 2018-11-26 17:53:27 | 显示全部楼层
    感谢大佬分享,拿去学习学习
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    2

    帖子

    0

    新手上路

    Rank: 1

    积分
    17
    最后登录
    2018-12-16
    发表于 2018-11-29 19:46:17 | 显示全部楼层
    问一下我用你的程序烧录下来后频率不对,1khz我这里输出142khz,请教一下这是为什么,是时钟出了问题吗
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-5-7 08:45
  • 签到天数: 279 天

    连续签到: 1 天

    [LV.8]以坛为家I

    114

    主题

    1314

    帖子

    29

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    11056

    热心会员

    最后登录
    2025-8-17
     楼主| 发表于 2018-11-29 22:21:57 | 显示全部楼层
    lol2333 发表于 2018-11-29 19:46
    问一下我用你的程序烧录下来后频率不对,1khz我这里输出142khz,请教一下这是为什么,是时钟出了问题吗 ...

    非常感谢指出贴子里面的错误,手上没有示波器,没有仔细看频率这一方面。。。。。
    我研究了一下,flexPWM是一个16位的外设,这里的pwm使用的ipgclk的频率为132MHz,而我的分频为1.也就是,132MHz/1KHz=132000>2^16;也就是溢出了。。
    需要在PWM_GetDefaultConfig快速配置的函数下面加上这一句
    pwmConfig.prescale=kPWM_Prescale_Divide_128;     //设置分频为128
    当然其他分频也是可以的,只要满足范围。贴子的问题我会在近期修改的,感谢支持
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    3

    主题

    14

    帖子

    0

    注册会员

    Rank: 2

    积分
    73
    最后登录
    2019-3-2
    发表于 2018-12-10 23:13:51 | 显示全部楼层
    感谢楼主,可以正常使用
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-8-19 03:52 , Processed in 0.096383 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表