一、ADC 初始化结构体详解
1.前言:
前面文章了解了ADC模块的基本框架,下面再讲解一下标准库的初始化结构体部分。结构体 xxx_InitTypeDef 和库函数 xxx_Init 配合使用是标准库精髓所在,理解了结构体xxx_InitTypeDef 每个成员意义基本上就可以对该外设运用自如了。结构体 xxx_InitTypeDef 定义在 stm32f4xx_xxx.h 文件中,库函数 xxx_Init 定义在 stm32f4xx_xxx.c 文件中,编程时我们可以结合这两个文件内注释使用。
2.ADC_InitTypeDef 结构体
ADC_InitTypeDef 结构体定义在 stm32f4xx_adc.h 文件内,具体定义如下:
typedef struct
{
uint32_t ADC_Resolution; //ADC 分辨率选择
FunctionalState ADC_ScanConvMode; //ADC 扫描选择
FunctionalState ADC_ContinuousConvMode; //ADC 连续转换模式选择
uint32_t ADC_ExternalTrigConvEdge; //ADC 外部触发极性
uint32_t ADC_ExternalTrigConv; //ADC 外部触发选择
uint32_t ADC_DataAlign; //输出数据对齐方式
uint8_t ADC_NbrOfConversion; //转换通道数目
}ADC_InitTypeDef;
ADC_Resolution:
配置 ADC 的分辨率,可选的分辨率有 12 位、 10 位、 8 位和 6 位。分辨率越高,AD 转换数据精度越高,转换时间也越长;(一般选用12位)。
#define ADC_Resolution_12b ((uint32_t)0x00000000) //分辨率12bit
#define ADC_Resolution_10b ((uint32_t)0x01000000) //分辨率10bit
#define ADC_Resolution_8b ((uint32_t)0x02000000)
#define ADC_Resolution_6b ((uint32_t)0x03000000)
ScanConvMode:
配置是否使用扫描。如果是单通道 AD 转换使用 DISABLE,如果是多通道 AD 转换使用 ENABLE。
(扫描的意思就是,如果你使用了多个通道的,它会扫描你所有的通道,依次执行一次转化。
如果不使用,则会按照你配置的转化顺序转化一个通道。)
ADC_ContinuousConvMode:
配置是启动自动连续转换还是单次转换。使用 ENABLE 配置为使能自动连续转换;使用 DISABLE 配置为单次转换,转换一次后停止需要手动控制才重新启动转换。
( 如果上面配置了扫描模式,这是使用单次转化模式,则依次转化你配置的所有通道后停止。
如果上面配置了扫描模式,这是使用连续转化模式,则依次转化你配置的所有通道后再轮询从头开始转化。)
注意:这里开启的连续转化模式是只有规则通道开启了,注入通道还需要再ADC_CR1 寄存器中的 JAUTO位置1 ,需要调用此函数 ADC_AutoInjectedConvCmd(); 都开启后则注入组中的通道会在规则组通道之后自动转换。
拓展补充:
还有一个不连续采样模式,与单次转化模式不太一样,还需要单独的函数去配置开启。
/***** 规则通道 ****//
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);//配置所选ADCx规则通道的不连续模式的通道计数。
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//启用或禁用指定ADCx的规则通道上的不连续模式。
/**** 注入通道 ********/
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//启用或禁用指定ADCx的注入组通道的不连续模式
ADC_ExternalTrigConvEdge: (用于配置规则通道)
外部触发极性选择,如果使用外部触发,可以选择触发的极性,可选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。(不需要外部触发就配置禁止,即是软件触发)
/* ADC external trigger edge for regular channels conversion 规则通道的 */
#define ADC_ExternalTrigConvEdge_None ((uint32_t)0x00000000)//禁止触发检测
#define ADC_ExternalTrigConvEdge_Rising ((uint32_t)0x10000000)//上升沿触发检测
#define ADC_ExternalTrigConvEdge_Falling ((uint32_t)0x20000000)//下降沿触发检测
#define ADC_ExternalTrigConvEdge_RisingFalling ((uint32_t)0x30000000)//上升沿和下降沿均可触发检测
注意:
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
//禁止触发检测,使用软件触发(规则通道)
ADC_Init(ADC1, &ADC_InitStructure)
//这里是配置的规则通道的外部触发极性选择,
ADC_ExternalTrigInjectedConvEdgeConfig(ADC1, ADC_ExternalTrigInjecConvEdge_Rising);
/* 这个函数是配置注入通道的,注意不要混淆,具体可以参考程序和参考手册的寄存器*/
ADC_ExternalTrigConv: (用于配置规则通道)
外部触发选择,图单个 ADC 功能框图 中列举了很多外部触发条件,可根据项目需求配置触发来源。实际上,我们一般使用软件自动触发。(没有外部触发就可以不用配置)
/* ADC_extrenal_trigger_sources_for_regular_channels_conversion 规则通道的 */
#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) //定时器1的CC1事件触发。
#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x01000000) //.....以下就省略不写啦
#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x02000000)
#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x03000000)
#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x04000000)
#define ADC_ExternalTrigConv_T2_CC4 ((uint32_t)0x05000000)
#define ADC_ExternalTrigConv_T2_TRGO ((uint32_t)0x06000000)
#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x07000000)
#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x08000000)
#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x09000000)
#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x0A000000)
#define ADC_ExternalTrigConv_T5_CC2 ((uint32_t)0x0B000000)
#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x0C000000)
#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x0D000000)
#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x0E000000)
#define ADC_ExternalTrigConv_Ext_IT11 ((uint32_t)0x0F000000)
**** 注意: ****
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_Init(ADC1, &ADC_InitStructure)
//同样这个也是只配置规则通道的外部触发条件
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4);
/* 这个函数是配置注入通道的外部触发条件*/
ADC_DataAlign:
转换结果数据对齐模式,可选右对齐 ADC_DataAlign_Right 或者左对齐ADC_DataAlign_Left
一般我们选择右对齐模式。
ADC_NbrOfChannel: (用于配置规则通道)
AD 转换通道数目。(1<=数目<=16)
注意:
这里也是配置的规则通道的转化通道数目。
ADC_InjectedSequencerLengthConfig(ADC1, 2);
//设置注入通道长度
//这个函数是单独配置注入通道的数目
3.ADC_CommonInitTypeDef 结构体
ADC 除了有 ADC_InitTypeDef 初始化结构体外,还有一个 ADC_CommonInitTypeDef 通用初始化结构体。 ADC_CommonInitTypeDef 结构体内容决定三个 ADC 共用的工作环境,比如模式选择、ADC 时钟等等。
ADC_CommonInitTypeDef 结构体也是定义在 stm32_f4xx.h 文件中,具体定义如下:
typedef struct
{
uint32_t ADC_Mode; //ADC模式
uint32_t ADC_Prescaler; //ADC分频系数
uint32_t ADC_DMAAccessMode; //DMA模式配置
uint32_t ADC_TwoSamplingDelay; //采样延迟
}ADC_CommonInitTypeDef;
ADC_Mode:
ADC 工作模式选择,有独立模式、双重模式以及三重模式,stm32F4系类一共有13种工作模式(其他芯片可能不同有13种)。
/* 所有ADC都独立 */
#define ADC_Mode_Independent ((uint32_t)0x00000000) //独立模式
/* ADC1和ADC2一起工作,ADC3独立 双重模式*/
/* 规则同时+注入同时组合模式 */
#define ADC_DualMode_RegSimult_InjecSimult ((uint32_t)0x00000001) //规则同步+注入同步组合模式
#define ADC_DualMode_RegSimult_AlterTrig ((uint32_t)0x00000002) //规则同步+交替触发组合模式
#define ADC_DualMode_InjecSimult ((uint32_t)0x00000005) //注入同步模式
#define ADC_DualMode_RegSimult ((uint32_t)0x00000006) //规则同步模式
#define ADC_DualMode_Interl ((uint32_t)0x00000007) //交替模式
#define ADC_DualMode_AlterTrig ((uint32_t)0x00000009) //交替触发模式
/* ADC1、ADC2和ADC3一起工作 三重模式 */
/* 规则同时+注入同时组合模式 */
#define ADC_TripleMode_RegSimult_InjecSimult ((uint32_t)0x00000011) //规则同步+注入同步组合模式
#define ADC_TripleMode_RegSimult_AlterTrig ((uint32_t)0x00000012) //规则同步+交替触发组合模式
#define ADC_TripleMode_InjecSimult ((uint32_t)0x00000015) //注入同步模式
#define ADC_TripleMode_RegSimult ((uint32_t)0x00000016) //规则同步模式
#define ADC_TripleMode_Interl ((uint32_t)0x00000017) //交替模式
#define ADC_TripleMode_AlterTrig ((uint32_t)0x00000019) //交替触发模式
ADC_Prescaler: ADC 时钟分频系数选择, ADC 时钟是有 PCLK2 分频而来,分频系数决定 ADC时钟频率,可选的分频系数为 2、 4、 6 和 8。 stm32F4的PCLK2 最大时钟配置为 84MHz,如果选2分频,则ADC的时钟为84/2=42MHz。
#define ADC_Prescaler_Div2 ((uint32_t)0x00000000) /*PCLK2 2分频 */
#define ADC_Prescaler_Div4 ((uint32_t)0x00010000) /*PCLK2 4分频 */
#define ADC_Prescaler_Div6 ((uint32_t)0x00020000) /*PCLK2 6分频 */
#define ADC_Prescaler_Div8 ((uint32_t)0x00030000) /*PCLK2 8分频 */
ADC_DMAAccessMode:
DMA 模式设置,只有在双重或者三重模式才需要设置,可以设置三种模式,具体可参考参考手册说明。
#define ADC_DMAAccessMode_Disabled ((uint32_t)0x00000000) /* 禁止DMA模式*/
#define ADC_DMAAccessMode_1 ((uint32_t)0x00004000) /* 使能DMA模式1*/
#define ADC_DMAAccessMode_2 ((uint32_t)0x00008000) /* 使能DMA模式2*/
#define ADC_DMAAccessMode_3 ((uint32_t)0x0000C000) /* 使能DMA模式3 */
/* 注意 上面的只用于在双重或者三重模式 */
/*若使用为独立模式,开启DMA则需要下面函数开启。 */
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); //开启DMA
ADC_TwoSamplingDelay: 2 个采样阶段之前的延迟,(仅适用于双重或三重交错模式)。
(注:如果没有使用双重或三重模式,则不用配置此参数)
#define ADC_TwoSamplingDelay_5Cycles ((uint32_t)0x00000000) /* 5个Tadcclk */
//中间的就省略不写了,一共是 5 -- 20
#define ADC_TwoSamplingDelay_20Cycles ((uint32_t)0x00000F00) /* 20个Tadcclk */
4.ADC的标准库函数
再分析一些标准库的函数功能
void ADC_DeInit(void);
//将ADC配置设置为默认复位状态
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
//开启ADCx的A/D转换器
- 规则通道配置函数
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
// 配置 ADCx规则 通道转换顺序,采样时间
ADC_SoftwareStartConv(ADC_TypeDef* ADCx);
//使能指定的ADCx的软件转换启动功能
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
//获取所选ADC软件的开始定期转换状态。
void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
//启用或禁用ADC连续转换模式ADCx
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
//配置所选ADCx规则通道的不连续模式的通道计数。
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
//启用或禁用指定ADCx的规则通道上的不连续模式。
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
//返回规则通道的上一个ADCx转换结果数据。
- 规则通道DMA配置功能
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
//启用或禁用指定的ADCx的DMA请求(对于独立模式)。
void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
//在最后一次传输后启用或禁用ADC DMA请求(对于独立模式)
- 注入通道配置功能
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
//为所选ADCx注入通道配置其在注入序列中的转换顺序及其采样时间。
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
//配置注入通道的注入序列长度。
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset)
//设置注入通道转换值偏移量
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
//为注入通道转换配置ADCx外部触发器事件。
void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge);
//为注入通道转换配置ADCx外部触发极性。
void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx);
//启用所选ADCx软件启动注入通道的转换
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx)
//获取所选ADC软件的开始注入转换状态。
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
//启用或禁用所选ADC在规则通道转换后的自动注入通道转换。
ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
//为指定的ADC启用或禁用注入组通道的不连续模式。
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
//返回ADC注入通道转换结果
- 中断和标志管理功能
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState)
//启用或禁用指定的ADC中断。
ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
//检查是否设置了指定的ADC标志。
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
//清除ADCx的挂起标志。
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
//检查指定的ADCx的中断是否发生
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
//清除ADCx的中断挂起位。
5.最后:
总算是填完了,具体细节内容请参考标准库和参考手册,多重ADC模式暂时用不着就没有写,后续用到了再补上,也感谢读者能耐心看到这里,如有错误的地方请多多指导。