ADC - aman396271/Flagchip_Study GitHub Wiki
概要
该 ADC 是一款 12 位精度的逐次逼近 (SAR) 模数转换器。它拥有多达 38 个通道,可测量来自 32 个外部模拟源和 5 个内部模拟源的信号。各通道的 A/D 转换可以单次、连续或非续模式进行。结果数据存储在 FIFO 或结果寄存器中,格式可以是左对齐或右对齐。
默认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模式
Bit数
支持8、10、12bit ADC转换,位数越低,转化越快
AVG平均数
支持AVG(ADC Average Function),在AVG_EN=1使能AVG后,每4-32次(在AVG_LEN设置)做一次平均,结果输出到FIFO or ADC_RESULT
数据对齐
数据对齐,0:right-align,1:left-align,如下图所示
Overflow溢出
溢出后需软件写1
The OVR flag is cleared by software by writing 1 to it.
在ADC_CFG1的OVRMOD可以设置溢出后要保存的数据是旧数据还是新数据
DMA
中断源
低功耗特性
Single 单次扫描
初始化
时钟初始化
SDK中的时钟配置为
{PCC_CLK_ADC0, true, PCC_CLKGATE_SRC_FOSCDIV, PCC_CLK_DIV_BY1},时钟源为FOSC_DIVM
根据时钟树,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))
由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要求每一次转换必须有一个外部触发,而PTIMER的BTB其设定是pre-trigger之间由 前一次采样完成事件触发下一次PTIMER预触发信号,使用两者结合便能生成自动转换的链式ADC采样转换
时钟
时钟来自于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