打印
[APM32E1]

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

[复制链接]
159|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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)。它们在工作模式、优先级、使用方式等方面有所不同

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)


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

4

帖子

0

粉丝