[APM32E1] APM32E103 ADC特性讲解及如何通过DMA读取ADC数值

[复制链接]
1078|1
 楼主| lc115647 发表于 2024-12-10 23:22 | 显示全部楼层 |阅读模式
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)。它们在工作模式、优先级、使用方式等方面有所不同
规则.png
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应用初始化
  1. void ADC_Init(void)
  2. {
  3.        GPIO_Config_T           gpioConfig;
  4.        ADC_Config_T            adcConfig;

  5.        /* Enable GPIOA clock */
  6.        RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);

  7.        /* Configure PC0 (ADC Channel0) as analog input */
  8.        GPIO_ConfigStructInit(&gpioConfig);
  9.        gpioConfig.mode    = GPIO_MODE_ANALOG;
  10.        gpioConfig.pin     = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  11.        GPIO_Config(GPIOA, &gpioConfig);

  12.        /* ADCCLK = PCLK2/4 */
  13.        RCM_ConfigADCCLK(RCM_PCLK2_DIV_4);

  14.        /* Enable ADC clock */
  15.        RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);

  16.        /* ADC configuration */
  17.        ADC_Reset(ADC1);

  18.        ADC_ConfigStructInit(&adcConfig);
  19.        adcConfig.mode                  = ADC_MODE_INDEPENDENT;
  20.        adcConfig.scanConvMode          = ENABLE;
  21.        adcConfig.continuosConvMode     = DISABLE;
  22.        adcConfig.externalTrigConv      = ADC_EXT_TRIG_CONV_None;
  23.        adcConfig.dataAlign             = ADC_DATA_ALIGN_RIGHT;
  24.        /* channel number */
  25.        adcConfig.nbrOfChannel          = 1;
  26.        ADC_Config(ADC1, &adcConfig);

  27.        /* ADC channel Convert configuration */
  28.        ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_13CYCLES5);

  29.        /* Enable ADC DMA */
  30.        ADC_EnableDMA(ADC1);

  31.        /* Enable ADC */
  32.        ADC_Enable(ADC1);

  33.        /* Enable ADC1 reset calibration register */
  34.        ADC_ResetCalibration(ADC1);
  35.        /* Check the end of ADC1 reset calibration register */
  36.        while (ADC_ReadResetCalibrationStatus(ADC1));

  37.        /* Start ADC1 calibration */
  38.        ADC_StartCalibration(ADC1);
  39.        /* Check the end of ADC1 calibration */
  40.        while (ADC_ReadCalibrationStartFlag(ADC1));

  41.        /* Start ADC1 Software Conversion */
  42.        ADC_EnableSoftwareStartConv(ADC1);
  43. }
DMA初始化
  1. void DMA_Init(void)
  2. {
  3.         DMA_Config_T dmaConfig;

  4.         /* Enable DMA Clock */
  5.        RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);

  6.        /* DMA config */
  7.        dmaConfig.peripheralBaseAddr = ((uint32_t)ADC1_BASE + 0x4C);
  8.        dmaConfig.memoryBaseAddr = (uint32_t)&DMA_ADCConvertedValue;
  9.        dmaConfig.dir = DMA_DIR_PERIPHERAL_SRC;
  10.        dmaConfig.bufferSize = 1;
  11.        dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
  12.        dmaConfig.memoryInc = DMA_MEMORY_INC_DISABLE;
  13.        dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_HALFWORD;
  14.        dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_HALFWORD;
  15.        dmaConfig.loopMode = DMA_MODE_CIRCULAR;
  16.        dmaConfig.priority = DMA_PRIORITY_HIGH;
  17.        dmaConfig.M2M = DMA_M2MEN_DISABLE;

  18.        /* Enable DMA channel */
  19.        DMA_Config(DMA1_Channel1, &dmaConfig);

  20.        /* Enable DMA */
  21.        DMA_Enable(DMA1_Channel1);
  22. }
主函数应用
  1. int main(void)
  2. {
  3.        /* ADC convert to voltage */
  4.        float voltage = 0;

  5.        USART_Config_T USART_ConfigStruct;

  6.        /* USART config */
  7.        USART_ConfigStruct.baudRate = 115200;
  8.        USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
  9.        USART_ConfigStruct.mode = USART_MODE_TX;
  10.        USART_ConfigStruct.parity = USART_PARITY_NONE;
  11.        USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
  12.        USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;

  13.        APM_MINI_COMInit(COM1, &USART_ConfigStruct);

  14.        /* DMA initialization */
  15.        DMA_Init();

  16.        /* ADC1 initialization */
  17.        ADC_Init();

  18.        while (1)
  19.        {
  20.               if (DMA_ReadStatusFlag(DMA1_FLAG_TC1) == SET)


发光的梦 发表于 2025-9-9 09:04 | 显示全部楼层
ADC的应用还可以这么高级。
我这小项目,小工程,感觉见识太少了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

29

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部