CSDN专栏:

第33讲:实战——ADC采集、电压采样快速代码生成

一、ADC基础

ADC(模数转换器)是模拟量采集的核心,用于读取传感器模拟信号、电压采样等。

1.1 ADC配置要点

基本参数

  • 分辨率:12位(STM32F103)
  • 采样时间:影响精度
  • 触发方式:软件触发、定时器触发
  • 转换模式:单次、连续、扫描

通道配置

ADC1通道:

  • 通道0:PA0
  • 通道1:PA1
  • 通道2:PA2
  • 通道3:PA3
  • 通道4:PA4
  • 通道5:PA5
  • 通道6:PA6
  • 通道7:PA7

二、单通道ADC采集

2.1 基础采集

Prompt

生成STM32F103 ADC采集代码:
- ADC1通道0:PA0
- 功能:采集电压值
- 使用HAL库

AI生成

#include "stm32f1xx_hal.h"

ADC_HandleTypeDef hadc1;

void ADC1_Init(void) {
    hadc1.Instance = ADC1;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.ContinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 1;
    HAL_ADC_Init(&hadc1);
    
    // 配置通道
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

uint16_t ADC_Read(void) {
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 100);
    uint16_t value = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    return value;
}

float ADC_ReadVoltage(void) {
    uint16_t raw = ADC_Read();
    float voltage = (float)raw * 3.3f / 4095.0f;
    return voltage;
}

int main(void) {
    HAL_Init();
    SystemClock_Config();
    ADC1_Init();
    UART_Init();
    
    while(1) {
        float voltage = ADC_ReadVoltage();
        printf("Voltage: %.2fV\r\n", voltage);
        HAL_Delay(100);
    }
}

2.2 多次采样滤波

平均值滤波

#define SAMPLE_COUNT  10

uint16_t ADC_ReadFiltered(void) {
    uint32_t sum = 0;
    
    for(uint8_t i = 0; i < SAMPLE_COUNT; i++) {
        sum += ADC_Read();
    }
    
    return sum / SAMPLE_COUNT;
}

中值滤波

#define MEDIAN_COUNT  5

uint16_t ADC_ReadMedian(void) {
    uint16_t values[MEDIAN_COUNT];
    
    for(uint8_t i = 0; i < MEDIAN_COUNT; i++) {
        values[i] = ADC_Read();
    }
    
    // 排序
    for(uint8_t i = 0; i < MEDIAN_COUNT - 1; i++) {
        for(uint8_t j = i + 1; j < MEDIAN_COUNT; j++) {
            if(values[i] > values[j]) {
                uint16_t temp = values[i];
                values[i] = values[j];
                values[j] = temp;
            }
        }
    }
    
    return values[MEDIAN_COUNT / 2];
}

三、多通道ADC采集

3.1 扫描模式

Prompt

生成STM32F103 多通道ADC采集代码:
- ADC1通道0-3:PA0-PA3
- 功能:采集4路电压
- 使用DMA传输
- 使用HAL库

AI生成

#define ADC_CHANNELS  4

uint16_t adcBuffer[ADC_CHANNELS];

void ADC1_Multi_Init(void) {
    hadc1.Instance = ADC1;
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;  // 扫描模式
    hadc1.Init.ContinuousConvMode = ENABLE;      // 连续转换
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = ADC_CHANNELS;
    HAL_ADC_Init(&hadc1);
    
    // 配置各通道
    ADC_ChannelConfTypeDef sConfig = {0};
    
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_1;
    sConfig.Rank = ADC_REGULAR_RANK_2;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_2;
    sConfig.Rank = ADC_REGULAR_RANK_3;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    sConfig.Channel = ADC_CHANNEL_3;
    sConfig.Rank = ADC_REGULAR_RANK_4;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    // 启动DMA
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, ADC_CHANNELS);
}

float ADC_GetVoltage(uint8_t channel) {
    if(channel >= ADC_CHANNELS) return 0.0f;
    return (float)adcBuffer[channel] * 3.3f / 4095.0f;
}

四、典型应用场景

4.1 电压监测

需求

监测电池电压,低于阈值报警

代码

#define BATTERY_LOW_THRESHOLD  3.3f

void Battery_Monitor(void) {
    float voltage = ADC_ReadVoltage();
    
    printf("Battery: %.2fV\r\n", voltage);
    
    if(voltage < BATTERY_LOW_THRESHOLD) {
        printf("Warning: Battery low!\r\n");
        // 报警
    }
}

4.2 温度采集(NTC热敏电阻)

需求

使用NTC热敏电阻测量温度

代码

// NTC参数
#define NTC_R25      10000.0f  // 25°C时的电阻(10kΩ)
#define NTC_BETA     3950.0f   // B值
#define NTC_R_REF    10000.0f  // 参考电阻(10kΩ)

float NTC_ReadTemperature(void) {
    uint16_t raw = ADC_Read();
    
    // 计算NTC电阻
    float r_ntc = (float)raw * NTC_R_REF / (4095.0f - raw);
    
    // 计算温度(B值方程)
    float tempK = 1.0f / (1.0f / 298.15f + log(r_ntc / NTC_R25) / NTC_BETA);
    float tempC = tempK - 273.15f;
    
    return tempC;
}

4.3 光照采集

需求

使用光敏电阻测量光照强度

代码

float Light_ReadIntensity(void) {
    uint16_t raw = ADC_Read();
    
    // 转换为光照强度(简化)
    // 实际需要根据光敏电阻特性曲线计算
    float intensity = (float)raw / 4095.0f * 100.0f;  // 0-100%
    
    return intensity;
}

五、本讲核心要点

6.1 记住这三句话

  1. ADC配置:分辨率、采样时间、触发方式、转换模式

  2. 数据滤波:平均值滤波、中值滤波,提高精度

  3. 典型应用:电压监测、温度采集、光照采集

6.2 下讲预告

第34讲将深入讲解:实战:PWM输出调速、控灯原型开发

PWM是电机控制、LED调光的基础,如何快速生成PWM代码?下一讲将详细讲解。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐