在线时间43 小时
UID3743754
注册时间2021-5-28
NXP金币0
TA的每日心情 | 衰 2021-8-30 18:28 |
---|
签到天数: 4 天 [LV.2]偶尔看看I
中级会员
- 积分
- 467
- 最后登录
- 2022-9-8
|
本帖最后由 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已经完整转换并且进入中断后的时刻。 是否参 ...
|
-
|