查看: 1480|回复: 3

[求助] FTM0觸發PDB再觸發ADC

[复制链接]
  • TA的每日心情

    2021-8-30 18:28
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    3

    主题

    13

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    467
    最后登录
    2022-9-8
    发表于 2021-8-30 15:17:32 | 显示全部楼层 |阅读模式
    本帖最后由 Alan_3318a3 于 2021-8-30 15:41 编辑

    使用frdm-kv31f,SDK使用2.10.0,目前利用SDK的範例程式(pdb_adc16_trigger)修改,想要達成PWM(紅色)觸發PDB經一段延遲再觸發ADC。

    PWM頻率為20kHz,PDB MOD為2999,IDLY為750,DLY為2000。
    利用PDB的中斷副程式輸出GPIO(淺藍色)代表PDB觸發的位置,剛好在PWM的1/4觸發。利用ADC的中斷副程式輸出GPIO(深藍色)代表ADC觸發的位置,發現與推論的結果有誤,應該要在PWM的67%附近觸發。
    不知道哪裡理解有錯誤?


    #include <stdio.h>
    #include "board.h"
    #include "peripherals.h"
    #include "pin_mux.h"
    #include "clock_config.h"
    #include "MKV31F51212.h"
    #include "fsl_debug_console.h"
    #include "fsl_pdb.h"
    #include "fsl_ftm.h"
    #include "fsl_adc16.h"


    #define PDB0_IRQn      PDB0_IRQn
    #define PDB0_IRQHandler PDB0_IRQHandler


    #define DEMO_ADC_BASE          ADC0
    #define DEMO_ADC_CHANNEL_GROUP 0U
    #define DEMO_ADC_USER_CHANNEL  8U
    #define DEMO_ADC_IRQ_ID        ADC0_IRQn
    #define DEMO_ADC_IRQ_HANDLER   ADC0_IRQHandler

    #define FTM_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_BusClk)

    static void DEMO_InitPDB_ADC(void);

    volatile bool g_PdbDelayInterruptFlag;
    volatile uint32_t g_PdbDelayInterruptCounter;
    volatile uint32_t pdb_mod;

    volatile bool g_AdcInterruptFlag;
    volatile uint32_t g_AdcInterruptCounter;
    volatile uint32_t g_AdcConvValue;

    void static DEMO_InitPDB_ADC(void)
    {
        adc16_config_t adc16ConfigStruct;
        adc16_channel_config_t adc16ChannelConfigStruct;

        /*
         * adc16ConfigStruct.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
         * adc16ConfigStruct.clockSource = kADC16_ClockSourceAsynchronousClock;
         * adc16ConfigStruct.enableAsynchronousClock = true;
         * adc16ConfigStruct.clockDivider = kADC16_ClockDivider8;
         * adc16ConfigStruct.resolution = kADC16_ResolutionSE12Bit;
         * adc16ConfigStruct.longSampleMode = kADC16_LongSampleDisabled;
         * adc16ConfigStruct.enableHighSpeed = false;
         * adc16ConfigStruct.enableLowPower = false;
         * adc16ConfigStruct.enableContinuousConversion = false;
         */
        ADC16_GetDefaultConfig(&adc16ConfigStruct);
        ADC16_Init(DEMO_ADC_BASE, &adc16ConfigStruct);
    #if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
        ADC16_EnableHardwareTrigger(DEMO_ADC_BASE, false);
        if (kStatus_Success == ADC16_DoAutoCalibration(DEMO_ADC_BASE))
        {
            PRINTF("ADC16_DoAutoCalibration() Done.\r\n");
        }
        else
        {
            PRINTF("ADC16_DoAutoCalibration() Failed.\r\n");
        }
    #endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
        ADC16_EnableHardwareTrigger(DEMO_ADC_BASE, true);

        adc16ChannelConfigStruct.channelNumber                        = DEMO_ADC_USER_CHANNEL;
        adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = true; /* Enable the interrupt. */
    #if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
        adc16ChannelConfigStruct.enableDifferentialConversion = false;
    #endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
        ADC16_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adc16ChannelConfigStruct);
    }

    void PDB0_IRQHandler(void)
    {
            GPIO_PinWrite(GPIOA,12,1);
        PDB_ClearStatusFlags(PDB0, kPDB_DelayEventFlag);
        GPIO_PinWrite(GPIOA,12,0);
    //    g_PdbDelayInterruptFlag = true;
    //    g_PdbDelayInterruptCounter++;
        SDK_ISR_EXIT_BARRIER;
    }

    void DEMO_ADC_IRQ_HANDLER(void)
    {
        /* Read to clear COCO flag. */
            GPIO_PinWrite(GPIOA,5,1);

        g_AdcConvValue = ADC16_GetChannelConversionValue(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP);
        g_AdcInterruptCounter++;
        g_AdcInterruptFlag = true;
        GPIO_PinWrite(GPIOA,5,0);
        SDK_ISR_EXIT_BARRIER;
    }

    int main(void) {
            pdb_config_t pdbConfigStruct;
            pdb_adc_pretrigger_config_t pdbAdcPreTriggerConfigStruct;

        ftm_config_t ftmInfo;//timer struct
            ftm_chnl_pwm_signal_param_t ftmParam;
            pdb_mod = (FTM_SOURCE_CLOCK/20000)-1;

            ftmParam.chnlNumber            = kFTM_Chnl_0;
            ftmParam.level                 = kFTM_HighTrue;
            ftmParam.dutyCyclePercent      = 50;
            ftmParam.firstEdgeDelayPercent = 0U;
            ftmParam.enableComplementary   = false;
            ftmParam.enableDeadtime        = false;

        BOARD_InitBootPins();
        BOARD_InitBootClocks();
        BOARD_InitBootPeripherals();
        BOARD_InitDebugConsole();

        EnableIRQ(DEMO_ADC_IRQ_ID);

        EnableIRQ(PDB0_IRQn);
        PDB_GetDefaultConfig(&pdbConfigStruct);
        pdbConfigStruct.triggerInputSource = kPDB_TriggerInput8;
            PDB_Init(PDB0, &pdbConfigStruct);

            /* Configure the delay interrupt. */
            PDB_SetModulusValue(PDB0, 2999);

            /* The available delay value is less than or equal to the modulus value. */
            PDB_SetCounterDelayValue(PDB0, 750);
            PDB_EnableInterrupts(PDB0, kPDB_DelayInterruptEnable);

            pdbAdcPreTriggerConfigStruct.enablePreTriggerMask          = 1U << kPDB_ADCPreTrigger0;
            pdbAdcPreTriggerConfigStruct.enableOutputMask              = 1U << kPDB_ADCPreTrigger0;
            pdbAdcPreTriggerConfigStruct.enableBackToBackOperationMask = 0U;
            PDB_SetADCPreTriggerConfig(PDB0, kPDB_ADCTriggerChannel0, &pdbAdcPreTriggerConfigStruct);
            PDB_SetADCPreTriggerDelayValue(PDB0, kPDB_ADCTriggerChannel0, kPDB_ADCPreTrigger0, 2000U);

            PDB_DoLoadValues(PDB0);

        DEMO_InitPDB_ADC();

            FTM_GetDefaultConfig(&ftmInfo);
            ftmInfo.extTriggers = 1;
            /* Initialize FTM module */
            FTM_Init(FTM0, &ftmInfo);
            /*Setup PWM param*/
            FTM_SetupPwm(FTM0, &ftmParam, 1U, kFTM_EdgeAlignedPwm, 20000U, FTM_SOURCE_CLOCK);
            /*Start timer*/
            FTM_StartTimer(FTM0, kFTM_SystemClock);
        while(1) {
    //        g_PdbDelayInterruptFlag = false;
    //        while (!g_PdbDelayInterruptFlag)
    //                {
    //                }

    //                PRINTF("PDB Delay Interrupt Counter: %d\r\n", g_PdbDelayInterruptCounter);
        }
    }





    最佳答案

    Hi Alan,ADC需要采样转换完成后才会触发中断(Sample time and total conversion time可以根据参考手册计算),所以ADC中断里翻转IO口的瞬间其实不是ADC采样的时刻,而是ADC已经完整转换并且进入中断后的时刻。 是否参 ...
    TEK00000.PNG
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    656

    主题

    6312

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    19991
    最后登录
    2024-4-23
    发表于 2021-9-1 15:43:56 | 显示全部楼层
    Hi Alan,
    ADC需要采样转换完成后才会触发中断(Sample time and total conversion time可以根据参考手册计算),所以ADC中断里翻转IO口的瞬间其实不是ADC采样的时刻,而是ADC已经完整转换并且进入中断后的时刻。
    是否参考过这篇AN?

    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2021-8-30 18:28
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    3

    主题

    13

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    467
    最后登录
    2022-9-8
     楼主| 发表于 2021-9-6 10:19:57 | 显示全部楼层
    謝謝,原來是我誤解了,我再來試試讀到的值對不對
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2021-8-30 18:28
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    3

    主题

    13

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    467
    最后登录
    2022-9-8
     楼主| 发表于 2021-11-22 22:00:05 | 显示全部楼层
    找到問題了,ADC的時鐘選擇bus clock,除頻到24MHz以下
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-4-23 19:45 , Processed in 0.128921 second(s), 25 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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