1、APM32E103 ADC特性
系列产品有3个 ADC,精度为 12位,每个 ADC最多有 16个外部通道和 2个内部通道。其中 ADC1和 ADC2都有 16个外部通道, ADC3一般有 8个外部通道,各通道 A/D转换模式有单次、连续、扫描或间断, ADC转换结果可以左对齐或右对齐存储在 16位数据寄存器中。
- ADC供电要求:2.4V到3.6V,一般电源电压为3.3V
- ADC输入范围:VREF- ≤VIN ≤VREF+。
- ADC模式: 独立 ADC模式 、 双 重 ADC模式
- 支持自校准功能:通过设置 ADC_CTRL2寄存器的 CAL位启动校准。在校准期间 CAL位置 1,校准结束硬件清零,每次上电前都重新执行一次校准操作。
2、ADC简介
2.1 模式介绍
扫描模式:这个模式就是自动扫描你开启的所有通道进行转换,直至转换完。例如你开启了CH0、CH1、CH2、CH3这四个通道,启动转换后ADC会自动将这4个通道全部转换完,但是这种连续性是可以被打断的,所以就引出了间断模式。
连续模式: 开启连续模式后,ADC的转换不由其他控制。例如将ADC设置为了定时器的TGRO触发采样,如果开启连续模式,ADC将忽略定时器的触发采样。(连续转换模式开启后其实就是满频率的采样)。
间断模式: 可以将多个通道进行分组采集,例如你开启了CH0~3这4个通道,假如你设置了间断次数为4,就相当于将4个通道分成了4组,每组1个通道,那么要想采集完这4个通道就需要手动触发4次ADC采集;如果设置了间断次数为2,那么采集完4个通道就需要手动触发2次ADC采集。
3、ADC的采样时间和采样频率的计算
根据手册上公式: TCONV=采样时间 +12.5个固定周期
采样时间由 SMPCYCCFGx[2:0]位控制,最小采样周期为 1.5个,当ADCCLK=14MHz,采样时间为 1.5周期: TCONV(转换时间)=1.5周期 +12.5周期 =14周期 =1 μs;因此可以知道E103 ADC最大的信号采样频率为1MHz;
4、ADC规则序列和注入序列
ADC 有两组不同的通道采样方式:规则组(Regular Group)和注入组(Injected Group)。它们在工作模式、优先级、使用方式等方面有所不同
5、独立ADC模式与双重ADC模式
独立ADC模式:即只使用一个ADC控制器模块对通道上的数据进行采样,每次只能读取一个通道上面的值;多通道、连续转换模式可如下所示
E103具有三个ADC并提供双 ADC 模式:可以以ADC1 为主,ADC2 为从。对于常规通道转换和注入通道转换,ADC1 与 ADC2 在内部同步。ADC1 与 ADC2 一起工作。可同时读取两个不同通道的值
双 ADC 常规同步模式用于同时执行两个转换,以实现 ADC1 与 ADC2 的同步。每个 ADC转换一个通道序列(已使能扫描并配置每个 ADC 的定序器)或者转换单个通道(已禁止扫描)。可以从外部触发或通过软件启动转换。在此模式下,ADC1 和 ADC2 的转换结果存储在 ADC1 的数据寄存器(32 位格式)中。下图显示了 ADC1 和 ADC2 同时转换两个序列的方式。ADC1 依次转换一个序列的16个通道:通道 15 到通道 0,ADC2 也依次转换一个序列的16个通道:通道 0 到通道 15。
常规双ADC同步模式如下所示
6、应用代码
ADC应用初始化
void ADC_Init(void)
{
GPIO_Config_T gpioConfig;
ADC_Config_T adcConfig;
/* Enable GPIOA clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
/* Configure PC0 (ADC Channel0) as analog input */
GPIO_ConfigStructInit(&gpioConfig);
gpioConfig.mode = GPIO_MODE_ANALOG;
gpioConfig.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
GPIO_Config(GPIOA, &gpioConfig);
/* ADCCLK = PCLK2/4 */
RCM_ConfigADCCLK(RCM_PCLK2_DIV_4);
/* Enable ADC clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
/* ADC configuration */
ADC_Reset(ADC1);
ADC_ConfigStructInit(&adcConfig);
adcConfig.mode = ADC_MODE_INDEPENDENT;
adcConfig.scanConvMode = ENABLE;
adcConfig.continuosConvMode = DISABLE;
adcConfig.externalTrigConv = ADC_EXT_TRIG_CONV_None;
adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT;
/* channel number */
adcConfig.nbrOfChannel = 1;
ADC_Config(ADC1, &adcConfig);
/* ADC channel Convert configuration */
ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_13CYCLES5);
/* Enable ADC DMA */
ADC_EnableDMA(ADC1);
/* Enable ADC */
ADC_Enable(ADC1);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while (ADC_ReadResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while (ADC_ReadCalibrationStartFlag(ADC1));
/* Start ADC1 Software Conversion */
ADC_EnableSoftwareStartConv(ADC1);
}
DMA初始化
void DMA_Init(void)
{
DMA_Config_T dmaConfig;
/* Enable DMA Clock */
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);
/* DMA config */
dmaConfig.peripheralBaseAddr = ((uint32_t)ADC1_BASE + 0x4C);
dmaConfig.memoryBaseAddr = (uint32_t)&DMA_ADCConvertedValue;
dmaConfig.dir = DMA_DIR_PERIPHERAL_SRC;
dmaConfig.bufferSize = 1;
dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
dmaConfig.memoryInc = DMA_MEMORY_INC_DISABLE;
dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_HALFWORD;
dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_HALFWORD;
dmaConfig.loopMode = DMA_MODE_CIRCULAR;
dmaConfig.priority = DMA_PRIORITY_HIGH;
dmaConfig.M2M = DMA_M2MEN_DISABLE;
/* Enable DMA channel */
DMA_Config(DMA1_Channel1, &dmaConfig);
/* Enable DMA */
DMA_Enable(DMA1_Channel1);
}
主函数应用
int main(void)
{
/* ADC convert to voltage */
float voltage = 0;
USART_Config_T USART_ConfigStruct;
/* USART config */
USART_ConfigStruct.baudRate = 115200;
USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
USART_ConfigStruct.mode = USART_MODE_TX;
USART_ConfigStruct.parity = USART_PARITY_NONE;
USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
APM_MINI_COMInit(COM1, &USART_ConfigStruct);
/* DMA initialization */
DMA_Init();
/* ADC1 initialization */
ADC_Init();
while (1)
{
if (DMA_ReadStatusFlag(DMA1_FLAG_TC1) == SET)
|