S32 Design Studio PE工具配置flexTimer_pwm

工具配置

它跟flextimer_ic一样都是需要用FTM设备的,也是要配置对应的引脚。不熟悉的可以看看这篇文章S32 Design Studio PE工具配置flexTimer_ic-CSDN博客

initialization

这里的配置跟flexTimer_ic的差不多,一样的地方就不再赘述,主要区别是用了48M的系统时钟,2分频之后就变成了24M给到FTM0,操作模式变味了输出边沿对齐的PWM波。最下面的register sync默认就行。

生成代码

也就是对应上面的配置信息

/* PWM configuration for flexTimer_pwm0 */
 ftm_pwm_param_t flexTimer_pwm0_PwmConfig =
{
     3U, /* Number of independent PWM channels */
     0U, /* Number of combined PWM channels */
     FTM_MODE_EDGE_ALIGNED_PWM, /* PWM mode */
     0U, /* Dead time value */
     FTM_DEADTIME_DIVID_BY_1, /* Dead time value */
     24000U, /* PWM frequency */
     flexTimer_pwm0_IndependentChannelsConfig, /* Independent PWM channels configuration structure */
     NULL, /* No PWM channels configuration structure */
     &flexTimer_pwm0_FaultConfig /* PWM fault configuration structure */
};

configuration

General PWM congifurations

上面的24M是动不了的,1000计数为一个周期。

fault mode initalization

这里默认配置就行,虽然显示4个通道,其实并非都用上的。

PWM independent configuration

这里就配置通道极性和占空比就行。极性low就是平时为low,占空比时候为high。占空比可以填0-0x8000,这的0x4000就是50%占空比。

PWM combined configuration

默认就行

生成代码

在Generated_Code/flexTimer_pwm0.c 里面

/* Global configuration of flexTimer_pwm0 */
ftm_user_config_t  flexTimer_pwm0_InitConfig =
{
    {
        true,   /* Software trigger state */
        false,  /* Hardware trigger 1 state */
        false,  /* Hardware trigger 2 state */
        false,  /* Hardware trigger 3 state */
        false, /* Max loading point state */
        false, /* Min loading point state */
        FTM_SYSTEM_CLOCK, /* Update mode for INVCTRL register */
        FTM_SYSTEM_CLOCK, /* Update mode for SWOCTRL register */
        FTM_SYSTEM_CLOCK, /* Update mode for OUTMASK register */
        FTM_SYSTEM_CLOCK, /* Update mode for CNTIN register */
        true, /* Automatic clear of the trigger*/
        FTM_UPDATE_NOW, /* Synchronization point */
    },
     FTM_MODE_EDGE_ALIGNED_PWM, /* Mode of operation for FTM */
     FTM_CLOCK_DIVID_BY_2, /* FTM clock prescaler */
     FTM_CLOCK_SOURCE_SYSTEMCLK,   /* FTM clock source */
     FTM_BDM_MODE_00, /* FTM debug mode */
     false, /* Interrupt state */
     false /* Initialization trigger */
};

初始化

也是跟flexTimer_ic一样,初始化个外设和通道。

FTM_DRV_Init(INST_FLEXTIMER_PWM1, &flexTimer_pwm0_InitConfig, &ftmStateStruct0);
FTM_DRV_InitPwm(INST_FLEXTIMER_PWM1, &flexTimer_pwm0_PwmConfig);

接口使用

除了上一篇讲到的接口,还有SDK里面带的接口,在SDK\platform\drivers\src\ftm\ftm_pwm_driver.c里面。

FTM_DRV_InitPwmIndependentChannel

初始化独立通道,这个在初始化函数里面用到。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_InitPwmIndependentChannel
 * Description   : Configures the PWM signal for the independent channel.
 *
 *END**************************************************************************/
static void FTM_DRV_InitPwmIndependentChannel(uint32_t instance,
                                              const ftm_pwm_param_t * param)
{
    FTM_Type * ftmBase = g_ftmBase[instance];
    uint8_t index = 0U;
    uint8_t channelId = 0U;
    uint8_t chnlPairNum = 0U;

    /* Configure independent PWM channels */
    for (index = 0U; index < param->nNumIndependentPwmChannels; index++)
    {
        channelId = param->pwmIndependentChannelConfig[index].hwChannelId;
        chnlPairNum =  (uint8_t)(channelId >> 1U);
        /* Configure POL bits for fail safe state */
        FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId, (bool)param->pwmIndependentChannelConfig[index].safeState);

        /* Configure polarity of the PWM signal taking into consideration POL and ELSA/ELSB */
        if ((uint32_t)(param->pwmIndependentChannelConfig[index].safeState) == (uint32_t)(param->pwmIndependentChannelConfig[index].polarity))
        {
            FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, (uint8_t)1U);
        }
        else
        {
            FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, (uint8_t)2U);
        }

        if (param->pwmIndependentChannelConfig[index].enableSecondChannelOutput)
        {
            /* Configure dead time, and enable complementary channel. */
            FTM_DRV_SetDualChnDeadtimeCmd(ftmBase, chnlPairNum, param->pwmIndependentChannelConfig[index].deadTime);
            FTM_DRV_SetChnEdgeLevel(ftmBase, channelId + 1U, (uint8_t)2U);
            FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, true);
            if (param->pwmIndependentChannelConfig[index].secondChannelPolarity == FTM_MAIN_INVERTED)
            {
                FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId + 1U, (bool)param->pwmIndependentChannelConfig[index].safeState);
            }
            else
            {
                FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId + 1U, !((bool)param->pwmIndependentChannelConfig[index].safeState));
            }
        }
        else
        {
            FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, false);
        }

        /* Disable combined mode. */
        FTM_DRV_SetDualEdgeCaptureCmd(ftmBase, chnlPairNum, false);
        FTM_DRV_SetDualChnCombineCmd(ftmBase, chnlPairNum, false);
        FTM_DRV_SetDualChnMofCombineCmd(ftmBase, chnlPairNum, false);
        /* Set MSB and MSA bits*/
        FTM_DRV_SetChnMSnBAMode(ftmBase, channelId, 3U);
        /* Configure fault mode */
        FTM_DRV_SetDualChnFaultCmd(ftmBase, chnlPairNum, ((param->faultConfig)->faultMode != FTM_FAULT_CONTROL_DISABLED) ? true : false);
        /* Enable sync control for channels*/
        FTM_DRV_SetDualChnPwmSyncCmd(ftmBase, chnlPairNum, true);
        /* Enable the generation a trigger on chip module */
        FTM_DRV_SetChnTriggerCmd(ftmBase, channelId, param->pwmIndependentChannelConfig[index].enableExternalTrigger);

        /* Write FTMn_PWMLOAD register to enable synchronized loading points for the given channel */
        FTM_DRV_EnablePwmChannelOutputs(ftmBase, channelId);
        if (param->pwmIndependentChannelConfig[index].enableSecondChannelOutput)
        {
            FTM_DRV_EnablePwmChannelOutputs(ftmBase, channelId + 1U);
        }
    }
}

FTM_DRV_InitPwmCombinedChannel

初始化通道,也是在初始化函数里面有用到。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_InitPwmCombinedChannel
 * Description   : Configures the PWM signal for the combined channel.
 *
 *END**************************************************************************/
static void FTM_DRV_InitPwmCombinedChannel(uint32_t instance,
                                           const ftm_pwm_param_t * param)
{
    FTM_Type * ftmBase = g_ftmBase[instance];
    uint8_t index = 0U;
    uint8_t channelId = 0U;
    uint8_t chnlPairNum = 0U;

    /* Configure combined PWM channels */
    for (index = 0U; index < param->nNumCombinedPwmChannels; index++)
    {
        channelId = param->pwmCombinedChannelConfig[index].hwChannelId;
        chnlPairNum = (uint8_t)(channelId >> 1U);
        /* Check if the channel id is even number */
        DEV_ASSERT((channelId % 2U) == 0U);

        /* Configure POL bits for fail safe state */
        FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId, (bool)param->pwmCombinedChannelConfig[index].mainChannelSafeState);

        /* Configure polarity of the PWM signal taking into consideration POL and ELSA/ELSB */
        if ((uint32_t)(param->pwmCombinedChannelConfig[index].mainChannelSafeState) == (uint32_t)(param->pwmCombinedChannelConfig[index].mainChannelPolarity))
        {
            FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, (uint8_t)1U);
        }
        else
        {
            FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, (uint8_t)2U);
        }

        FTM_DRV_SetDualEdgeCaptureCmd(ftmBase, chnlPairNum, false);
        /* Set MSB and MSA bits */
        FTM_DRV_SetChnMSnBAMode(ftmBase, channelId, 3U);

        /* Enable channel (n) output */
        FTM_DRV_EnablePwmChannelOutputs(ftmBase, channelId);
        /* Configure channel n+1 if it necessary. */
        if (param->pwmCombinedChannelConfig[index].enableSecondChannelOutput)
        {
            channelId = channelId + 1U;
            /* Configure POL bits for fail safe state */
            FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId, (bool)param->pwmCombinedChannelConfig[index].secondChannelSafeState);
            FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, (uint8_t)2U);
            /* Configure polarity of the second channel relative to main channel polarity. */
            if (param->pwmCombinedChannelConfig[index].secondChannelSafeState == param->pwmCombinedChannelConfig[index].mainChannelSafeState)
            {
                if(param->pwmCombinedChannelConfig[index].secondChannelPolarity == FTM_MAIN_DUPLICATED)
                {
                    /* If dead time is enabled and COMPx = 0 the channel n+1 is automatically disabled. */
                    DEV_ASSERT(!(param->pwmCombinedChannelConfig[index].deadTime));
                    FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, false);
                }
                else
                {
                    FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, true);
                }
            }
            else
            {
                if(param->pwmCombinedChannelConfig[index].secondChannelPolarity == FTM_MAIN_DUPLICATED)
                {
                    FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, true);
                }
                else
                {
                    /* If dead time is enabled and COMPx = 0 the channel n+1 is automatically disabled. */
                    DEV_ASSERT(!(param->pwmCombinedChannelConfig[index].deadTime));
                    FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, false);
                }
            }
            /* Enable channel (n+1) output */
            FTM_DRV_EnablePwmChannelOutputs(ftmBase, (uint8_t)(channelId));
        }

        /* Set fault control for the channel */
        FTM_DRV_SetDualChnFaultCmd(ftmBase, chnlPairNum, ((param->faultConfig)->faultMode != FTM_FAULT_CONTROL_DISABLED) ? true : false);
        /* Enable sync control for channels */
        FTM_DRV_SetDualChnPwmSyncCmd(ftmBase, chnlPairNum, true);
        /* Enable the combine mode */
        FTM_DRV_SetDualChnCombineCmd(ftmBase, chnlPairNum, true);
        /* Configure the modified combine mode */
        FTM_DRV_SetDualChnMofCombineCmd(ftmBase, chnlPairNum, param->pwmCombinedChannelConfig[index].enableModifiedCombine);
        /* Configure dead time */
        FTM_DRV_SetDualChnDeadtimeCmd(ftmBase, chnlPairNum, param->pwmCombinedChannelConfig[index].deadTime);
        /* Enable the generation a trigger on the channel (n) */
        channelId = (uint8_t)(chnlPairNum << 1U);
        FTM_DRV_SetChnTriggerCmd(ftmBase, channelId, param->pwmCombinedChannelConfig[index].enableExternalTrigger);
        /* Enable the generation a trigger on the channel (n+1) */
        channelId = channelId + 1U;
        FTM_DRV_SetChnTriggerCmd(ftmBase, channelId, param->pwmCombinedChannelConfig[index].enableExternalTriggerOnNextChn);
    }
}

FTM_DRV_InitPwmDutyCycleChannel

初始化占空比周期,在初始化函数里面用到。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_InitPwmDutyCycleChannel
 * Description   : This function will update the duty cycle for the PWM signal
 * at the initialization.
 *
 *END**************************************************************************/
static status_t FTM_DRV_InitPwmDutyCycleChannel(uint32_t instance,
                                                const ftm_pwm_param_t * param)
{
    uint8_t index = 0U;
    uint8_t hwChannel = 0U;
    status_t retVal = STATUS_SUCCESS;

    for (index = 0U; index < param->nNumIndependentPwmChannels; index++)
    {
        hwChannel = param->pwmIndependentChannelConfig[index].hwChannelId;
        /* Write CnV registers and setup duty cycle and phase values */
        retVal = FTM_DRV_UpdatePwmChannel(instance,
                                          hwChannel,
                                          FTM_PWM_UPDATE_IN_DUTY_CYCLE,
                                          param->pwmIndependentChannelConfig[index].uDutyCyclePercent,
                                          0U,
                                          false);
    }

    for (index = 0U; index < param->nNumCombinedPwmChannels; index++)
    {
        hwChannel = param->pwmCombinedChannelConfig[index].hwChannelId;
        /* Write CnV registers and setup duty cycle and phase values */
        retVal = FTM_DRV_UpdatePwmChannel(instance,
                                          hwChannel,
                                          FTM_PWM_UPDATE_IN_DUTY_CYCLE,
                                          param->pwmCombinedChannelConfig[index].firstEdge,
                                          param->pwmCombinedChannelConfig[index].secondEdge,
                                          false);
    }

    return retVal;
}

FTM_DRV_InitPwm

PWM输出专用的初始化接口

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_InitPwm
 * Description   : Configures duty cycle and frequency and starts outputting
 * PWM on specified channels.
 *
 * Implements    : FTM_DRV_InitPwm_Activity
 *END**************************************************************************/
status_t FTM_DRV_InitPwm(uint32_t instance,
                         const ftm_pwm_param_t * param)
{
    DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
    DEV_ASSERT(param != NULL);
    status_t retVal = STATUS_SUCCESS;
    uint8_t fltChannel = 0U;
    uint8_t faultChnNum = 0U;
    uint32_t tempInst = instance;
    ftm_state_t * state = ftmStatePtr[instance];
    FTM_Type * ftmBase = g_ftmBase[instance];

    if ((NULL != state) && (FTM_MODE_NOT_INITIALIZED == state->ftmMode))
    {
        /* Disable counter clock */
        FTM_DRV_SetClockSource(ftmBase, FTM_CLOCK_SOURCE_NONE);
        /* Clear the overflow flag */
        FTM_DRV_ClearTimerOverflow(ftmBase);
        /* Disable write protection */
        FTM_DRV_SetWriteProtectionCmd(ftmBase, false);
        /* Configure FTM mode */
        state->ftmMode = param->mode;
        /* Configure independent PWM channels */
        FTM_DRV_InitPwmIndependentChannel(instance, param);
        /* Configure combined PWM channels */
        FTM_DRV_InitPwmCombinedChannel(instance, param);
        /* Set enable outputs to be set to Initial/default value */
        FTM_DRV_SetInitChnOutputCmd(ftmBase, true);
        /* Enable faults (if faults were configured) */
        if ((param->faultConfig)->faultMode != FTM_FAULT_CONTROL_DISABLED)
        {
            /* Configure PWM Output behavior */
            FTM_DRV_SetPwmFaultBehavior(ftmBase, ((param->faultConfig)->pwmOutputStateOnFault) ? true : false);
            /* Configure fault filter value */
            FTM_DRV_SetFaultInputFilterVal(ftmBase, ((param->faultConfig)->faultFilterValue));
            /* Check the FTM instances */
            if (tempInst <= 3U)
            {
                faultChnNum = (uint8_t)FTM_FEATURE_FAULT_CHANNELS;
            }
            else
            {
                faultChnNum = (uint8_t)(FTM_FEATURE_FAULT_CHANNELS >> 1U);
            }

            for (fltChannel = 0U; fltChannel < faultChnNum; fltChannel++)
            {
                if (true == (param->faultConfig)->ftmFaultChannelParam[fltChannel].faultChannelEnabled)
                {
                    /* Enable fault channel */
                    FTM_DRV_SetFaultInputCmd(ftmBase, fltChannel, true);
                    /* Configure fault filter */
                    FTM_DRV_SetFaultInputFilterCmd(ftmBase,
                                                   fltChannel,
                                                   ((param->faultConfig)->ftmFaultChannelParam[fltChannel].faultFilterEnabled) ? true : false);
                    /* Configure fault outputs */
                    FTM_DRV_SetChnFaultInputPolarityCmd(ftmBase,
                                                        fltChannel,
                                                        (((param->faultConfig)->ftmFaultChannelParam[fltChannel].ftmFaultPinPolarity  == FTM_POLARITY_HIGH)? true : false));
                }
            }

            /* Set fault interrupt */
            if (true == ((param->faultConfig)->pwmFaultInterrupt))
            {
                FTM_DRV_SetFaultInt(ftmBase, true);
            }

            /* Enable fault control */
            FTM_DRV_SetFaultControlMode(ftmBase, (uint32_t)(param->faultConfig)->faultMode);
        }

        /* Configure PWM mode: edge or center aligned */
        FTM_DRV_SetCpwms(ftmBase, (param->mode == FTM_MODE_CEN_ALIGNED_PWM) ? true : false);
        /* Calculate frequency of the give FTM hardware module - all channels will run at the same frequency */
        state->ftmPeriod = FTM_DRV_ConvertFreqToPeriodTicks(instance, param->uFrequencyHZ);
        /* Based on reference manual, in PWM mode CNTIN is to be set 0*/
        FTM_DRV_SetCounterInitVal(ftmBase, 0U);
        /* Write MOD register with the value of the period */
        /* For center aligned mode MOD register should be divided by 2 */
        /* For edge aligned mode period is determined by: MOD-CNTIN+1 */
        if (param->mode == FTM_MODE_CEN_ALIGNED_PWM)
        {
            FTM_DRV_SetMod(ftmBase, (uint16_t)(state->ftmPeriod >> 1U));
        }
        else
        {
            FTM_DRV_SetMod(ftmBase, (uint16_t)(state->ftmPeriod - 1U));
        }

        /* Update the duty cycle */
        retVal = FTM_DRV_InitPwmDutyCycleChannel(instance, param);

        if (STATUS_SUCCESS == retVal)
        {
            /* Configure dead time for combine mode */
            FTM_DRV_SetDeadtimeCount(ftmBase, param->deadTimeValue);
            FTM_DRV_SetDeadtimePrescale(ftmBase, param->deadTimePrescaler);
            FTM_DRV_Enable(ftmBase, true);
            FTM_DRV_SetPwmSyncMode(ftmBase, true);
            /* Set clock source to start counter */
            FTM_DRV_SetClockSource(ftmBase, state->ftmClockSource);
        }
        else
        {
            /* Restore FTM mode if initialization fails */
            state->ftmMode = FTM_MODE_NOT_INITIALIZED;
        }
    }
    else
    {
        retVal = STATUS_ERROR;
    }

    return retVal;
}

FTM_DRV_DeinitPwm

逆初始化

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_DeinitPwm
 * Description   : Stops all PWM channels.
 *
 * Implements    : FTM_DRV_DeinitPwm_Activity
 *END**************************************************************************/
status_t FTM_DRV_DeinitPwm(uint32_t instance)
{
    DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
    FTM_Type * ftmBase = g_ftmBase[instance];
    uint8_t channel;
    uint8_t chnlPairNum;
    ftm_state_t * state = ftmStatePtr[instance];
    DEV_ASSERT(state != NULL);

    /* Stop the FTM counter */
    FTM_DRV_SetClockSource(ftmBase, FTM_CLOCK_SOURCE_NONE);
    for (channel = 0U; channel < FEATURE_FTM_CHANNEL_COUNT; channel++)
    {
        chnlPairNum = (uint8_t)(channel >> 1U);
        /* Disable PWM mode in hardware */
        FTM_DRV_SetChnCountVal(ftmBase, channel, 0U);
        FTM_DRV_SetChnEdgeLevel(ftmBase, channel, 0U);
        FTM_DRV_SetChnMSnBAMode(ftmBase, channel, 0U);
        FTM_DRV_SetCpwms(ftmBase, false);
        /* Configure polarity bit */
        FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channel, false);
        FTM_DRV_DisablePwmChannelOutputs(ftmBase, channel);
        /* Clear the PWM synchronization */
        FTM_DRV_SetDualChnPwmSyncCmd(ftmBase, chnlPairNum, false);
        /* Clear combination for each pair of channels */
        FTM_DRV_SetDualChnMofCombineCmd(ftmBase, chnlPairNum, false);
        FTM_DRV_SetDualChnCombineCmd(ftmBase, chnlPairNum, false);
        FTM_DRV_SetDualChnDeadtimeCmd(ftmBase, chnlPairNum, false);
        FTM_DRV_SetDualChnFaultCmd(ftmBase, chnlPairNum, false);
    }

    /* Clear the dead-time pre-scaler and value */
    FTM_DRV_SetExtDeadtimeValue(ftmBase, 0U);
    FTM_DRV_SetDeadtimePrescale(ftmBase, FTM_DEADTIME_DIVID_BY_1);
    FTM_DRV_SetDeadtimeCount(ftmBase, 0U);
    /* Clear fault control register */
    FTM_DRV_ClearFaultControl(ftmBase);
    /* Disable fault interrupt */
    FTM_DRV_SetFaultInt(ftmBase, false);
    /* Disable fault control */
    FTM_DRV_SetFaultControlMode(ftmBase, (uint32_t)FTM_FAULT_CONTROL_DISABLED);
    /* Clear the module value of the registers */
    FTM_DRV_SetMod(ftmBase, 0U);
    FTM_DRV_SetCounter(ftmBase, 0U);
    state->ftmMode = FTM_MODE_NOT_INITIALIZED;

    return STATUS_SUCCESS;
}

FTM_DRV_UpdatePwmChannel

改变通道输出的PWM占空比,这个相当重要。入参顺序是:设备号、通道号、操作方式(FTM_PWM_UPDATE_IN_DUTY_CYCLE还是FTM_PWM_UPDATE_IN_TICKS),第一边沿(占空比),第二边沿(窗口PWM采用得到,默认写0),是否软件触发(一般写1)。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_UpdatePwmChannel
 * Description   : This function will update the duty cycle of PWM output.
 * - If the type of update in the duty cycle, this function will convert the input parameters representing
 * frequency in Hz to a period value in ticks needed by the hardware timer. Period is calculated depending
 * on the operating mode of the FTM module and is stored in internal state structure.
 * firstEdge and secondEdge can have value between 0 - FTM_MAX_DUTY_CYCLE(0 = 0% duty
 * and FTM_MAX_DUTY_CYCLE = 100% duty). secondEdge value is used only whenFTM module is used in PWM combine mode.
 * - If the type of update in ticks, this function will get value in ticks to the hardware timer.
 * firstEdge and secondEdge variables can have value between 0 and ftmPeriod is stored in the state structure.
 * - in the modified combine mode, the firstEdge parameter is fixed value and only can modify the secondEdge variables
 * which is the initial value in the channel (n+1) match edge when the FTM counter has been ran.
 *
 * Implements    : FTM_DRV_UpdatePwmChannel_Activity
 *END**************************************************************************/
status_t FTM_DRV_UpdatePwmChannel(uint32_t instance,
                                  uint8_t channel,
                                  ftm_pwm_update_option_t typeOfUpdate,
                                  uint16_t firstEdge,
                                  uint16_t secondEdge,
                                  bool softwareTrigger)
{
    DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
    DEV_ASSERT(channel < FEATURE_FTM_CHANNEL_COUNT);
    uint16_t hwFirstEdge = 0U;
    uint16_t hwSecondEdge = 0U;
    uint16_t ftmPeriod = 0U;
    uint8_t chnlPairNum = (uint8_t)(channel >> 1U);
    FTM_Type * ftmBase = g_ftmBase[instance];
    ftm_state_t * state = ftmStatePtr[instance];
    status_t retStatus = STATUS_SUCCESS;

    /* Get the newest period in the MOD register */
    ftmPeriod = FTM_DRV_GetMod(ftmBase);
    /* Check the mode operation in FTM module */
    if (state->ftmMode == FTM_MODE_CEN_ALIGNED_PWM)
    {
        ftmPeriod = (uint16_t)(ftmPeriod << 1U);
    }
    else if (state->ftmMode == FTM_MODE_EDGE_ALIGNED_PWM)
    {
        ftmPeriod = (uint16_t)(ftmPeriod + 1U);
    }
    else
    {
        retStatus = STATUS_ERROR;
    }

    /* Check the type of update for PWM */
    if (FTM_PWM_UPDATE_IN_DUTY_CYCLE == typeOfUpdate)
    {
        if ((firstEdge <= FTM_MAX_DUTY_CYCLE) && (secondEdge <= FTM_MAX_DUTY_CYCLE))
        {
            /* Calculate DutyCycle based of the previously calculated frequency*/
            /* For greater resolution the DutyCycle values are in the range [0. FTM_MAX_DUTY_CYCLE]
             *  where 0 = 0% or PWM always at Low and FTM_MAX_DUTY_CYCLE = 100% or PWM always HIGH;
             *  a value of 0x4000 is equivalent of 50% DutyCycle. */
            hwFirstEdge = (uint16_t)((ftmPeriod * firstEdge) >> FTM_DUTY_TO_TICKS_SHIFT);
            hwSecondEdge = (uint16_t)((ftmPeriod * secondEdge) >> FTM_DUTY_TO_TICKS_SHIFT);
            /* adjust DutyCycle if 100% value is to be achieved. */
            if (FTM_MAX_DUTY_CYCLE == firstEdge)
            {
                /* If expected duty is 100% then increase by 1 the value that is to be written
                 *  to Hardware so it will exceed value of period */
                hwFirstEdge = (uint16_t)(hwFirstEdge + 1U);
            }
        }
        else
        {
            retStatus = STATUS_ERROR;
        }
    }
    else
    {
        if ((firstEdge <= ftmPeriod) && (secondEdge <= ftmPeriod))
        {
            hwFirstEdge = firstEdge;
            hwSecondEdge = secondEdge;
        }
        else
        {
            retStatus = STATUS_ERROR;
        }
    }

    if (STATUS_SUCCESS == retStatus)
    {
        if (true == FTM_DRV_GetDualChnCombineCmd(ftmBase, chnlPairNum))
        {
            if (true == FTM_DRV_GetDualChnMofCombineCmd(ftmBase, chnlPairNum))
            {
                /* Check the clock source for FTM counter is disabled or not */
                if (FTM_DRV_GetClockSource(ftmBase) == 0U)
                {
                    FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)(chnlPairNum * 2U), hwFirstEdge);
                }
            }
            else
            {
                FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)(chnlPairNum * 2U), hwFirstEdge);
            }

            /* Modify the initial value in the channel (n+1) match edge */
            FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)((chnlPairNum * 2U) + 1U), hwSecondEdge);
        }
        else
        {
            /* Channel value is divided by 2 for up down counter mode to keep same duty */
            if (true == FTM_DRV_GetCpwms(ftmBase))
            {
                FTM_DRV_SetChnCountVal(ftmBase, channel, (uint16_t)(hwFirstEdge >> 1U));
            }
            else
            {
                FTM_DRV_SetChnCountVal(ftmBase, channel, hwFirstEdge);
            }
        }

        /* Software trigger is generated to change CnV registers */
        /* Before this please configure sync mechanism to use software trigger */
        FTM_DRV_SetSoftwareTriggerCmd(ftmBase, softwareTrigger);

        /* Store the PWM period in the state structure */
        state->ftmPeriod = ftmPeriod;
    }

    return retStatus;
}

FTM_DRV_UpdatePwmPeriod

更新PWM输出的周期,这个也很重要,是调占空比或者调周期两种方式的其中一种。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_UpdatePwmPeriod
 * Description   : This function will update the new period in the frequency or
 * in the counter value into mode register which modify the period of PWM signal
 * on the channel output.
 * - If the type of update in the duty cycle which is reused in FTM_DRV_UpdatePwmChannel
 * function to convert the newValue parameters representing frequency in Hz to
 * a period value to update the MOD register. The newValue parameter must be value
 * between 1U and maximum is the frequency of the FTM counter.
 * - If the type of update in ticks, this function will get value in counting to
 * the MOD register. The newValue parameter must be value between 1U and 0xFFFFU
 *
 * Implements : FTM_DRV_UpdatePwmPeriod_Activity
 *END**************************************************************************/
status_t FTM_DRV_UpdatePwmPeriod(uint32_t instance,
                                 ftm_pwm_update_option_t typeOfUpdate,
                                 uint32_t newValue,
                                 bool softwareTrigger)
{
    DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
    DEV_ASSERT(newValue != 0U);
    uint32_t ftmPeriod = 0U;
    FTM_Type * ftmBase = g_ftmBase[instance];
    ftm_state_t * state = ftmStatePtr[instance];
    status_t retStatus = STATUS_SUCCESS;

    /* Check the type of update for period in PWM mode */
    if (FTM_PWM_UPDATE_IN_TICKS == typeOfUpdate)
    {
        ftmPeriod = newValue;
    }
    else
    {
        if (newValue <= state->ftmSourceClockFrequency)
        {
            ftmPeriod = (uint32_t)FTM_DRV_ConvertFreqToPeriodTicks(instance, newValue);
        }
        else
        {
            retStatus = STATUS_ERROR;
        }
    }

    if (STATUS_SUCCESS == retStatus)
    {
        /* Check the ftmPeriod is invalid */
        DEV_ASSERT(ftmPeriod <= 0xFFFFU);
        /* Check the signal operation in which PWM mode */
        DEV_ASSERT((FTM_MODE_CEN_ALIGNED_PWM == state->ftmMode) || (FTM_MODE_EDGE_ALIGNED_PWM == state->ftmMode));
        if (FTM_MODE_CEN_ALIGNED_PWM == state->ftmMode)
        {
            ftmPeriod = (ftmPeriod >> 1U);
        }
        else
        {
            ftmPeriod = (ftmPeriod - 1U);
        }
        /* Set the new modulo value into MOD register */
        FTM_DRV_SetMod(ftmBase, (uint16_t)(ftmPeriod));
        /* Software trigger is generated to change MOD registers */
        FTM_DRV_SetSoftwareTriggerCmd(ftmBase, softwareTrigger);

        /* Store the PWM period in the state structure */
        state->ftmPeriod = (uint16_t)ftmPeriod;
    }

    return retStatus;
}

FTM_DRV_FastUpdatePwmChannels

更新通道,基本不会用。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_FastUpdatePwmChannels
 * Description   : This function will update the duty cycle of PWM output for multiple channels.
 *
 * The main differences between this function and FTM_DRV_UpdatePwmChannel is the execution speed. This
 * feature makes this function ideal for applications like motor controlling.
 * The downside is the low flexibility of the parameters (this function accept only updates in ticks).
 *
 * Implements : FTM_DRV_FastUpdatePwmChannels_Activity
 *END**************************************************************************/
status_t FTM_DRV_FastUpdatePwmChannels(uint32_t instance,
                                       uint8_t numberOfChannels,
                                       const uint8_t * channels,
                                       const uint16_t * duty,
                                       bool softwareTrigger)
{
    FTM_Type * ftmBase = g_ftmBase[instance];
    DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
    DEV_ASSERT(numberOfChannels <= FEATURE_FTM_CHANNEL_COUNT);
    uint8_t i;

    for (i = 0U; i < numberOfChannels; i++)
    {
        ((ftmBase)->CONTROLS[channels[i]].CnV) = duty[i];
    }

    if (softwareTrigger)
    {
       ftmBase->SYNC |= FTM_SYNC_SWSYNC_MASK;
    }

    return STATUS_SUCCESS;
}

FTM_DRV_ControlChannelOutput

控制通道是否输出,初始化之后就是输出的,一般只有想关的时候才会调用。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_ControlChannelOutput
 * Description   : This function is used to control the final logic of the
 * channel output.
 *
 * Implements : FTM_DRV_ControlChannelOutput_Activity
 *END**************************************************************************/
status_t FTM_DRV_ControlChannelOutput(uint32_t instance,
                                      uint8_t channel,
                                      bool enableChannelOutput)
{
    DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
    DEV_ASSERT(channel < FEATURE_FTM_CHANNEL_COUNT);
    FTM_Type * ftmBase = g_ftmBase[instance];

    if (enableChannelOutput == true)
    {
        /* Enable the channel output */
        FTM_DRV_EnablePwmChannelOutputs(ftmBase, channel);
    }
    else
    {
        /* Disable the channel output */
        FTM_DRV_DisablePwmChannelOutputs(ftmBase, channel);
    }

    return STATUS_SUCCESS;
}

FTM_DRV_UpdatePwmPeriodDither

在PWM周期内使用抖动,基本不会用到。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_UpdatePwmPeriodDither
 * Description   : This function will use in the PWM period dithering. This value
 * is added to an internal accumulator at the end of each PWM period. The value is
 * updated with its write buffer value according to the register synchronization.
 *
 * Implements : FTM_DRV_UpdatePwmPeriodDither_Activity
 *END**************************************************************************/
status_t FTM_DRV_UpdatePwmPeriodDither(uint32_t instance,
                                       uint8_t newModFracVal,
                                       bool softwareTrigger)
{
    DEV_ASSERT((instance == 1U) || (instance == 2U));
    DEV_ASSERT(newModFracVal <= 32U);
    FTM_Type * ftmBase = g_ftmBase[instance];

    FTM_DRV_SetModFracVal(ftmBase, newModFracVal);
    /* Software trigger is generated to change MOD_MIRROR registers */
    FTM_DRV_SetSoftwareTriggerCmd(ftmBase, softwareTrigger);

    return STATUS_SUCCESS;
}

FTM_DRV_UpdatePwmEdgeChannelDither

在PWM边沿内使用抖动,基本不会用到。

/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_DRV_UpdatePwmEdgeChannelDither
 * Description   : This function will use in the PWM edge dithering. This value
 * is added to the channel (n) internal accumulator at the end of each PWM period.
 * The FRACVAL is updated with its write buffer value according to the register
 * synchronization. The PWM edge dithering is not available when the channel in the
 * input capture modes, and the channel in output compare mode.
 *
 * Implements    : FTM_DRV_UpdatePwmEdgeChannelDither_Activity
 *END**************************************************************************/
status_t FTM_DRV_UpdatePwmEdgeChannelDither(uint32_t instance,
                                            uint8_t channel,
                                            uint8_t newMatchFracVal,
                                            bool softwareTrigger)
{
    DEV_ASSERT((instance == 1U) || (instance == 2U));
    DEV_ASSERT(channel < FEATURE_FTM_CHANNEL_COUNT);
    DEV_ASSERT(newMatchFracVal <= 32U);
    FTM_Type * ftmBase = g_ftmBase[instance];

    FTM_DRV_SetChnMatchFracVal(ftmBase, channel, newMatchFracVal);
    /* Software trigger is generated to change CnV_MIRROR registers */
    FTM_DRV_SetSoftwareTriggerCmd(ftmBase, softwareTrigger);

    return STATUS_SUCCESS;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃鱼的羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值