RT1010 PWM 组成配置和 PWMX 的使用

1. 前言

        本篇博文将着眼于 i.MX RT1010 内部的 eFlexPWM,介绍其各个功能模块,以及 PWM 产生的原理。

2. 功能模块组成

        以下是 RT1010 内部 PWM 的一个 Submoudle 的组成框图,从框图中我们可以看到:

  1. 自左向右依次有 Prescaler 对时钟进行预分频,分频之后的时钟作为 16 bit counter 计数器的时钟,驱动其计数,计数的初始值由 Counter preload mux 根据不同的同步方式进行选择重载;
  2. 接下来将由 3 组 6 个比较器对 0-5 Campare value 寄存器的数值与 16 bit counter 的计数值进行比较:
    1. 对由 Compare 0 value 寄存器和 Compare 1 value 寄存器为一组的数值与当前的计数值进行比较,输出的比较值连接到 Reload Logic 进行 Master Reload 控制;另外通过 Compare 0 value 寄存器与当前计数值的值进行比较,通过 Pin Mux 可将四个 GPIO 端口复用为 PWMX 进行 PWM 的输出。
    2. 对由 Compare 2 value 寄存器和 Compare 3 value 寄存器为一组的数值与当前的计数值进行比较,分别控制一个 SR 触发的 S 端和 R 端,当 S 为 1 时 PWM 输出高电平,R 为 1 时,PWM 输出低电平,这样通过  Compare 2 value 寄存器和 Compare 3 value 寄存器即可输出一路 PWM23;
    3. 类似的可以通过 Compare 4 value 寄存器和 Compare 5 value 寄存器输出另一路 PWM45;
  3. PWM23 和 PWM45 经过 Comp. vs Indep. 模块的处理用于控制输出独立的或互补的 PWM 的波形,通过 Deed Time Cenerator 的处理用以插入死区时间,通过 Mux Select Logic 用以选择 GPIO 的引脚复用;最后一级的模块将对这两路 PWM 由 Fault protection 和 Output override control  进行出错保护。

 图 1. PWM 子模块框图

        通过 MCUXpresso Config Tools 可以看到芯片内部只有一个 PWM1,PWM1 下面有 4 个 Submoudles,每个 Submodle 可以控制 A 和 B 两个可互补的通道和一个 X  通道,可以针对有相应复用功能的引脚进行 PWM 功能复用。

        参考 SDK 的 PWM 例程,在枚举 _pwm_init_source 中对 counter 的重载方式进行了定义,可选的方式有本地同步(LocalSync)、主模块重载同步(MasterReload)、主模块同步(MasterSync)、外部同步(ExtSync)。不同的同步方式将影响到模块 4 个 Submodle 的计数器同步方式。例如对于选用主模块同步 MasterSync 这种方式将导致四个模块的计数器重载与 Submoulde 0 的重载时机一样,而采用本地同步(LocalSync)则不会受到主模块同步的影响。

/*! @brief PWM counter initialization options */
typedef enum _pwm_init_source
{
    kPWM_Initialize_LocalSync = 0U, /*!< Local sync causes initialization */
    kPWM_Initialize_MasterReload,   /*!< Master reload from submodule 0 causes initialization */
    kPWM_Initialize_MasterSync,     /*!< Master sync from submodule 0 causes initialization */
    kPWM_Initialize_ExtSync         /*!< EXT_SYNC causes initialization */
} pwm_init_source_t;

        PWM 模式,在枚举 _pwm_mode 中定义,kPWM_SignedCenterAligned 和 kPWM_CenterAligned 是中央对其方式,kPWM_SignedEdgeAligned 和 kPWM_EdgeAligned 是边缘对齐方式,Signed 和 Unsigned 指的是 INIT 计数器的初始值是有符号数和无符号数。

        由于 SDK 中没有 PWMX PWM 生成的代码例程,本篇博文将添加一种 kPWM_NonAligned 方式进行测试。 

/*! @brief PWM operation mode */
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 */
	kPWM_NonAligned               //added by joey wang 2023.2.8
} pwm_mode_t;

中央对齐模式:

        在此模式下,INIT 将向上计数,由 VAL2 通过比较器与计数值进行比较打开 PWMA 的上升边沿,VAL3 打开 PWMA 的下降边沿; 由 VAL4 打开 PWMB 的上升边沿,VAL5 打开 PWMB 的下降边沿,不难看出 Singed 模式下数值对称,有利于计算。

 边沿对齐模式:

        在边沿对齐模式下,INIT 的取值和 VAL2 和 VAL4 的取值一样,即 PWMA 和 PWMB 上升沿 PWM 打开的时机一样,即达到了边沿对齐的目的,只需要指定 VAL3 和 VAL5 的数值,即可改变 PWMA 或 PWMB 的占空比。

实验现象:

在 PWM_SetupPwm 中增加 kPWM_NonAligned 的 case 判断:

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)
{
    assert(chnlParams);
    assert(pwmFreq_Hz);
    assert(numOfChnls);
    assert(srcClock_Hz);

    uint32_t pwmClock;
    uint16_t pulseCnt = 0, pwmHighPulse = 0;
    uint16_t modulo = 0;
    uint8_t i, polarityShift = 0, outputEnableShift = 0;

    if (numOfChnls > 3U)
    {
        /* Each submodule has 3 signals; PWM A & PWM B & PWM X*/
        return kStatus_Fail;
    }

    /* Divide the clock by the prescale value */
    pwmClock = (srcClock_Hz / (1UL << ((base->SM[subModule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT)));
    pulseCnt = (uint16_t)(pwmClock / pwmFreq_Hz);

    /* Setup each PWM channel */
    for (i = 0; i < numOfChnls; i++)
    {
        /* Calculate pulse width */
        pwmHighPulse = (pulseCnt * chnlParams->dutyCyclePercent) / 100U;

        /* Setup the different match registers to generate the PWM signal */
        switch (mode)
        {
            case kPWM_SignedCenterAligned:
                /* Setup the PWM period for a signed center aligned signal */
                if (i == 0U)
                {
                    modulo = (pulseCnt >> 1U);
                    /* Indicates the start of the PWM period */
                    base->SM[subModule].INIT = PWM_GetComplementU16(modulo);
                    /* Indicates the center value */
                    base->SM[subModule].VAL0 = 0;
                    /* Indicates the end of the PWM period */
                    /* The change during the end to start of the PWM period requires a count time */
                    base->SM[subModule].VAL1 = modulo - 1U;
                }

                /* Setup the PWM dutycycle */
                if (chnlParams->pwmChannel == kPWM_PwmA)
                {
                    base->SM[subModule].VAL2 = PWM_GetComplementU16(pwmHighPulse / 2U);
                    base->SM[subModule].VAL3 = (pwmHighPulse / 2U);
                }
                else if(chnlParams->pwmChannel == kPWM_PwmB)
                {
                    base->SM[subModule].VAL4 = PWM_GetComplementU16(pwmHighPulse / 2U);
                    base->SM[subModule].VAL5 = (pwmHighPulse / 2U);
                }
                break;
            case kPWM_CenterAligned:
                /* Setup the PWM period for an unsigned center aligned signal */
                /* Indicates the start of the PWM period */
                if (i == 0U)
                {
                    base->SM[subModule].INIT = 0;
                    /* Indicates the center value */
                    base->SM[subModule].VAL0 = (pulseCnt / 2U);
                    /* Indicates the end of the PWM period */
                    /* The change during the end to start of the PWM period requires a count time */
                    base->SM[subModule].VAL1 = pulseCnt - 1U;
                }

                /* Setup the PWM dutycycle */
                if (chnlParams->pwmChannel == kPWM_PwmA)
                {
                    base->SM[subModule].VAL2 = ((pulseCnt - pwmHighPulse) / 2U);
                    base->SM[subModule].VAL3 = ((pulseCnt + pwmHighPulse) / 2U);
                }
                else
                {
                    base->SM[subModule].VAL4 = ((pulseCnt - pwmHighPulse) / 2U);
                    base->SM[subModule].VAL5 = ((pulseCnt + pwmHighPulse) / 2U);
                }
                break;
            case kPWM_SignedEdgeAligned:
                /* Setup the PWM period for a signed edge aligned signal */
                if (i == 0U)
                {
                    modulo = (pulseCnt >> 1U);
                    /* Indicates the start of the PWM period */
                    base->SM[subModule].INIT = PWM_GetComplementU16(modulo);
                    /* Indicates the center value */
                    base->SM[subModule].VAL0 = 0;
                    /* Indicates the end of the PWM period */
                    /* The change during the end to start of the PWM period requires a count time */
                    base->SM[subModule].VAL1 = modulo - 1U;
                }

                /* Setup the PWM dutycycle */
                if (chnlParams->pwmChannel == kPWM_PwmA)
                {
                    base->SM[subModule].VAL2 = PWM_GetComplementU16(modulo);
                    base->SM[subModule].VAL3 = PWM_GetComplementU16(modulo) + pwmHighPulse;
                }
                else
                {
                    base->SM[subModule].VAL4 = PWM_GetComplementU16(modulo);
                    base->SM[subModule].VAL5 = PWM_GetComplementU16(modulo) + pwmHighPulse;
                }
                break;
            case kPWM_EdgeAligned:
                /* Setup the PWM period for a unsigned edge aligned signal */
                /* Indicates the start of the PWM period */
                if (i == 0U)
                {
                    base->SM[subModule].INIT = 0;
                    /* Indicates the center value */
                    base->SM[subModule].VAL0 = (pulseCnt / 2U);
                    /* Indicates the end of the PWM period */
                    /* The change during the end to start of the PWM period requires a count time */
                    base->SM[subModule].VAL1 = pulseCnt - 1U;
                }

                /* Setup the PWM dutycycle */
                if (chnlParams->pwmChannel == kPWM_PwmA)
                {
                    base->SM[subModule].VAL2 = 0;
                    base->SM[subModule].VAL3 = pwmHighPulse;
                }
                else
                {
                    base->SM[subModule].VAL4 = 0;
                    base->SM[subModule].VAL5 = pwmHighPulse;
                }
                break;
				/*added by joey wang at 2023.2.14*/
			 case kPWM_NonAligned:
                /* Setup the PWM period for a signed center aligned signal */
                if (i == 0U)
                {
					 /* Setup the PWM period for a PWM_X non-aligned signal */
					pulseCnt = base->SM[subModule].VAL1;
					/* Indicates the start of the PWM period */
					base->SM[subModule].INIT = 0;
					/* Indicates the center value */
					base->SM[subModule].VAL0 = (pulseCnt / 2);
					/* Indicates the end of the PWM period */
					base->SM[subModule].VAL1 = pulseCnt;
                }
				/*initialize duty circle, VAL0/VAL1 is the duty circle, note by joey 2023.2.16*/
				if(chnlParams->pwmChannel == kPWM_PwmX)
				{
					PRINTF("kPWM_PwmX duty is set\t\n");
					base->SM[subModule].VAL0 = pwmHighPulse;
					base->SM[subModule].VAL1 = pwmHighPulse*2;
					/*PRINTF("VAL0 = %d\r\n",base->SM[subModule].VAL0);
					PRINTF("VAL1 = %d\r\n",base->SM[subModule].VAL1);*/
				}
                break;
            default:
                assert(false);
                break;
        }
        /* Setup register shift values based on the channel being configured.
         * Also setup the deadtime value
         */
        if (chnlParams->pwmChannel == kPWM_PwmA)
        {
            polarityShift              = PWM_OCTRL_POLA_SHIFT;
            outputEnableShift          = PWM_OUTEN_PWMA_EN_SHIFT;
            base->SM[subModule].DTCNT0 = PWM_DTCNT0_DTCNT0(chnlParams->deadtimeValue);
        }
        else if(chnlParams->pwmChannel == kPWM_PwmB)
        {
            polarityShift              = PWM_OCTRL_POLB_SHIFT;
            outputEnableShift          = PWM_OUTEN_PWMB_EN_SHIFT;
            base->SM[subModule].DTCNT1 = PWM_DTCNT1_DTCNT1(chnlParams->deadtimeValue);
        }
				else
				{		
				    polarityShift              = PWM_OCTRL_POLX_SHIFT;
            outputEnableShift          = PWM_OUTEN_PWMX_EN_SHIFT;
            base->SM[subModule].DTCNT0 = PWM_DTCNT1_DTCNT1(chnlParams->deadtimeValue);
				}

        /* Set PWM output fault status */
        switch (chnlParams->pwmChannel)
        {
            case kPWM_PwmA:
                base->SM[subModule].OCTRL &= ~((uint16_t)PWM_OCTRL_PWMAFS_MASK);
                base->SM[subModule].OCTRL |= (((uint16_t)(chnlParams->faultState) << (uint16_t)PWM_OCTRL_PWMAFS_SHIFT) &
                                              (uint16_t)PWM_OCTRL_PWMAFS_MASK);
                break;
            case kPWM_PwmB:
                base->SM[subModule].OCTRL &= ~((uint16_t)PWM_OCTRL_PWMBFS_MASK);
                base->SM[subModule].OCTRL |= (((uint16_t)(chnlParams->faultState) << (uint16_t)PWM_OCTRL_PWMBFS_SHIFT) &
                                              (uint16_t)PWM_OCTRL_PWMBFS_MASK);
                break;
            case kPWM_PwmX:
                base->SM[subModule].OCTRL &= ~((uint16_t)PWM_OCTRL_PWMXFS_MASK);
                base->SM[subModule].OCTRL |= (((uint16_t)(chnlParams->faultState) << (uint16_t)PWM_OCTRL_PWMXFS_SHIFT) &
                                              (uint16_t)PWM_OCTRL_PWMXFS_MASK);
                break;
            default:
                assert(false);
                break;
        }

        /* Setup signal active level */
        if ((bool)chnlParams->level == kPWM_LowTrue)   // in this setting to set output level high or low, note by joey at 2023.2.16
        {
            base->SM[subModule].OCTRL &= ~((uint16_t)1U << (uint16_t)polarityShift);
        }
        else
        {
            base->SM[subModule].OCTRL |= ((uint16_t)1U << (uint16_t)polarityShift);
        }
        /* Enable PWM output */
        base->OUTEN |= ((uint16_t)1U << ((uint16_t)outputEnableShift + (uint16_t)subModule));

        /* Get the next channel parameters */
        chnlParams++;
    }

    return kStatus_Success;
}

再更新 PWM_UpdatePwmDutycycleHighAccuracy 函数

void PWM_UpdatePwmDutycycleHighAccuracy(
    PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, pwm_mode_t currPwmMode, uint16_t dutyCycle)
{
    assert((uint16_t)pwmSignal < 3U);
    uint16_t pulseCnt = 0, pwmHighPulse = 0;
    uint16_t modulo = 0;
	
		
    switch (currPwmMode)
    {
        case kPWM_SignedCenterAligned:
            modulo   = base->SM[subModule].VAL1 + 1U;
            pulseCnt = modulo * 2U;
            /* Calculate pulse width */
            pwmHighPulse = (pulseCnt * dutyCycle) / 65535U;

            /* Setup the PWM dutycycle */
            if (pwmSignal == kPWM_PwmA)
            {
                base->SM[subModule].VAL2 = PWM_GetComplementU16(pwmHighPulse / 2U);
                base->SM[subModule].VAL3 = (pwmHighPulse / 2U);
            }
            else
            {
                base->SM[subModule].VAL4 = PWM_GetComplementU16(pwmHighPulse / 2U);
                base->SM[subModule].VAL5 = (pwmHighPulse / 2U);
            }
            break;
        case kPWM_CenterAligned:
            pulseCnt = base->SM[subModule].VAL1 + 1U;
            /* Calculate pulse width */
            pwmHighPulse = (pulseCnt * dutyCycle) / 65535U;

            /* Setup the PWM dutycycle */
            if (pwmSignal == kPWM_PwmA)
            {
                base->SM[subModule].VAL2 = ((pulseCnt - pwmHighPulse) / 2U);
                base->SM[subModule].VAL3 = ((pulseCnt + pwmHighPulse) / 2U);
            }
            else
            {
                base->SM[subModule].VAL4 = ((pulseCnt - pwmHighPulse) / 2U);
                base->SM[subModule].VAL5 = ((pulseCnt + pwmHighPulse) / 2U);
            }
            break;
        case kPWM_SignedEdgeAligned:
            modulo   = base->SM[subModule].VAL1 + 1U;
            pulseCnt = modulo * 2U;
            /* Calculate pulse width */
            pwmHighPulse = (pulseCnt * dutyCycle) / 65535U;

            /* Setup the PWM dutycycle */
            if (pwmSignal == kPWM_PwmA)
            {
                base->SM[subModule].VAL2 = PWM_GetComplementU16(modulo);
                base->SM[subModule].VAL3 = PWM_GetComplementU16(modulo) + pwmHighPulse;
            }
            else
            {
                base->SM[subModule].VAL4 = PWM_GetComplementU16(modulo);
                base->SM[subModule].VAL5 = PWM_GetComplementU16(modulo) + pwmHighPulse;
            }
            break;
        case kPWM_EdgeAligned:
            pulseCnt = base->SM[subModule].VAL1 + 1U;
            /* Calculate pulse width */
            pwmHighPulse = (pulseCnt * dutyCycle) / 65535U;

            /* Setup the PWM dutycycle */
            if (pwmSignal == kPWM_PwmA)
            {
                base->SM[subModule].VAL2 = 0;
                base->SM[subModule].VAL3 = pwmHighPulse;
            }
            else
            {
                base->SM[subModule].VAL4 = 0;
                base->SM[subModule].VAL5 = pwmHighPulse;
            }
            break;
		case kPWM_NonAligned:
            pulseCnt = base->SM[subModule].VAL1 + 1U;
            /* Calculate pulse width */
            pwmHighPulse = (pulseCnt * dutyCycle) / 65535U;
            /* Setup the PWM dutycycle */
            if (pwmSignal == kPWM_PwmA)
            {
                base->SM[subModule].VAL2 = 0;
                base->SM[subModule].VAL3 = pwmHighPulse;
            }
            else if (pwmSignal == kPWM_PwmB)
            {
                base->SM[subModule].VAL4 = 0;
                base->SM[subModule].VAL5 = pwmHighPulse;
            }
            //add PWMX duty update here
			else
			{
				base->SM[subModule].VAL0 = pwmHighPulse;
                //base->SM[subModule].VAL1 = 0;
				PRINTF("pwmHighPulse = %d\r\n",pwmHighPulse);
				PRINTF("VAL1 = %d\r\n",base->SM[subModule].VAL1);
			}
			break;
        default:
            assert(false);
            break;
    }
}

        通过添加以上对 kPWM_NonAligned 输出 PWMX 的代码,再通过 PWM configure 函数,对 PWMX 的输出方式进行配置,代码如下,即可输出指定占空比的 PWMX 的 PWM 波形。

//PWM
void pwm_config(pwm_no_t pwm_no, uint32 frq ,gpio_no_t gpio_no)       //Configure PWM initial settings, frq: pwm frquency, 1 per 1Hz, 6 PWM channels share the same SCT, the frq value should be the same.  
{
		/* Structure of initialize PWM */
    pwm_config_t pwmConfig;
    pwm_fault_param_t faultConfig;
	
    CLOCK_SetDiv(kCLOCK_IpgDiv, 0x3); /* Set IPG PODF to 3, divede by 4 */

    /* Set the PWM Fault inputs to a low value */
    XBARA_Init(XBARA);
    XBARA_SetSignalsConnection(XBARA, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault0);
    XBARA_SetSignalsConnection(XBARA, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault1);
    XBARA_SetSignalsConnection(XBARA, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault2);
    XBARA_SetSignalsConnection(XBARA, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault3);

	PWM_GetDefaultConfig(&pwmConfig);

#ifdef DEMO_PWM_CLOCK_DEVIDER
    pwmConfig.prescale = DEMO_PWM_CLOCK_DEVIDER;
#endif

    /* Use full cycle reload */
    pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
    /* PWM A & PWM B form a complementary PWM pair */
    pwmConfig.pairOperation   = kPWM_Independent;
	pwmConfig.prescale        = kPWM_Prescale_Divide_4;
    pwmConfig.enableDebugMode = true;

    /* Initialize submodule 0 */
    if (PWM_Init(PWM1, kPWM_Module_0, &pwmConfig) == kStatus_Fail)
    {
        PRINTF("PWM initialization failed\r\n");
    }

    pwmConfig.clockSource           = kPWM_BusClock;
    pwmConfig.prescale              = kPWM_Prescale_Divide_4;
    pwmConfig.initializationControl = kPWM_Initialize_LocalSync;	//initializationControl
    if (PWM_Init(PWM1, kPWM_Module_1, &pwmConfig) == kStatus_Fail)
    {
        PRINTF("PWM initialization failed\r\n");
    }

    /* Initialize submodule 2 the same way as submodule 1 */
    if (PWM_Init(PWM1, kPWM_Module_2, &pwmConfig) == kStatus_Fail)
    {
        PRINTF("PWM initialization failed\r\n");
    }
		
		    /* Initialize submodule 3 the same way as submodule 1 */
    if (PWM_Init(PWM1, kPWM_Module_3, &pwmConfig) == kStatus_Fail)
    {
        PRINTF("PWM initialization failed\r\n");
    }

    /*
     *   config->faultClearingMode = kPWM_Automatic;
     *   config->faultLevel = false;
     *   config->enableCombinationalPath = true;
     *   config->recoverMode = kPWM_NoRecovery;
     */
    PWM_FaultDefaultConfig(&faultConfig);

#ifdef DEMO_PWM_FAULT_LEVEL
    faultConfig.faultLevel = DEMO_PWM_FAULT_LEVEL;
#endif

    /* Sets up the PWM fault protection */
    PWM_SetupFaults(PWM1, kPWM_Fault_0, &faultConfig);
    PWM_SetupFaults(PWM1, kPWM_Fault_1, &faultConfig);
    PWM_SetupFaults(PWM1, kPWM_Fault_2, &faultConfig);
    PWM_SetupFaults(PWM1, kPWM_Fault_3, &faultConfig);

    /* Set PWM fault disable mapping for submodule 0/1/2/3 */
    PWM_SetupFaultDisableMap(PWM1, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0,
                             kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
    PWM_SetupFaultDisableMap(PWM1, kPWM_Module_1, kPWM_PwmA, kPWM_faultchannel_0,
                             kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
    PWM_SetupFaultDisableMap(PWM1, kPWM_Module_2, kPWM_PwmA, kPWM_faultchannel_0,
                             kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);

    /* Call the init function with demo configuration */
    pwm_set_param(pwm_no, frq, gpio_no, pwm_mode);

    /* Set the load okay bit for all submodules to load registers from their buffer */
    PWM_SetPwmLdok(PWM1, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2 | kPWM_Control_Module_3, true);

    /* Start the PWM generation from Submodules 0, 1 and 2 */
    PWM_StartTimer(PWM1, kPWM_Control_Module_0 | kPWM_Control_Module_1 | kPWM_Control_Module_2 | kPWM_Control_Module_3);
}

static PWM_Type *const s_pwmBases[] = PWM_BASE_PTRS;

static uint32_t PWM_GetInstance(PWM_Type *base)
{
    uint32_t instance;
    /* Find the instance index from base address mappings. */
    for (instance = 0; instance < ARRAY_SIZE(s_pwmBases); instance++)
    {
        if (s_pwmBases[instance] == base)
        {
            break;
        }
    }
    assert(instance < ARRAY_SIZE(s_pwmBases));

    return instance;
}

pwm_set_param 函数

void pwm_set_param(pwm_no_t pwm_no,uint32 frq,gpio_no_t gpio_no,pwm_mode_t pwm_mode)
{
	pwm_t pwm_com;
	pwm_com = pwm_set_mux(pwm_no,gpio_no);
    uint16_t deadTimeVal;
    pwm_signal_param_t pwmSignal[3];
    uint32_t pwmSourceClockInHz;
    uint32_t pwmFrequencyInHz = frq;

    pwmSourceClockInHz = PWM_SRC_CLK_FREQ;

    /* Set deadtime count, we set this to about 650ns */
    deadTimeVal = ((uint64_t)pwmSourceClockInHz * 650) / 1000000000;

    pwmSignal[0].pwmChannel       = kPWM_PwmA;
    pwmSignal[0].level            = kPWM_HighTrue;
    pwmSignal[0].dutyCyclePercent = 50; /* 1 percent dutycycle */
    pwmSignal[0].deadtimeValue    = deadTimeVal;
    pwmSignal[0].faultState       = kPWM_PwmFaultState0;

    pwmSignal[1].pwmChannel = kPWM_PwmB;
    pwmSignal[1].level      = kPWM_HighTrue;
    /* Dutycycle field of PWM B does not matter as we are running in PWM A complementary mode */
    pwmSignal[1].dutyCyclePercent = 50;
    pwmSignal[1].deadtimeValue    = deadTimeVal;
    pwmSignal[1].faultState       = kPWM_PwmFaultState0;
		
	pwmSignal[2].pwmChannel = kPWM_PwmX;
    pwmSignal[2].level      = kPWM_HighTrue;
    /* Dutycycle field of PWM B does not matter as we are running in PWM A complementary mode */
    pwmSignal[2].dutyCyclePercent = 50;
    pwmSignal[2].deadtimeValue    = deadTimeVal;
    pwmSignal[2].faultState       = kPWM_PwmFaultState0;
		
	switch(pwm_com)
	{
		case pwm0A:
			PWM_SetupPwm(PWM1, kPWM_Module_0, pwmSignal, 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm0B:
			PWM_SetupPwm(PWM1, kPWM_Module_0, &pwmSignal[1], 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm0X:
			PWM_SetupPwm(PWM1, kPWM_Module_0, &pwmSignal[2], 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm1A:
			PWM_SetupPwm(PWM1, kPWM_Module_1, pwmSignal, 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm1B:
			PWM_SetupPwm(PWM1, kPWM_Module_1, &pwmSignal[1], 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm1X:
			PRINTF("out put PWM0X\r\n");
			PWM_SetupPwm(PWM1, kPWM_Module_1, &pwmSignal[2], 1, kPWM_NonAligned, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm2A:
			PWM_SetupPwm(PWM1, kPWM_Module_2, pwmSignal, 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm2B:
			PWM_SetupPwm(PWM1, kPWM_Module_2, &pwmSignal[1], 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm2X:
			PWM_SetupPwm(PWM1, kPWM_Module_2, &pwmSignal[2], 1, kPWM_NonAligned , pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm3A:
			PWM_SetupPwm(PWM1, kPWM_Module_3, pwmSignal, 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm3B:
			PWM_SetupPwm(PWM1, kPWM_Module_3, &pwmSignal[1], 1, pwm_mode, pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		case pwm3X:
			PRINTF("out put PWM3X\r\n");
			PWM_SetupPwm(PWM1, kPWM_Module_3, &pwmSignal[2], 1, kPWM_NonAligned , pwmFrequencyInHz,pwmSourceClockInHz);
			break;
		default: break;	
	}
}

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值