第十四章 ADC(下篇)

第十四章 ADC(下篇)

目录

第十四章 ADC(下篇)

1 例程设计

1.1 ADC_Double例程

1.2 ADC_Single例程

1.3 ADC_VrefintTemper例程

2 下载验证

2.1 ADC_Double例程

2.2 ADC_Single例程

2.3 ADC_VrefintTemper例程


1 例程设计

1.1 ADC_Double例程

这是一个基于 W55MH32 的 ADC(模拟 - 数字转换器)双模式测试例程。它的主要功能是配置串口、ADC 和 DMA,并且通过 ADC1 和 ADC2 同时对模拟信号进行采样,最后把采样结果通过串口打印出来。下面是对这个例程的设计分析:

1.系统初始化

  • 配置系统时钟、延时函数、串口、ADC 和 DMA。
  • 打印系统时钟频率信息。

2. ADC 双模式采样

  • ADC1 和 ADC2 工作于规则同步模式,同时对通道 0 和通道 1 进行采样。
  • 转换结果通过 DMA 传输到内存缓冲区。
void ADC_Configuration(void)
{
    ADC_InitTypeDef  ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    RCC_ADCCLKConfig(RCC_PCLK2_Div8);
    ADC_DeInit(ADC1);
    ADC_DeInit(ADC2);

    // 配置为规则同步模式
    ADC_InitStructure.ADC_Mode               = ADC_Mode_RegSimult; 
    ADC_InitStructure.ADC_ScanConvMode       = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel       = 1;
    ADC_Init(ADC1, &ADC_InitStructure);
    ADC_Init(ADC2, &ADC_InitStructure);

    /* channel configuration */
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);

    /* module enablement */
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);

    /* adc calibration */
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));
    ADC_ResetCalibration(ADC2);
    while (ADC_GetResetCalibrationStatus(ADC2));
    ADC_StartCalibration(ADC2);
    while (ADC_GetCalibrationStatus(ADC2));

    DMA_Configuration();
}

3.数据处理与输出

  • DMA 传输完成后触发中断,将 ADC 数字值转换为电压值并通过串口打印。
void DMA1_Channel1_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA1_IT_TC1) != RESET)
    {
        DMA_ClearITPendingBit(DMA1_IT_TC1);
        DMA_ClearFlag(DMA1_FLAG_TC1);

        // 数据处理与输出
        printf("ADC1 Code Value = %d ,voltage value = %2.4f\n", DAM_ADC_Value[0] & 0xFFFF,
               (float)VREF * (DAM_ADC_Value[0] & 0xFFFF) / 4095 / 1000);
        printf("ADC2 Code Value = %d ,voltage value = %2.4f\n", (DAM_ADC_Value[0] >> 16) & 0xFFFF,
               (float)VREF * ((DAM_ADC_Value[0] >> 16) & 0xFFFF) / 4095 / 1000);
    }
}

1.2 ADC_Single例程

该例程是一个基于 W55MH32 微控制器的 ADC 单通道采样程序,主要功能是周期性采集模拟输入信号并通过串口输出 ADC 值及其对应的电压。以下是详细的工作流程总结:

1.时钟配置

  • 获取系统各时钟频率(SYSCLK/HCLK/PCLK/ADCCLK),并通过串口打印。

2.UART 配置

  • 初始化 USART1 为 115200 波特率,用于串口输出数据。

3.ADC 配置

  • 使能 ADC1 时钟,配置 PA6 为模拟输入模式。
  • ADC 工作在独立模式,禁用连续转换,启用扫描模式(单通道时仅触发一次转换)。
  • 执行 ADC 校准以确保精度。
void ADC_Configuration(void)
{
    uint32_t         i;
    ADC_InitTypeDef  ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能 ADC1 和 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);

    // 配置 PA6 为模拟输入模式
    GPIO_InitStructure.GPIO_Pin   = ADC_TEST_CHANNEL_PIN; // PA6
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // ADC 时钟配置(PCLK2 的 1/8)
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);
    ADC_DeInit(ADC1); // 复位 ADC1

    // ADC 初始化配置
    ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent; // 独立模式
    ADC_InitStructure.ADC_ScanConvMode       = ENABLE;               // 启用扫描模式(单通道时仅转换一次)
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;              // 禁用连续转换,需软件触发
    ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None; // 软件触发
    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;  // 右对齐
    ADC_InitStructure.ADC_NbrOfChannel       = CONV_CHANNEL_NUM;     // 通道数(1)
    ADC_Init(ADC1, &ADC_InitStructure);

    // 配置 ADC 通道(通道 6,采样时间 239.5 周期)
    for (i = 0; i < CONV_CHANNEL_NUM; i++)
    {
        ADC_RegularChannelConfig(ADC1, ADC_CovChannel[i], i + 1, ADC_SampleTIME[i]);
    }

    // 启动 ADC 转换并使能 ADC
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    ADC_Cmd(ADC1, ENABLE);

    // ADC 校准
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));

    // 配置 DMA 传输
    DMA_Configuration();
}

4.DMA 配置

  • 设置 DMA1 通道 1 为循环模式,将 ADC 数据寄存器(ADC1->DR)的数据传输到内存数组DAM_ADC_Value
  • 使能 DMA 传输完成中断(TC 中断),触发数据处理。

1.3 ADC_VrefintTemper例程

该例程是一个基于 W55MH32 的 ADC 多通道采样程序,主要用于同时采集内部温度传感器和 VREFINT(内部参考电压)的模拟信号,并通过串口输出测量结果。以下是其主要工作流程如下:

1.系统初始化

          a.UART 配置:初始化 USART1 为 115200 波特率,用于串口输出。

          b.ADC 配置:使能 ADC1 时钟,配置为独立模式,启用扫描模式(多通道依次转换)。

  • 配置通道 16(温度传感器)和通道 17(VREFINT),采样时间 239.5 周期。
  • 校准 ADC 并使能内部温度传感器和 VREFINT。
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 启用扫描模式,多通道依次转换
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 禁用连续转换,需软件触发
ADC_TempSensorVrefintCmd(ENABLE); // 使能内部温度传感器和VREFINT

          c.DMA 配置:设置 DMA1 通道 1 为循环模式,将 ADC 数据寄存器(ADC1->DR)的数据传输到内存数组DAM_ADC_Value

  • 使能 DMA 传输完成中断(TC 中断)。

2.主循环逻辑

        a.每秒调用ADC_SoftwareStartConvCmd(ADC1, ENABLE)触发 ADC 转换。

        b.延时 1 秒后重复触发,实现周期性采样。

3.数据处理与输出

void DMA1_Channel1_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA1_IT_TC1) != RESET) // 检查传输完成中断
    {
        DMA_ClearITPendingBit(DMA1_IT_TC1); // 清除中断标志
        DMA_ClearFlag(DMA1_FLAG_TC1);

        // 计算温度传感器和VREFINT的电压值(VREF=3.3V,ADC精度12位)
        float tempVoltage = (float)VREF * DAM_ADC_Value[0] / 4095 / 1000; // 温度传感器电压
        float vrefintVoltage = (float)VREF * DAM_ADC_Value[1] / 4095 / 1000; // VREFINT电压

        // 串口输出结果
        printf("Temperature Sensor AD Value: %d, Voltage: %.4f V\t", DAM_ADC_Value[0], tempVoltage);
        printf("VREFINT AD Value: %d, Voltage: %.4f V\n", DAM_ADC_Value[1], vrefintVoltage);
    }
}

a.DMA 中断处理:当 DMA 传输完成时,触发DMA1_Channel1_IRQHandler

b.电压计算:根据公式 电压 = VREF × ADC值 / 4095 / 1000 计算实际电压值(VREF=3.3V)。

c.串口打印:输出温度传感器和 VREFINT 的 ADC 值及电压值。

2 下载验证

2.1 ADC_Double例程

程序运行时,ADC1和ADC2以规则同步模式周期性采样两个模拟通道(PA0和PA1),转换结果通过DMA传输至内存。每次DMA传输完成后触发中断,在中断中计算并通过串口打印ADC1和ADC2的原始数值(12位)及对应的电压值(单位:V),显示间隔由主循环中的1秒延时控制。系统启动时会输出各时钟频率参数,随后每秒更新一次ADC数据。

2.2 ADC_Single例程

程序运行时,系统首先输出各时钟频率参数,随后每秒触发一次ADC1通道6(PA6)的模拟信号采样。ADC转换结果通过DMA自动传输至内存,每次DMA传输完成后触发中断,在中断服务函数中计算并通过串口打印ADC原始值(12位)及对应的电压值(单位:V)。系统以1秒为间隔循环触发采样,实现周期性数据更新,最终在串口终端每秒显示一次ADC数据。

2.3 ADC_VrefintTemper例程

程序运行时,系统首先输出各时钟频率参数,随后每秒触发一次ADC1通道16(内部温度传感器)和通道17(VREFINT)的模拟信号采样。ADC转换结果通过DMA自动传输至内存,每次DMA传输完成后触发中断,在中断服务函数中计算并通过串口打印两个通道的ADC原始值(12位)及对应的电压值(单位:V)。系统以1秒为间隔循环触发采样,实现周期性数据更新,最终在串口终端每秒显示一次内部温度传感器和VREFINT的测量结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值