ADC - aman396271/Flagchip_Study GitHub Wiki

概要

该 ADC 是一款 12 位精度的逐次逼近 (SAR) 模数转换器。它拥有多达 38 个通道,可测量来自 32 个外部模拟源和 5 个内部模拟源的信号。各通道的 A/D 转换可以单次、连续或非续模式进行。结果数据存储在 FIFO 或结果寄存器中,格式可以是左对齐或右对齐。 image image 默认ADC是Disenable状态,需要Set ADEN=1 enable ADC,ADRDY标志着ADC是否就绪 ADDIS=1会disable ADC,并将ADC调整至power down mode,ADEN和ADDIS会在ADC完全disable是硬件清除 ADSTART=1和外部触发时间是ADC转换的开启

开始转换

在软件模式下是立即进行的,若是有触发,则在下一个触发沿开启;

停止正在进行的转换

软件可以通过在 ADC_CONTROL 寄存器中设置 ADSTP = 1 来停止任何正在进行的转换。这将重置 ADC 操作,使 ADC 处于空闲状态,准备进行新的操作。 当软件设置 ADSTP 位时,任何正在进行的转换都会中止。扫描序列也会中止并重置(这意味着重新启动 ADC 将启动一个新的序列)。此过程完成后,ADC 将返回到就绪状态,并且 ADSTP 和 ADSTART 位均由硬件清零。软件必须等到 ADSTP = 0(对于 FC4150F512,则需要另外 3 个 ADC 功能时钟周期)才能开始新的转换。

触发检测

The trigger selection is effective once the software has set bit ADSTART=1.Any hardware triggers which occur while a conversion is ongoing are ignored.If bit ADSTART=0, any hardware triggers which occur are ignored触发设置在ADSTART=1时奏效;若在转换过程中发生触发事件会被忽略;ADSTART=0时,触发事件会被忽略

Discontious模式

image image

Bit数

支持8、10、12bit ADC转换,位数越低,转化越快 image

AVG平均数

支持AVG(ADC Average Function),在AVG_EN=1使能AVG后,每4-32次(在AVG_LEN设置)做一次平均,结果输出到FIFO or ADC_RESULT image

数据对齐

数据对齐,0:right-align,1:left-align,如下图所示 image

Overflow溢出

image 溢出后需软件写1The OVR flag is cleared by software by writing 1 to it.ADC_CFG1的OVRMOD可以设置溢出后要保存的数据是旧数据还是新数据

DMA

image

中断源

image

低功耗特性

image

Single 单次扫描

初始化

时钟初始化

image SDK中的时钟配置为{PCC_CLK_ADC0, true, PCC_CLKGATE_SRC_FOSCDIV, PCC_CLK_DIV_BY1},时钟源为FOSC_DIVM image 根据时钟树,FOSC在外部晶振为24MHz(Demo板的外部晶振为24MHz)时,SDK设置tFoscCfg.eDivM = SCG_ASYNCCLOCKDIV_BY4,则ADC的外设时钟为24/4=6MHz

配置初始化

以Demo板引出PIN脚P37,即PTB20为例,其对应ADC为ADC0_SE14 首先是引脚的复用

    g_tPortEHandle.eInstance			= PORT_B;
    tInitStruct.u32PortPins			= PORT_PIN_20;
    tInitStruct.uPortPinMux.u32PortPinMode	= PORTB_20_ADC0_SE14;
    PORT_InitPins(&g_tPortEHandle, &tInitStruct);

其次是ADC配置的初始化 句柄定义

ADC_HandleType g_tAdc0Handle =
{
	.eInstance = 	ADC_INSTANCE_0,
};

通道定义

ADC_ChannelCfgType Adc0Channels[ADC0_EN_CHANNELS_NUM] =
{
		{.eChannel = ADC_CHANNEL_14,
		 .eSampleTimeOption = ADC_SAMPLE_TIME_OPTION_0},
};

初始化

void Bsp_ADC_Init(void)
{
	ADC_InitType tAdc0InitCfg;
	ADC_StatusType Adc0Status;
	g_tAdc0Handle.eInstance             = ADC_INSTANCE_0;
	ADC_InitStructure(&tAdc0InitCfg);	//初始化配置
	tAdc0InitCfg.eSequenceMode = ADC_SEQMODE_SINGLE;//ADC模式
	tAdc0InitCfg.aSampleTimes[0] = 16;//采样时间
	tAdc0InitCfg.eAlign = ADC_ALIGN_RIGHT;//对齐格式
	tAdc0InitCfg.u3AdcFuncClk = PCC_GetPccFunctionClock(PCC_CLK_ADC0);//外设时钟频率
	tAdc0InitCfg.eClockDivider = ADC_CLOCK_DIV_1;//时钟分频
	tAdc0InitCfg.pAdcResultBuffer = Adc0Buffer;//Buffer
	tAdc0InitCfg.bConversionCompleteIntEn = true;//开启转换完成中断
	tAdc0InitCfg.pConvCompleteCallback = Bsp_Adc0_ConversionCompleteCallback;//转换完成回调函数
	tAdc0InitCfg.bOverRunIntEn = false;//关闭溢出中断
	tAdc0InitCfg.bAnalogCmpIntEn = false;//关闭模拟对比中断
	ADC_Init(&g_tAdc0Handle,&tAdc0InitCfg);	//设置初始化
	ADC_InitChannel(&g_tAdc0Handle, Adc0Channels, ADC0_EN_CHANNELS_NUM);	//通道设置初始化
	Adc0Status = ADC_Enable(&g_tAdc0Handle);	//使能ADC
}

回调函数

static void Bsp_Adc0_ConversionCompleteCallback(ADC_HandleType *pHandle, const uint32_t *const pResult)
{
	ADC_Start(&g_tAdc0Handle);
}

可实现持续扫描并转换

Single+DMA传输

时钟初始化

DMA_MUX时钟配置 {PCC_CLK_DMA_MUX, true, PCC_CLKGATE_SRC_OFF, PCC_CLK_DIV_BY1} SMISC时钟配置

static void Bsp_SMISC_SetSysCgc(void)
{
    SMISC_SysCgcType tSmiscSysCgc = {0};
    tSmiscSysCgc.bEnableIsm = false;
    tSmiscSysCgc.bEnableSec = false;
    tSmiscSysCgc.bEnableIntm = false;
    tSmiscSysCgc.bEnableEim = false;
    tSmiscSysCgc.bEnableErm = false;
    tSmiscSysCgc.bEnableDma = true;
    tSmiscSysCgc.bEnableMap = false;
    SMISC_SetClockGate(&tSmiscSysCgc);
}

DMA初始化

DMA_HandleType g_tDmaHandle;
DMA_InstanceHandleType g_tDmaInstanceHandle;

DMA_InitType DmaInitCfg = {
	.eArbitrationAlgorithm = DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY,
	.bHaltOnError = false
};

void Bsp_DMA_Init(void)
{
	DMA_Init(&g_tDmaInstanceHandle,&DmaInitCfg);
	g_tDmaHandle.tSettings.pInstance = &g_tDmaInstanceHandle;
}

void Bsp_DMA_Start(void)
{
    DMA_StartChannel(&g_tDmaHandle);
}

在ADC中的初始化

void Bsp_ADC_DMA_Init(void)
{
	ADC_InitType tAdc0InitCfg;
	ADC_StatusType Adc0Status;
	g_tAdc0Handle.eInstance             = ADC_INSTANCE_0;
	ADC_InitStructure(&tAdc0InitCfg);	//初始化配置
	tAdc0InitCfg.eSequenceMode = ADC_SEQMODE_SINGLE;//ADC模式
	tAdc0InitCfg.aSampleTimes[0] = 16;//采样时间
	tAdc0InitCfg.eAlign = ADC_ALIGN_RIGHT;//对齐格式
	tAdc0InitCfg.u3AdcFuncClk = PCC_GetPccFunctionClock(PCC_CLK_ADC0);//外设时钟频率
	tAdc0InitCfg.eClockDivider = ADC_CLOCK_DIV_1;//时钟分频
	tAdc0InitCfg.pAdcResultBuffer = Adc0Buffer;//Buffer
	tAdc0InitCfg.bConversionCompleteIntEn = false;//关断转换完成中断
	tAdc0InitCfg.pConvCompleteCallback = NULL;//转换完成回调函数
	tAdc0InitCfg.bOverRunIntEn = false;//关闭溢出中断
	tAdc0InitCfg.bAnalogCmpIntEn = false;//关闭模拟对比中断

	ADC_Init(&g_tAdc0Handle,&tAdc0InitCfg);	//设置初始化
	ADC_InitChannel(&g_tAdc0Handle, Adc0Channels, ADC0_EN_CHANNELS_NUM);	//通道设置初始化

	ADC_InitDmaChannel(&g_tDmaHandle,&g_tAdc0Handle,&Adc0_DmaCfg);//DMA传输初始化

	Adc0Status = ADC_Enable(&g_tAdc0Handle);	//使能ADC
}

大部分的初始化内容被封装在 void ADC_InitDmaChannel(DMA_HandleType *pDmaHandle, ADC_HandleType *pAdcHandle, const ADC_DmaType *const pAdcDmaCfg)中,其内容为

        ADC_Type *const pAdc = s_apAdcBase[pAdcHandle->eInstance];

        if (pAdcDmaCfg->bDmaEnable == true)
        {
            (pAdcHandle->tSettings).pAdcResultBuffer = pAdcDmaCfg->pResultBuffer;
            (pAdcHandle->tSettings).pConvCompleteCallback = pAdcDmaCfg->pConvCompleteCallback;

            DMA_ChannelCfgType tDmaCfg;
            pDmaHandle->tSettings.u8Channel = pAdcDmaCfg->u8DmaChannel;
            if (ADC_HWA_GetSequenceMode(pAdc) == ADC_SEQMODE_DISCONTINUOUS_1)
            {
                tDmaCfg.pSrcBuffer = &pAdc->RESULT[ADC_DISCONTINUOUS_1_SC_START_INDEX];
                tDmaCfg.pDestBuffer = pAdcDmaCfg->pResultBuffer;
                tDmaCfg.u32BlockSize = 4U;
                tDmaCfg.u16BlockCount = (pAdcHandle->tSettings).u8ChnCnt;
                tDmaCfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE;
            }
            else
            {
                tDmaCfg.pSrcBuffer = &pAdc->FIFO_DATA;
                tDmaCfg.pDestBuffer = pAdcDmaCfg->pResultBuffer;
                tDmaCfg.u32BlockSize = 4U * (pAdcHandle->tSettings).u8ChnCnt;
                tDmaCfg.u16BlockCount = 1U;
                tDmaCfg.eSrcIncMode = DMA_INCREMENT_DISABLE;
            }
            tDmaCfg.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
            tDmaCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B;
            tDmaCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B;
            tDmaCfg.u8ChannelPriority = pAdcDmaCfg->u8ChannelPriority;
            tDmaCfg.bSrcBlockOffsetEn = false;
            tDmaCfg.bDestBlockOffsetEn = false;
            tDmaCfg.s32BlockOffset = 0;
            tDmaCfg.bSrcAddrLoopbackEn = true;
            tDmaCfg.bDestAddrLoopbackEn = true;
            tDmaCfg.bAutoStop = false;
            tDmaCfg.bSrcCircularBufferEn = false;
            tDmaCfg.u32SrcCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B;
            tDmaCfg.bDestCircularBufferEn = false;
            tDmaCfg.u32DestCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B;
            if (pAdcHandle->eInstance == ADC_INSTANCE_0)
            {
                tDmaCfg.eTriggerSrc = DMA_REQ_ADC0;
            }
            else if (pAdcHandle->eInstance == ADC_INSTANCE_1)
            {
                tDmaCfg.eTriggerSrc = DMA_REQ_ADC1;
            }
            else
            {}

            tDmaCfg.bTransferCompleteIntEn = pAdcDmaCfg->bDmaIntEnable;
            tDmaCfg.bTransferErrorIntEn = false;
            tDmaCfg.pTransferCompleteNotify = ADCn_DMAHandler;
            tDmaCfg.pTransferErrorNotify = NULL;
            tDmaCfg.completedata       = pAdcHandle;

            ADC_HWA_SetDMAEnableFlag(pAdc, true);

            DMA_DeinitChannel(pDmaHandle);
            DMA_InitChannel(pDmaHandle, &tDmaCfg);
        }
        else
        {
            ADC_HWA_SetDMAEnableFlag(pAdc, false);
        }

其主要逻辑分析 1、将ADC的ResultBuffer地址映射到DMA配置的地址,将ADC的回调函数地址映射到DMA配置的回调函数地址

 (pAdcHandle->tSettings).pAdcResultBuffer = pAdcDmaCfg->pResultBuffer;
 (pAdcHandle->tSettings).pConvCompleteCallback = pAdcDmaCfg->pConvCompleteCallback;

2、DMA读取FIFO

 tDmaCfg.pSrcBuffer = &pAdc->FIFO_DATA;//源地址是ADC的FIFO数据寄存器
 tDmaCfg.pDestBuffer = pAdcDmaCfg->pResultBuffer;//目标地址是DMA配置的目标地址
 tDmaCfg.u32BlockSize = 4U * (pAdcHandle->tSettings).u8ChnCnt;//以字节为单位,一次4个字节,即32bit
 tDmaCfg.u16BlockCount = 1U;//一次传输
 tDmaCfg.eSrcIncMode = DMA_INCREMENT_DISABLE;//由于数据来源于FIFO,不做递增

3、配置项

tDmaCfg.eDestIncMode = DMA_INCREMENT_DATA_SIZE;//目标地址递增,在配置多个缓冲buffer时有用,目前仅一个buffer没办法看出作用
tDmaCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B;//源数据大小为4b
tDmaCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B;//目标数据大小为4b
tDmaCfg.u8ChannelPriority = pAdcDmaCfg->u8ChannelPriority;//优先级
tDmaCfg.bSrcBlockOffsetEn = false;//源block不偏移,目前使用的是单block
tDmaCfg.bDestBlockOffsetEn = false;//目标block不偏移,目前使用的是单block
tDmaCfg.s32BlockOffset = 0;//偏移量为0
tDmaCfg.bSrcAddrLoopbackEn = true;//源地址回绕打开,传输完成后,地址会回到初始值
tDmaCfg.bDestAddrLoopbackEn = true;//目标地址回绕打开,传输完成后,地址会回到初始值
tDmaCfg.bAutoStop = false;//DMA 传输不会在完成一次 block 后自动关闭
/* 环形缓冲区不启用 */
tDmaCfg.bSrcCircularBufferEn = false;
tDmaCfg.u32SrcCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B;
tDmaCfg.bDestCircularBufferEn = false;
tDmaCfg.u32DestCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B;

4、DMA触发源

if (pAdcHandle->eInstance == ADC_INSTANCE_0)
{
   tDmaCfg.eTriggerSrc = DMA_REQ_ADC0;
}
 else if (pAdcHandle->eInstance == ADC_INSTANCE_1)
{
   tDmaCfg.eTriggerSrc = DMA_REQ_ADC1;
}
 else
{}

5、中断配置

tDmaCfg.bTransferCompleteIntEn = pAdcDmaCfg->bDmaIntEnable;//开启传输完成中断
tDmaCfg.bTransferErrorIntEn = false;//关闭错误中断
tDmaCfg.pTransferCompleteNotify = ADCn_DMAHandler;//指定回调函数
tDmaCfg.pTransferErrorNotify = NULL;
tDmaCfg.completedata       = pAdcHandle;//实例传输

6、使能ADC的DMAEN寄存器 ADC_HWA_SetDMAEnableFlag(pAdc, true) 7、DMA通道初始化

DMA_DeinitChannel(pDmaHandle);
DMA_InitChannel(pDmaHandle, &tDmaCfg);

Continuous+DMA传输

时钟配置不变 初始化配置中 tAdc0InitCfg.eSequenceMode = ADC_SEQMODE_CONTINUOUS

BTB Discontinuous

概要

非连续ADC采样在配合PTIMER(Programmable Timer)使用时,采用其Back-to-Back特性,在PTIMER的寄存器描述中(PTIMER_CTRL_CHn (Channel n Control Register)) image 由RM中对于Discontinuous Mode 1的描述:In this mode, hardware trigger events with pre-triggers are required to start each conversion defined in the sequence. And conversion will stop when ADSTP is set.The ADC can work with the PTIMER pre-trigger back-to-back (BTB) operation enabled. With the PTIMER BTB operation, the ADC can sample the specified channel with a configurable delay time. For example, the ADC will select the channel specified in ADC_SCn.CHS, where n is determined by PTIMER pre-trigger. SEQ_LEN is invalid for this mode. In this mode, the ADC conversion results are stored in the ADC_RESULTn register instead of the FIFO. 结合PTIMER中对于BTB的描述:Optional Back-to-Back (BTB) Mode operation, which enables the ADC conversions complete to trigger the next PTIMER channel

Discontinuous Mode 1要求每一次转换必须有一个外部触发,而PTIMERBTB其设定是pre-trigger之间由 前一次采样完成事件触发下一次PTIMER预触发信号,使用两者结合便能生成自动转换的链式ADC采样转换

时钟

image 时钟来自于CoreClock,一般为150MHz,Freq = Core_Freq / (PTIMER_ClockPreDividerType * PTIMER_ClockPreDivMultiplyFactorType) 在SDK中,其配置为

tPtimer0InitCfg.eClkPreDiv = PTIMER_PRE_DIVIDE_BY_128;
tPtimer0InitCfg.eClkPreMultFactor = PTIMER_PRE_DIVIDER_MULTIPLY_BY_10;
PTIMER_SetPeriod(&g_tPtimerHandle, 585U);

则Freq=150000000/(12810)=117187.5Hz,Period=1/117187.5,T=585(1/117187.5)=0.004992≈5ms

通道配置

SDK示例中,Channel0作为ADC采样的入口,没有配置成BTB模式,且设置了延时,而Channel1-3均设置成BTB模式,可以链式触发 第一个Channel配置成有延迟,在计数达到117后才产生触发信号,其预触发功能开启,且触发产生输出信号,作为不需要前端ADC完成信号来触发的应用,不开启BTB,在技术完成后会输出一个触发信号;后面三个Channel,被配置成无延迟、触发功能开启、不产生触发输出信号、开启BTB应用,在前一个完成后,链式开启下一个

static const PTIMER_ChannelCfgType s_aPtimer0ChannelCfg[PTIMER0_CHN_NUM_EN] =
{
    {
        .u16DelayCnt                 = 117U,  /* Only the first channel is triggered by delay */
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = true,
        .bPreTriggerBackToBackEnable = false,
    },
    {
        .u16DelayCnt                 = 0U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = false,
        .bPreTriggerBackToBackEnable = true,
    },
    {
        .u16DelayCnt                 = 0U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = false,
        .bPreTriggerBackToBackEnable = true,
    },
    {
        .u16DelayCnt                 = 0U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = false,
        .bPreTriggerBackToBackEnable = true,
    }
}

PTIMER初始化全过程,后续在ADC初始化时调用PTIMER Init函数

PTIMER_HandleType   g_tPtimerHandle;

static const PTIMER_ChannelCfgType sc_PtimerChannelCfg[ADC0_EN_CHANNELS_NUM]={
	{
		.bPreTriggerEnable 			= true,
		.bPreTriggerOutputEnable 	= true,
		.bPreTriggerBackToBackEnable= false,
		.u16DelayCnt				= 100U,
	},

	{
		.bPreTriggerEnable 			= true,
		.bPreTriggerOutputEnable 	= false,
		.bPreTriggerBackToBackEnable= true,
		.u16DelayCnt				= 0U,
	},

	{
		.bPreTriggerEnable 			= true,
		.bPreTriggerOutputEnable 	= false,
		.bPreTriggerBackToBackEnable= true,
		.u16DelayCnt				= 0U,
	},

};

void Bsp_PTIMER_Init(void)
{
	PTIMER_InitType tPtimer0InitCfg;

	g_tPtimerHandle.eInstance = PTIMER_INSTANCE_0;
	PTIMER_InitStructure(&tPtimer0InitCfg);
    tPtimer0InitCfg.eClkPreDiv = PTIMER_PRE_DIVIDE_BY_128;
    tPtimer0InitCfg.eClkPreMultFactor = PTIMER_PRE_DIVIDER_MULTIPLY_BY_10;
    PTIMER_Init(&g_tPtimerHandle, &tPtimer0InitCfg);
    PTIMER_Enable(&g_tPtimerHandle);
    PTIMER_SetPeriod(&g_tPtimerHandle, 585U);
    PTIMER_InitChannel(&g_tPtimerHandle, sc_PtimerChannelCfg, ADC0_EN_CHANNELS_NUM);
    PTIMER_LoadValue(&g_tPtimerHandle);
}

BTB ADC初始化

void Bsp_ADC_BTB_Init(void)
{
	ADC_InitType tAdc0InitCfg;
	ADC_StatusType Adc0Status;
	g_tAdc0Handle.eInstance             = ADC_INSTANCE_0;
	ADC_InitStructure(&tAdc0InitCfg);	//初始化配置
	tAdc0InitCfg.eAlign = ADC_ALIGN_RIGHT;//对齐格式
	tAdc0InitCfg.u3AdcFuncClk = PCC_GetPccFunctionClock(PCC_CLK_ADC0);//外设时钟频率
	tAdc0InitCfg.eClockDivider = ADC_CLOCK_DIV_1;//时钟分频

	tAdc0InitCfg.eSequenceMode = ADC_SEQMODE_DISCONTINUOUS_1;//不连续模式1
	tAdc0InitCfg.eTriggerMode = ADC_TRIGMODE_RISING_EDGE;
	tAdc0InitCfg.aSampleTimes[0] = 4;//采样时间
	tAdc0InitCfg.aSampleTimes[1] = 16;//采样时间
	tAdc0InitCfg.pAdcResultBuffer = Adc0Buffer;//Buffer

	tAdc0InitCfg.bConversionCompleteIntEn = true;//开启转换完成中断
	tAdc0InitCfg.pConvCompleteCallback = Bsp_Adc0_BTB_CC_Callback;//转换完成回调函数
	tAdc0InitCfg.bOverRunIntEn = false;//关闭溢出中断
	tAdc0InitCfg.bAnalogCmpIntEn = false;//关闭模拟对比中断

	ADC_Init(&g_tAdc0Handle,&tAdc0InitCfg);	//设置初始化
	ADC_InitChannel(&g_tAdc0Handle, Adc0Channels, ADC0_EN_CHANNELS_NUM);	//通道设置初始化
	Adc0Status = ADC_Enable(&g_tAdc0Handle);	//使能ADC
	Bsp_PTIMER_Init();//初始化PTIMER
}

ADC开启时,调用PTIMER_GenerateSWTrigger产生开启信号

void Bsp_ADC_Start(void)
{
	ADC_Start(&g_tAdc0Handle);
	PTIMER_GenerateSWTrigger(&g_tPtimerHandle);
}

在回调函数(或轮询中)调用PTIMER_GenerateSWTrigger产生开启信号

static void Bsp_Adc0_BTB_CC_Callback(struct _ADC_HandleType *pHandle, const uint32_t *const pBuff)
{
	PTIMER_GenerateSWTrigger(&g_tPtimerHandle);
}

DMA+BTB

开启DMA中断及DMA回调

Discontinuous

对比BTB,改变PTIMER CHHANNEL配置为

static const PTIMER_ChannelCfgType s_aPtimer0ChannelCfg[PTIMER0_CHN_NUM_EN] =
{
    {
        .u16DelayCnt                  = 7500U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = true,
        .bPreTriggerBackToBackEnable = false,
    },
    {
        .u16DelayCnt                  = 15000U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = true,
        .bPreTriggerBackToBackEnable = false,
    },
    {
        .u16DelayCnt                  = 22500U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = true,
        .bPreTriggerBackToBackEnable = false,
    },
    {
        .u16DelayCnt                  = 30000U,
        .bPreTriggerEnable           = true,
        .bPreTriggerOutputEnable     = true,
        .bPreTriggerBackToBackEnable = false,
    }
};

不再是自动触发的链式结构,而是根据DelayCnt触发

ADC的触发

static const ADC_InitType  tAdc0InitCfg = {
	.pAdcResultBuffer 	= s_aAdc0ResultBuf,
	.eTriggerMode 		= ADC_TRIGMODE_SW,
	.eSequenceMode   	= ADC_SEQMODE_SINGLE,
	.eResolution		= ADC_RESOLUTION_12_BIT,
	.eVoltageRef		= ADC_REF_INTERNAL,
	.eClockDivider		= ADC_CLOCK_DIV_1,
	.aSampleTimes[0] 	= 4U,
	.aSampleTimes[1] 	= 10U,
	.aSampleTimes[2]	= 40U,
	.aSampleTimes[3] 	= 80U,
	.bConversionCompleteIntEn	= true,
	.pConvCompleteCallback		= ADC0_CompleteCallback,
};

void Bsp_ADC0_Init(void)
{
    g_tAdcHandle0.eInstance       	= ADC_INSTANCE_0;
    ADC_Init(&g_tAdcHandle0, &tAdc0InitCfg);
    for(int i = 0;i < ADC0_CHN_NUM_EN;i++)
    {
    	 ADC_InitChannel(&g_tAdcHandle0, s_ADC0_Channels, ADC0_CHN_NUM_EN);
    }
    ADC_Enable(&g_tAdcHandle0);
}

float Vadc;
void ADC0_CompleteCallback(struct _ADC_HandleType *pHandle, const uint32_t *const pBuff)
{
	(void) pHandle;
	(void) pBuff;
	Vadc = (float)s_aAdc0ResultBuf[0]/4096.0f*5.0f;
}

//使用FTU中断来开启ADC
void FTU2_OverflowCallback(FTU_HandleType *pHandle)
{
	(void) pHandle;
	printf_flag = 1;
    ADC_Start(&g_tAdcHandle0);
}

TRGSEL触发

使用FTU的重装载作为触发源:

FTU2->TRIGCONF = 1<<6;		// Reload Trigger Enable
FTU2->CONF = 1<<11;		// Reload Trigger on Reload Point

将触发源进行对应:

TRGSEL_SetTargetTriggerSource(TRGSEL_INSTANCE_0,TRGSEL0_TARGET_ADC0_TRG0,TRGSEL0_SRC_FTU2_RELOAD_TRG);

选择ADC的触发源和触发方式:

.eTriggerSel		= ADC_TRIGGER_SEL_TRGSEL,
.eTriggerMode 		= ADC_TRIGMODE_RISING_EDGE,

注意:在不使用discontinuous mode 1(SEQ_MOD=3)时,pre-triggers是不奏效的,不需要设置

#End