工具配置
我这个K1芯片有两个ADC驱动,也就有两个components,点开之后每个components都有四个选项卡converter转换器、channel通道、compare比较器、average求平均。
配置引脚
配置之前,得先配置好引脚,哪个引脚用来采集ADC。
每个components会生成两个文件,譬如我这里的adConv0会生成一个adConv0.c和一个adConv0.h,adConv1会生成一个adConv1.c和一个adConv1.h。
配置时钟
每个转换器有自己的基础时钟,譬如我们这里配个8M的,到ADC里面会继续分频。
converter转换器
一个转换器生成一个adc_converter_config_t类型的结构体。
/*! adConv0 configuration structure */
const adc_converter_config_t adConv0_ConvConfig0 = {
.clockDivide = ADC_CLK_DIVIDE_4,
.sampleTime = 255U,
.resolution = ADC_RESOLUTION_12BIT,
.inputClock = ADC_CLK_ALT_1,
.trigger = ADC_TRIGGER_SOFTWARE,
.pretriggerSel = ADC_PRETRIGGER_SEL_PDB,
.triggerSel = ADC_TRIGGER_SEL_PDB,
.dmaEnable = false,
.voltageRef = ADC_VOLTAGEREF_VREF,
.continuousConvEnable = false,
.supplyMonitoringEnable = false,
};
分频可以选择1/2/4/8分频
/*!
* @brief Clock Divider selection
*
* Implements : adc_clk_divide_t_Class
*/
typedef enum
{
ADC_CLK_DIVIDE_1 = 0x00U, /*!< Input clock divided by 1. */
ADC_CLK_DIVIDE_2 = 0x01U, /*!< Input clock divided by 2. */
ADC_CLK_DIVIDE_4 = 0x02U, /*!< Input clock divided by 4. */
ADC_CLK_DIVIDE_8 = 0x03U /*!< Input clock divided by 8. */
} adc_clk_divide_t;
采样时间就是采样周期,有个计数器不断累加,一到达特定次数就进行一次采样,并且将次数清零,最小1最大255。
精度可以选择8/10/12位精度,精度越高,转换时间越长。
/*!
* @brief Conversion resolution selection
*
* Implements : adc_resolution_t_Class
*/
typedef enum
{
ADC_RESOLUTION_8BIT = 0x00U, /*!< 8-bit resolution mode */
ADC_RESOLUTION_12BIT = 0x01U, /*!< 12-bit resolution mode */
ADC_RESOLUTION_10BIT = 0x02U /*!< 10-bit resolution mode */
} adc_resolution_t;
输入时钟是在时钟树里面确定的,我这里只有一个可以选,其他的都只是个标签。
/*!
* @brief Input clock source selection
*
* Implements : adc_input_clock_t_Class
*/
typedef enum
{
ADC_CLK_ALT_1 = 0x00U, /*!< Input clock alternative 1. */
ADC_CLK_ALT_2 = 0x01U, /*!< Input clock alternative 2. */
ADC_CLK_ALT_3 = 0x02U, /*!< Input clock alternative 3. */
ADC_CLK_ALT_4 = 0x03U /*!< Input clock alternative 4. */
} adc_input_clock_t;
触发源就是选择软件触发还是硬件触发,硬件触发有电平、边沿,软件有定时器溢出、PWM计数器溢出、ADC采集完毕等等。
前触发选择,也叫预触发,还有触发选择,这两个默认就行。
/*!
* @brief Pretrigger types selectable from Trigger Latching and Arbitration Unit
*
* Implements : adc_pretrigger_sel_t_Class
*/
typedef enum
{
ADC_PRETRIGGER_SEL_PDB = 0x00U, /*!< PDB pretrigger selected. */
ADC_PRETRIGGER_SEL_TRGMUX = 0x01U, /*!< TRGMUX pretrigger selected. */
ADC_PRETRIGGER_SEL_SW = 0x02U /*!< Software pretrigger selected. */
} adc_pretrigger_sel_t;
/*!
* @brief Trigger source selectable from Trigger Latching and Arbitration Unit
*
* Implements : adc_trigger_sel_t_Class
*/
typedef enum
{
ADC_TRIGGER_SEL_PDB = 0x00U, /*!< PDB trigger selected. */
ADC_TRIGGER_SEL_TRGMUX = 0x01U /*!< TRGMUX trigger selected. */
} adc_trigger_sel_t;
参考电压可以选择MCU供电电压还是外部输入的参考电压,默认都是MCU供电电压,也就是第一个。
/*!
* @brief Voltage reference selection
*
* Implements : adc_voltage_reference_t_Class
*/
typedef enum
{
ADC_VOLTAGEREF_VREF = 0x00U, /*!< VrefH and VrefL as Voltage reference. */
ADC_VOLTAGEREF_VALT = 0x01U /*!< ValtH and ValtL as Voltage reference. */
} adc_voltage_reference_t;
Channel通道
每个ADC转换器都对应好几个通道,自己配置对应到哪个通道就行,每个通道都有自己的引脚。一般都设置为只读,不启动中断。
这里每一个通道就生成一个通道结构体
const adc_chan_config_t adConv0_ChnConfig0 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT2,
};
const adc_chan_config_t adConv0_ChnConfig1 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT6,
};
const adc_chan_config_t adConv0_ChnConfig2 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT8,
};
const adc_chan_config_t adConv0_ChnConfig3 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT9,
};
const adc_chan_config_t adConv0_ChnConfig4 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT12,
};
const adc_chan_config_t adConv0_ChnConfig5 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT13,
};
const adc_chan_config_t adConv0_ChnConfig6 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT14,
};
const adc_chan_config_t adConv0_ChnConfig7 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT15,
};
compare对比器
对比器很少用,因为一开就是一整个ADC所有通道都用上,也就是每个通道是或的关系,满足比较条件后,产生中断。具体细节可以看后面的接口使用。
生成代码
const adc_compare_config_t adConv0_HwCompConfig0 = {
.compareEnable = true,
.compareGreaterThanEnable = true,
.compareRangeFuncEnable = true,
.compVal1 = 10000U,
.compVal2 = 20000U,
};
average求平均
可以用来硬件滤波,可以
生成代码
const adc_average_config_t adConv0_HwAvgConfig0 = {
.hwAvgEnable = false,
.hwAverage = ADC_AVERAGE_4,
};
接口使用
ADC_DRV_InitConverterStruct
初始化转换器
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_InitConverterStruct
* Description : This function initializes the members of the adc_converter_config_t
* structure to default values (Reference Manual resets). This function should be called
* on a structure before using it to configure the converter (ADC_DRV_ConfigConverter), otherwise all members
* must be written (initialized) by the caller. This function insures that all members are written
* with safe values, so the user can modify only the desired members.
*
* Implements : ADC_DRV_InitConverterStruct_Activity
*END**************************************************************************/
void ADC_DRV_InitConverterStruct(adc_converter_config_t * const config)
{
DEV_ASSERT(config != NULL);
config->clockDivide = ADC_CLK_DIVIDE_1;
config->sampleTime = (uint8_t)ADC_DEFAULT_SAMPLE_TIME;
config->resolution = ADC_RESOLUTION_8BIT;
config->inputClock = ADC_CLK_ALT_1;
config->trigger = ADC_TRIGGER_SOFTWARE;
config->pretriggerSel = ADC_PRETRIGGER_SEL_PDB;
config->triggerSel = ADC_TRIGGER_SEL_PDB;
config->dmaEnable = false;
config->voltageRef = ADC_VOLTAGEREF_VREF;
config->continuousConvEnable = false;
config->supplyMonitoringEnable = false;
}
ADC_DRV_ConfigConverter
将转换器配置到ADC
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ConfigConverter
* Description : This function configures the ADC converter with the options
* provided in the configuration structure.
*
* Implements : ADC_DRV_ConfigConverter_Activity
*END**************************************************************************/
void ADC_DRV_ConfigConverter(const uint32_t instance,
const adc_converter_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
/* Some alternative clocks can be unavailable depending on the device */
DEV_ASSERT(config->inputClock <= NUMBER_OF_ALT_CLOCKS);
ADC_Type * const base = s_adcBase[instance];
clock_names_t adc_clocks[ADC_INSTANCE_COUNT] = ADC_CLOCKS;
uint32_t adc_freq = 0u;
status_t clk_status = CLOCK_SYS_GetFreq(adc_clocks[instance], &adc_freq);
DEV_ASSERT(clk_status == STATUS_SUCCESS);
(void) clk_status;
adc_freq = adc_freq / (uint32_t)(1UL << ((uint32_t)(config->clockDivide)));
DEV_ASSERT((adc_freq >= ADC_CLOCK_FREQ_MIN_RUNTIME) && (adc_freq <= ADC_CLOCK_FREQ_MAX_RUNTIME));
ADC_SetClockDivide(base, config->clockDivide);
ADC_SetSampleTime(base, config->sampleTime);
ADC_SetResolution(base, config->resolution);
ADC_SetInputClock(base, config->inputClock);
ADC_SetTriggerMode(base, config->trigger);
ADC_SetPretriggerSelect(instance, config->pretriggerSel);
ADC_SetTriggerSelect(instance, config->triggerSel);
ADC_SetDMAEnableFlag(base, config->dmaEnable);
ADC_SetVoltageReference(base, config->voltageRef);
ADC_SetContinuousConvFlag(base, config->continuousConvEnable);
/* Supply monitoring is only available for ADC 0. */
DEV_ASSERT((config->supplyMonitoringEnable == false) || (instance == 0u));
if(instance == 0u)
{
SIM_Type * const simBase = SIM;
ADC_SetSupplyMonitoringEnableFlag(simBase, config->supplyMonitoringEnable);
}
}
ADC_DRV_GetConverterConfig
获取转换器配置
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetConverterConfig
* Description : This functions returns the current converter configuration in
* the form of a configuration structure.
*
* Implements : ADC_DRV_GetConverterConfig_Activity
*END**************************************************************************/
void ADC_DRV_GetConverterConfig(const uint32_t instance,
adc_converter_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
const ADC_Type * const base = s_adcBase[instance];
config->clockDivide = ADC_GetClockDivide(base);
config->sampleTime = ADC_GetSampleTime(base);
config->resolution = ADC_GetResolution(base);
config->inputClock = ADC_GetInputClock(base);
config->trigger = ADC_GetTriggerMode(base);
config->triggerSel = ADC_GetTriggerSelect(instance);
config->pretriggerSel = ADC_GetPretriggerSelect(instance);
config->dmaEnable = ADC_GetDMAEnableFlag(base);
config->voltageRef = ADC_GetVoltageReference(base);
config->continuousConvEnable = ADC_GetContinuousConvFlag(base);
/* Supply monitoring is only available for ADC 0. */
if(instance == 0u)
{
const SIM_Type * const simBase = SIM;
config->supplyMonitoringEnable = ((simBase->CHIPCTL & SIM_CHIPCTL_ADC_SUPPLYEN_MASK) != 0u) ? true : false;
}
else
{
config->supplyMonitoringEnable = false;
}
}
ADC_DRV_Reset
将整个ADC重启和恢复成默认配置,里面会重置所有ADC寄存器。
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_Reset
* Description : This function writes all the internal ADC registers with
* their Reference Manual reset values.
*
* Implements : ADC_DRV_Reset_Activity
*END**************************************************************************/
void ADC_DRV_Reset(const uint32_t instance)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
ADC_Type * const baseAddr = s_adcBase[instance];
uint8_t idx = 0U;
for(idx = 0U; idx < ADC_SC1_COUNT; idx++)
{
baseAddr->SC1[idx] = ADC_SC1_ADCH(ADC_INPUTCHAN_DISABLED) | ADC_SC1_AIEN(0x00U);
}
baseAddr->CFG1 = ADC_CFG1_ADICLK(ADC_CLK_ALT_1) | ADC_CFG1_MODE(ADC_RESOLUTION_8BIT) | ADC_CFG1_ADIV(ADC_CLK_DIVIDE_1);
baseAddr->CFG2 = ADC_CFG2_SMPLTS(ADC_DEFAULT_SAMPLE_TIME);
for(idx = 0U; idx < ADC_CV_COUNT; idx++)
{
baseAddr->CV[idx] = ADC_CV_CV(0U);
}
baseAddr->SC2 = ADC_SC2_REFSEL(ADC_VOLTAGEREF_VREF) | ADC_SC2_DMAEN(0x00U) | ADC_SC2_ACREN(0x00U) | ADC_SC2_ACFGT(0x00U) | ADC_SC2_ACFE(0x00U) |
ADC_SC2_ADTRG(0x00U);
baseAddr->SC3 = ADC_SC3_AVGS(ADC_AVERAGE_4) | ADC_SC3_AVGE(0x00U) | ADC_SC3_ADCO(0x00U) | ADC_SC3_CAL(0x00U);
baseAddr->USR_OFS = ADC_USR_OFS_USR_OFS(0U);
baseAddr->UG = ADC_UG_UG(ADC_DEFAULT_USER_GAIN);
#if FEATURE_ADC_HAS_EXTRA_NUM_REGS
for(idx = 0U; idx < ADC_aSC1_COUNT; idx++)
{
baseAddr->aSC1[idx] = ADC_aSC1_ADCH(ADC_INPUTCHAN_DISABLED) | ADC_aSC1_AIEN(0x00U);
}
#endif /* FEATURE_ADC_HAS_EXTRA_NUM_REGS */
ADC_SetPretriggerSelect(instance, ADC_PRETRIGGER_SEL_PDB);
ADC_SetTriggerSelect(instance, ADC_TRIGGER_SEL_PDB);
ADC_DRV_SetSwPretrigger(instance, ADC_SW_PRETRIGGER_DISABLED);
/* Reset ADC Supply Monitoring - available only for ADC 0 */
if(instance == 0u)
{
SIM_Type * const simBase = SIM;
ADC_SetSupplyMonitoringEnableFlag(simBase, false);
simBase->CHIPCTL &= ~SIM_CHIPCTL_ADC_SUPPLY_MASK;
}
}
ADC_DRV_InitHwCompareStruct
初始化对比器
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_InitHwCompareStruct
* Description : This function initializes the Hardware Compare configuration
* structure to default values (Reference Manual resets). This function should be
* called before configuring the Hardware Compare feature (ADC_DRV_ConfigHwCompare),
* otherwise all members must be written by the caller. This function insures that all
* members are written with safe values, so the user can modify the desired members.
*
* Implements : ADC_DRV_InitHwCompareStruct_Activity
*END**************************************************************************/
void ADC_DRV_InitHwCompareStruct(adc_compare_config_t * const config)
{
DEV_ASSERT(config != NULL);
config->compareEnable = false;
config->compareGreaterThanEnable = false;
config->compareRangeFuncEnable = false;
config->compVal1 = 0U;
config->compVal2 = 0U;
}
ADC_DRV_ConfigHwCompare
将对比器配置到ADC里面
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ConfigHwCompare
* Description : This functions sets the configuration for the Hardware
* Compare feature using the configuration structure.
*
* Implements : ADC_DRV_ConfigHwCompare_Activity
*END**************************************************************************/
void ADC_DRV_ConfigHwCompare(const uint32_t instance,
const adc_compare_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
ADC_Type * const base = s_adcBase[instance];
ADC_SetHwCompareEnableFlag(base, config->compareEnable);
ADC_SetHwCompareGtEnableFlag(base, config->compareGreaterThanEnable);
ADC_SetHwCompareRangeEnableFlag(base, config->compareRangeFuncEnable);
ADC_SetHwCompareComp1Value(base, config->compVal1);
ADC_SetHwCompareComp2Value(base, config->compVal2);
}
ADC_DRV_GetHwCompareConfig
获取比较器配置
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetHwCompareConfig
* Description : This function returns the configuration for the Hardware
* Compare feature.
*
* Implements : ADC_DRV_GetHwCompareConfig_Activity
*END**************************************************************************/
void ADC_DRV_GetHwCompareConfig(const uint32_t instance,
adc_compare_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
const ADC_Type * const base = s_adcBase[instance];
config->compareEnable = ADC_GetHwCompareEnableFlag(base);
config->compareGreaterThanEnable = ADC_GetHwCompareGtEnableFlag(base);
config->compareRangeFuncEnable = ADC_GetHwCompareRangeEnableFlag(base);
config->compVal1 = ADC_GetHwCompareComp1Value(base);
config->compVal2 = ADC_GetHwCompareComp2Value(base);
}
ADC_DRV_InitHwAverageStruct
求平均器结构体初始化,这个感觉没啥用。
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_InitHwAverageStruct
* Description : This function initializes the Hardware Average configuration
* structure to default values (Reference Manual resets). This function should be
* called before configuring the Hardware Average feature (ADC_DRV_ConfigHwAverage),
* otherwise all members must be written by the caller. This function insures that all
* members are written with safe values, so the user can modify the desired members.
*
* Implements : ADC_DRV_InitHwAverageStruct_Activity
*END**************************************************************************/
void ADC_DRV_InitHwAverageStruct(adc_average_config_t * const config)
{
DEV_ASSERT(config != NULL);
config->hwAvgEnable = false;
config->hwAverage = ADC_AVERAGE_4;
}
ADC_DRV_ConfigHwAverage
求平均器配置进ADC里面
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ConfigHwAverage
* Description : This function sets the configuration for the Hardware
* Average feature.
*
* Implements : ADC_DRV_ConfigHwAverage_Activity
*END**************************************************************************/
void ADC_DRV_ConfigHwAverage(const uint32_t instance,
const adc_average_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
ADC_Type * const base = s_adcBase[instance];
ADC_SetHwAverageEnableFlag(base, config->hwAvgEnable);
ADC_SetHwAverageMode(base, config->hwAverage);
}
ADC_DRV_GetHwAverageConfig
获取求平均器的配置
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetHwAverageConfig
* Description : This function returns the configuration for the Hardware
* Average feature.
*
* Implements : ADC_DRV_GetHwAverageConfig_Activity
*END**************************************************************************/
void ADC_DRV_GetHwAverageConfig(const uint32_t instance,
adc_average_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
const ADC_Type * const base = s_adcBase[instance];
config->hwAvgEnable = ADC_GetHwAverageEnableFlag(base);
config->hwAverage = ADC_GetHwAverageMode(base);
}
ADC_DRV_InitChanStruct
初始化通道结构体,这个也没啥用。
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_InitChanStruct
* Description : This function initializes the control channel
* configuration structure to default values (Reference Manual resets). This function should
* be called on a structure before using it to configure a channel (ADC_DRV_ConfigChan), otherwise
* all members must be written by the caller. This function insures that all members are written
* with safe values, so the user can modify only the desired members.
*
* Implements : ADC_DRV_InitChanStruct_Activity
*END**************************************************************************/
void ADC_DRV_InitChanStruct(adc_chan_config_t * const config)
{
DEV_ASSERT(config != NULL);
config->interruptEnable = false;
config->channel = ADC_INPUTCHAN_DISABLED;
}
ADC_DRV_ConfigChan
转换接口,这个一定会用上,每次转换都得用它。
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ConfigChan
* Description : This function sets a control channel configuration.
*
* When Software Trigger mode is enabled, configuring control channel index 0,
* implicitly triggers a new conversion on the selected ADC input channel.
* Therefore, ADC_DRV_ConfigChan can be used for sw-triggering conversions.
*
* Configuring any control channel while it is actively controlling a conversion
* (sw or hw triggered) will implicitly abort the on-going conversion.
*
* Implements : ADC_DRV_ConfigChan_Activity
*END**************************************************************************/
void ADC_DRV_ConfigChan(const uint32_t instance,
const uint8_t chanIndex,
const adc_chan_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(chanIndex < ADC_CTRL_CHANS_COUNT);
DEV_ASSERT(config != NULL);
ADC_Type * const base = s_adcBase[instance];
/* ADC_INPUTCHAN_SUPPLY_ can only be used with ADC 0,
* If used, the feature must be enabled separately via supplyMonitoringEnable flag in adc_converter_config_t. */
DEV_ASSERT((instance == 0u) || ((uint32_t)config->channel < (uint32_t)ADC_INPUTCHAN_SUPPLY_VDD) || \
((uint32_t)config->channel > (uint32_t)ADC_INPUTCHAN_SUPPLY_VDD_LV));
ADC_SetInputChannel(base, chanIndex, config->channel, config->interruptEnable);
}
ADC_DRV_GetChanConfig
获取通道配置,也没啥用
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetChanConfig
* Description : This function returns the current configuration for a control
* channel.
*
* Implements : ADC_DRV_GetChanConfig_Activity
*END**************************************************************************/
void ADC_DRV_GetChanConfig(const uint32_t instance,
const uint8_t chanIndex,
adc_chan_config_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(chanIndex < ADC_CTRL_CHANS_COUNT);
DEV_ASSERT(config != NULL);
const ADC_Type * const base = s_adcBase[instance];
config->interruptEnable = ADC_GetChanInterruptEnableFlag(base, chanIndex);
config->channel = ADC_GetInputChannel(base, chanIndex);
}
ADC_DRV_SetSwPretrigger
设置转换器前触发
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_SetSwPretrigger
* Description : This function sets the software pretrigger - affects only first 4 control channels.
*
* Implements : ADC_DRV_SetSwPretrigger_Activity
*END**************************************************************************/
void ADC_DRV_SetSwPretrigger(const uint32_t instance,
const adc_sw_pretrigger_t swPretrigger)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
SIM_Type * const simBase = SIM;
uint32_t intermValue = 0U;
uint32_t mask[ADC_INSTANCE_COUNT] = {0U};
#if (ADC_INSTANCE_COUNT == 1U)
mask[0] = SIM_ADCOPT_ADC0SWPRETRG_MASK;
#elif (ADC_INSTANCE_COUNT == 2U)
mask[0] = SIM_ADCOPT_ADC0SWPRETRG_MASK;
mask[1] = SIM_ADCOPT_ADC1SWPRETRG_MASK;
#else
#error "Maximum supported value for ADC_INSTANCE_COUNT is 2."
#endif
/* If SW Pretrigger Select is not enabled, the SW pretriggers will be ignored by ADC. */
DEV_ASSERT((ADC_GetPretriggerSelect(instance) == ADC_PRETRIGGER_SEL_SW) || \
(swPretrigger == ADC_SW_PRETRIGGER_DISABLED));
intermValue = simBase->ADCOPT & (~ mask[instance]);
switch(instance)
{
case 0:
intermValue |= SIM_ADCOPT_ADC0SWPRETRG(swPretrigger);
break;
case 1:
intermValue |= SIM_ADCOPT_ADC1SWPRETRG(swPretrigger);
break;
default:
DEV_ASSERT(false);
break;
}
simBase->ADCOPT = intermValue;
}
ADC_DRV_WaitConvDone
等待转换完成,这个也必定用上。
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_WaitConvDone
* Description : This functions waits for a conversion to complete by
* continuously polling the Conversion Active Flag.
*
* Implements : ADC_DRV_WaitConvDone_Activity
*END**************************************************************************/
void ADC_DRV_WaitConvDone(const uint32_t instance)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
const ADC_Type * const base = s_adcBase[instance];
while (ADC_GetConvActiveFlag(base) == true)
{
/* Wait for conversion to finish */
}
}
ADC_DRV_GetConvCompleteFlag
获取转换成功的标志位
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetConvCompleteFlag
* Description : This function returns the state of the Conversion Complete
* flag for a control channel. This flag is set when a conversion is complete
* or the condition generated by the Hardware Compare feature is evaluated to true.
*
* Implements : ADC_DRV_GetConvCompleteFlag_Activity
*END**************************************************************************/
bool ADC_DRV_GetConvCompleteFlag(const uint32_t instance,
const uint8_t chanIndex)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(chanIndex < ADC_CTRL_CHANS_COUNT);
const ADC_Type * const base = s_adcBase[instance];
#if FEATURE_ADC_HAS_EXTRA_NUM_REGS
uint32_t tmp = base->aSC1[chanIndex];
tmp = (tmp & ADC_aSC1_COCO_MASK) >> ADC_aSC1_COCO_SHIFT;
#else
uint32_t tmp = base->SC1[chanIndex];
tmp = (tmp & ADC_SC1_COCO_MASK) >> ADC_SC1_COCO_SHIFT;
#endif /* FEATURE_ADC_HAS_EXTRA_NUM_REGS */
return (tmp != 0u) ? true : false;
}
ADC_DRV_GetChanResult
获取转换成功结果
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetChanResult
* Description : This function returns the conversion result from a
* control channel.
*
* Implements : ADC_DRV_GetChanResult_Activity
*END**************************************************************************/
void ADC_DRV_GetChanResult(const uint32_t instance,
const uint8_t chanIndex,
uint16_t * const result)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(result != NULL);
const ADC_Type * const base = s_adcBase[instance];
#if FEATURE_ADC_HAS_EXTRA_NUM_REGS
DEV_ASSERT(chanIndex < ADC_aR_COUNT);
uint32_t tmp = base->aR[chanIndex];
tmp = (tmp & ADC_aR_D_MASK) >> ADC_aR_D_SHIFT;
#else
DEV_ASSERT(chanIndex < ADC_R_COUNT);
uint32_t tmp = base->R[chanIndex];
tmp = (tmp & ADC_R_D_MASK) >> ADC_R_D_SHIFT;
#endif /* FEATURE_ADC_HAS_EXTRA_NUM_REGS */
*result = (uint16_t)tmp;
}
ADC_DRV_AutoCalibration
ADC自动标定
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_AutoCalibration
* Description : This functions executes an Auto-Calibration sequence. It
* is recommended to run this sequence before using the ADC converter.
* this function will check and reset clock divide based the adc frequency.
* an error will be displayed if adc_freq too big
* this function will set satisfy clock divide,start calibration.
* final this function: restore adc clock divide,hardware average and trigger settings.
*
* Implements : ADC_DRV_AutoCalibration_Activity
*END**************************************************************************/
void ADC_DRV_AutoCalibration(const uint32_t instance)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
ADC_Type * const base = s_adcBase[instance];
/* set hardware average to maximum and set software trigger*/
bool hwavgen = ADC_GetHwAverageEnableFlag(base);
adc_average_t hwavg = ADC_GetHwAverageMode(base);
adc_trigger_t trig = ADC_GetTriggerMode(base);
uint8_t sampletime = ADC_GetSampleTime(base);
ADC_SetHwAverageMode(base, ADC_AVERAGE_32);
ADC_SetHwAverageEnableFlag(base, true);
ADC_SetTriggerMode(base, ADC_TRIGGER_SOFTWARE);
/* Set the sample time to the reset value because it affects the
calibration duration but not the results
*/
ADC_SetSampleTime(base, ADC_RESET_SAMPLE_TIME_VALUE);
base->CLPS = 0x00u;
base->CLP3 = 0x00u;
base->CLP2 = 0x00u;
base->CLP1 = 0x00u;
base->CLP0 = 0x00u;
base->CLPX = 0x00u;
base->CLP9 = 0x00u;
/*Set clock divider */
clock_names_t adc_clocks[ADC_INSTANCE_COUNT] = ADC_CLOCKS;
uint32_t adc_freq = 0u;
adc_clk_divide_t adc_clk_divide_res = ADC_GetClockDivide(base);
adc_clk_divide_t adc_clk_divide = ADC_CLK_DIVIDE_1;
status_t clk_status = CLOCK_SYS_GetFreq(adc_clocks[instance], &adc_freq);
DEV_ASSERT(clk_status == STATUS_SUCCESS);
(void) clk_status;
DEV_ASSERT(adc_freq >= ADC_CLOCK_FREQ_MIN_RUNTIME);
if ((adc_freq / (uint32_t)(1UL << ((uint32_t)(adc_clk_divide_res)))) <= (ADC_CLOCK_FREQ_MAX_RUNTIME / 2U))
{
/* no action if adc_freq is satisfy */
}
else
{
if ((adc_freq / 2U) <= (ADC_CLOCK_FREQ_MAX_RUNTIME / 2U))
{
adc_clk_divide = ADC_CLK_DIVIDE_2;
}
else if ((adc_freq / 4U) <= (ADC_CLOCK_FREQ_MAX_RUNTIME / 2U))
{
adc_clk_divide = ADC_CLK_DIVIDE_4;
}
else if ((adc_freq / 8U) <= (ADC_CLOCK_FREQ_MAX_RUNTIME / 2U))
{
adc_clk_divide = ADC_CLK_DIVIDE_8;
}
else
{
/* frequency is greater than required clock for calibration */
DEV_ASSERT(false);
}
ADC_SetClockDivide(base, adc_clk_divide);
}
/* start calibration */
ADC_SetCalibrationActiveFlag(base, true);
while (ADC_GetCalibrationActiveFlag(base))
{
/* Wait for calibration to finish */
}
/* restore adc clock divide*/
ADC_SetClockDivide(base, adc_clk_divide_res);
/* restore hardware average and trigger settings*/
ADC_SetHwAverageEnableFlag(base, hwavgen);
ADC_SetHwAverageMode(base, hwavg);
ADC_SetTriggerMode(base, trig);
ADC_SetSampleTime(base, sampletime);
}
ADC_DRV_InitUserCalibrationStruct
初始化自动标定结构体
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_InitUserCalibrationStruct
* Description : This function initializes the User Calibration configuration
* structure to default values (Reference Manual resets). This function should be called
* on a structure before using it to configure the User Calibration feature (ADC_DRV_ConfigUserCalibration),
* otherwise all members must be written by the caller. This function insures that all members are written
* with safe values, so the user can modify only the desired members.
*
* Implements : ADC_DRV_InitUserCalibrationStruct_Activity
*END**************************************************************************/
void ADC_DRV_InitUserCalibrationStruct(adc_calibration_t * const config)
{
DEV_ASSERT(config != NULL);
config->userGain = (uint16_t)ADC_DEFAULT_USER_GAIN;
config->userOffset = (uint16_t)0U;
}
ADC_DRV_ConfigUserCalibration
将用户标定结构体配置进ADC里面
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ConfigUserCalibration
* Description : This function sets the configuration for the user calibration
* registers.
*
* Implements : ADC_DRV_ConfigUserCalibration_Activity
*END**************************************************************************/
void ADC_DRV_ConfigUserCalibration(const uint32_t instance,
const adc_calibration_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
ADC_Type * const base = s_adcBase[instance];
ADC_SetUserGainValue(base, config->userGain);
ADC_SetUserOffsetValue(base, config->userOffset);
}
ADC_DRV_GetUserCalibration
获取用户标定结构体
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetUserCalibration
* Description : This function returns the current user calibration
* register values.
*
* Implements : ADC_DRV_GetUserCalibration_Activity
*END**************************************************************************/
void ADC_DRV_GetUserCalibration(const uint32_t instance,
adc_calibration_t * const config)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT(config != NULL);
const ADC_Type * const base = s_adcBase[instance];
config->userGain = ADC_GetUserGainValue(base);
config->userOffset = ADC_GetUserOffsetValue(base);
}
ADC_DRV_GetInterruptNumber
获取中断号
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetInterruptNumber
* Description : This function returns the interrupt number for the specified ADC instance.
*
* Implements : ADC_DRV_GetInterruptNumber_Activity
*END**************************************************************************/
IRQn_Type ADC_DRV_GetInterruptNumber(const uint32_t instance)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
static const IRQn_Type adcIrqId[ADC_INSTANCE_COUNT] = ADC_IRQS;
IRQn_Type irqId = adcIrqId[instance];
return irqId;
}
ADC_DRV_ClearLatchedTriggers
清除触发标志位
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ClearLatchedTriggers
* Description : This function clears all trigger latched flags of the ADC instance.
*
* Implements : ADC_DRV_ClearLatchedTriggers_Activity
*END**************************************************************************/
void ADC_DRV_ClearLatchedTriggers(const uint32_t instance,
const adc_latch_clear_t clearMode)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
DEV_ASSERT((clearMode == ADC_LATCH_CLEAR_WAIT) || (clearMode == ADC_LATCH_CLEAR_FORCE));
ADC_Type * const base = s_adcBase[instance];
if (clearMode == ADC_LATCH_CLEAR_FORCE)
{
ADC_ClearLatchTriggers(base);
}
while (ADC_GetTriggerLatchFlags(base) != 0u)
{
/* Wait for latched triggers to be processed */
}
}
ADC_DRV_ClearTriggerErrors
清除触发错误标志位
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_ClearTriggerErrors
* Description : This function clears all trigger error flags of the ADC instance.
*
* Implements : ADC_DRV_ClearTriggerErrors_Activity
*END**************************************************************************/
void ADC_DRV_ClearTriggerErrors(const uint32_t instance)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
ADC_Type * const base = s_adcBase[instance];
base->SC2 |= ADC_SC2_TRGSTERR_MASK;
}
ADC_DRV_GetTriggerErrorFlags
获取触发错误标志位
/*FUNCTION**********************************************************************
*
* Function Name : ADC_DRV_GetTriggerErrorFlags
* Description : This function returns the trigger error flags bits of the ADC instance.
*
* Implements : ADC_DRV_GetTriggerErrorFlags_Activity
*END**************************************************************************/
uint32_t ADC_DRV_GetTriggerErrorFlags(const uint32_t instance)
{
DEV_ASSERT(instance < ADC_INSTANCE_COUNT);
const ADC_Type * const base = s_adcBase[instance];
uint32_t trig_errors = (base->SC2 & ADC_SC2_TRGSTERR_MASK) >> ADC_SC2_TRGSTERR_SHIFT;
return trig_errors;
}
一般用法
初始化的时候初始化ADC就可以了,顺带自动标定一下。
void ADC_Init()
{
ADC_DRV_ConfigConverter(INST_ADCONV0, &adConv0_ConvConfig0);
ADC_DRV_AutoCalibration(INST_ADCONV0);
}
采集的时候三步走:转换对应通道采集到的值,等待转换完成,获取转换之后的值。
static uint16_t ADC_DRV_GetADCValue(const uint32_t instance,const adc_chan_config_t * const config)
{
uint16_t adcRawValue;
/* Configure ADC channel and software trigger a conversion */
ADC_DRV_ConfigChan(instance, 0U, config);
/* Wait for the conversion to be done */
ADC_DRV_WaitConvDone(instance);
/* Store the channel result into a local variable */
ADC_DRV_GetChanResult(instance, 0U, &adcRawValue);
return adcRawValue;
}