ADC(模拟信号转数字信号)在嵌入式中应用还是挺多的,很多传感器上面采集到的信号是模拟信号(常见的温度、光敏传感器),由于模拟信号不过形象,所以很多时候把它转换为便于识别的数值信号。M3中的ADC转换器是12位精度,多达18个通道(16个外部通道+2个内部信号源),各通道的A/D转换可以单次、连续、扫描或间断模式执行,并且每个通道可以单独设置采样时间,ADC转换的结果也可以左对齐或右对齐的方式存放在16位的数据寄存器中。并且M3的中ADC还支持模拟看门狗以允许应用程序检测输入电压是否超出用户定义的高/低阀值,超出可以产生中断。注意ADC的输入时钟不得超过14MHz,ADC供电是在2.4-3.6V之间,ADC电压的测量范围是Vref+ - Vref-。
ADC的框架图
ADCx_INx:模拟输入信号,外部的16个模拟输入通道。
Vref+、 Vref-:模拟参考正负极。ADC使用的高端/正极参考电压,2.4V ≤ VREF+ ≤ VDDA。
VDDA、VSSA:ADC模拟电源,用来对ADC模块供电。
ADC的开关控制。
M3上电后,为了降低设备的功耗,外设的时钟基本上都是关闭的,所以在使用ADC之前需要先开启ADC模块的时钟。ADC模块输入的时钟最大为14M,RCC控制器为ADC提供一个专用的可编程预分频器。库函数是:
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
RCC_APB2PeriphResetCmd (RCC_APB2Periph_ADC1,ENABLE);
/**
* @brief Configures the ADC clock (ADCCLK).
* @param RCC_PCLK2: defines the ADC clock divider. This clock is derived from
* the APB2 clock (PCLK2).
* This parameter can be one of the following values:
* @arg RCC_PCLK2_Div2: ADC clock = PCLK2/2
* @arg RCC_PCLK2_Div4: ADC clock = PCLK2/4
* @arg RCC_PCLK2_Div6: ADC clock = PCLK2/6
* @arg RCC_PCLK2_Div8: ADC clock = PCLK2/8
* @retval None
*/
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2)
ADC时钟开启之后,ADC进入断电模式(低功耗),需要设置配置寄存器的ADON位将其唤醒,ADC唤醒后需要延迟一段时间(SSTAB)用于稳定ADC模块,再次设置ADON位时才会会进行装换。**可以通过清除ADON位停止转换,并将ADC置于断电模式。**ADC在开始精度转换前需要一个稳定时间tSTAB,用于稳定ADC模块,设置ADON触发转换,转换后数据存在在相应的数据寄存器中。
使能ADC模块的库函数是:
/*唤醒ADC模块*/
/*@brief Enables or disables the specified ADC peripheral.*/
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/**
* @brief Enables or disables the analog watchdog on single/all regular
* or injected channels
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_AnalogWatchdog: the ADC analog watchdog configuration.
* This parameter can be one of the following values:
* @arg ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a single regular channel
* @arg ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a single injected channel
* @arg ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog on a single regular or injected channel
* @arg ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all regular channel
* @arg ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all injected channel
* @arg ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on all regular and injected channels
* @arg ADC_AnalogWatchdog_None: No channel guarded by the analog watchdog
* @retval None
*/
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);/*开启模拟看门狗*/
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);/*设置模拟看门狗的高低阀值*/
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);/*假如模拟看门狗是单通道使用,则需要指定哪个通道使用模拟看门狗*/
/*此函数用于设置规则组通道序列以及采样的时间,*/
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);/*获取规则组数据寄存器值*/
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);/*获取注入组数据寄存器值*/
/**
* @brief Enables or disables the specified ADC DMA request.
* @param ADCx: where x can be 1 or 3 to select the ADC peripheral.
* Note: ADC2 hasn't a DMA capability.
* @param NewState: new state of the selected ADC DMA transfer.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);/*开启DMA功能*/
装换结束后数据将会存放在相应的数据寄存器中,EOC标志被设置,要是使能了中断,则会产生相应的中断。
由于规则组数据寄存器只有一个,所以在连续转换时会存在数据的覆盖,这里可以设置配置寄存器中的DMA位,在每次转换结束后,DMA把数据寄存器中的数据传输到SRAM中;而注入通道装换的数据总是存储在ADC_JDRx中,每个注入通道都有一个相应的数据寄存器来保存数据。
/*开始转换规则通道,软件设置硬件清除*/
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
/*配置和使能间断模式*/
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/*规则组的外部触发使能,触发方式在ADC_InitTypeDef->ADC_ExternalTrigConv指定*/
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/*RSTCAL:复位校准和CAL:A/D校准都是由软件设置硬件清除,校准时ADC要处于关电状态*/
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
外部触发转换。
转换可以由外部事件触发,需要设置EXTTRIG控制位,需要配置触发事件(配置EXTSEL[2:0]和JEXTSEL[2:0])。只有在外部触发信号的上升沿才会启动转换。软件触发事件可以通过对寄存器ADC_CR2的SWSTART或JSWSTART位置’1’产生。
DMA请求。
规则通道转换的值存储在一个仅有的数据寄存器中,在转换多个规则通道时需要使用DMA,这样可以避免数据因覆盖而丢失。只有ADC1和ADC3拥有DMA功能,ADC2转换的数据可以通过双ADC模式利用ADC1的DMA功能传输。
ADC中断。ADC1和ADC2的中断映射在同一个中断向量上,ADC3的中断向量独立。中断有三种:规则组转换结束(EOC)中断;注入组转换结束(JEOC)中断;模拟看门狗中断(AWD)读取规则数据寄存器时会把EOC给清除
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
ADC通道IO分部
更多的细节请查阅参考手册。需要特别注意的是,用来做ADC输入的IO不能被复用,否则会导致采集到的信号不准确
还有一点需要注意的是连接在ADC引脚上的设备要和控制器芯片的供电一样,即有共地线