STM8S103 电压电流测量程序

STM8S103测量电压和电流的程序,包含ADC多通道采样、分流器计算、滤波算法、过载保护等功能。

一、硬件连接

1.1 测量电路设计

电压测量电路 (0-30V):
Vin(0-30V) → 分压电阻 → ADC通道2(PA2)
计算:R1=100kΩ, R2=10kΩ → 分压比=1/11
ADC量程:0-5V对应0-55V输入

电流测量电路 (0-5A):
电流采样 → 分流电阻(0.1Ω) → 运放放大 → ADC通道3(PA3)
分流器:0.1Ω, 0.5W
运放:LM358, 放大倍数=10
ADC量程:0-5V对应0-5A输入

保护电路:
├── 过压保护:TVS管
├── 过流保护:自恢复保险丝
└── 反向保护:二极管

1.2 STM8S103引脚配置

STM8S103F3P6 (20引脚)
├── 电源
│   ├── VDD → 5V
│   └── VSS → GND
├── 电压测量
│   └── PA2 (AIN2) → 分压输出
├── 电流测量
│   └── PA3 (AIN3) → 运放输出
├── 串口调试
│   ├── PD5 (UART1_TX) → TX
│   └── PD6 (UART1_RX) → RX
├── 状态指示
│   ├── PC3 → LED1 (电源指示)
│   ├── PC4 → LED2 (测量指示)
│   └── PC5 → LED3 (故障指示)
└── 控制接口
    ├── PB4 → 校准按键
    ├── PB5 → 模式选择
    └── PD3 → 继电器控制

二、核心驱动实现

2.1 主头文件

/**
 * @file measurement.h
 * @brief STM8S103 电压电流测量
 */

#ifndef __MEASUREMENT_H
#define __MEASUREMENT_H

#include "stm8s.h"
#include <stdint.h>
#include <stdbool.h>

/* 系统时钟频率 */
#define F_CPU        16000000UL  // 16MHz
#define F_MASTER     F_CPU

/* ADC配置 */
#define ADC_SAMPLE_TIMES   16     // 采样次数
#define ADC_REF_VOLTAGE    5.0f   // 参考电压5V
#define ADC_RESOLUTION     1024   // 10位ADC

/* 电压测量参数 */
#define VOLTAGE_DIVIDER_RATIO  11.0f  // 分压比 R1+R2/R2 = 11
#define VOLTAGE_MAX_INPUT      55.0f  // 最大输入电压55V
#define VOLTAGE_OVER_THRESHOLD 50.0f  // 过压阈值50V
#define VOLTAGE_UNDER_THRESHOLD 5.0f  // 欠压阈值5V

/* 电流测量参数 */
#define CURRENT_SHUNT_RESISTOR 0.1f   // 分流电阻0.1Ω
#define CURRENT_AMP_GAIN       10.0f  // 运放放大倍数
#define CURRENT_MAX_INPUT      5.0f   // 最大输入电流5A
#define CURRENT_OVER_THRESHOLD 4.5f   // 过流阈值4.5A

/* 测量结果结构体 */
typedef struct {
    float voltage_raw;       // 原始电压值
    float voltage_filtered;  // 滤波后电压
    float current_raw;       // 原始电流值
    float current_filtered;  // 滤波后电流
    float power;             // 功率计算
    float energy;            // 累计能量(Wh)
    uint32_t sample_count;   // 采样计数
    uint8_t error_flags;     // 错误标志
} Measurement_Result;

/* 错误标志位 */
#define ERROR_OVERVOLTAGE    (1 << 0)
#define ERROR_OVERCURRENT    (1 << 1)
#define ERROR_ADC_FAILURE    (1 << 2)
#define ERROR_CALIBRATION    (1 << 3)
#define ERROR_WATCHDOG       (1 << 4)

/* 校准参数结构体 */
typedef struct {
    float voltage_offset;    // 电压零点偏移
    float voltage_gain;      // 电压增益
    float current_offset;    // 电流零点偏移
    float current_gain;      // 电流增益
    uint8_t calibrated;      // 校准标志
} Calibration_Data;

/* 滤波器结构体 */
typedef struct {
    float alpha;             // 滤波系数
    float prev_value;        // 前一次值
    uint8_t window_size;     // 滑动窗口大小
    float buffer[16];        // 缓冲区
    uint8_t index;           // 缓冲区索引
} Filter_Data;

/* 函数声明 */
void System_Init(void);
void ADC_Init(void);
void GPIO_Init(void);
void Timer_Init(void);
void UART_Init(void);
void IWDG_Init(void);

float ADC_ReadVoltage(void);
float ADC_ReadCurrent(void);
float ADC_ConvertToVoltage(uint16_t adc_value);
float Calculate_Power(float voltage, float current);
float Calculate_Energy(float power, float time_ms);

void Moving_Average_Filter(Filter_Data *filter, float new_value);
float Low_Pass_Filter(float new_value, float old_value, float alpha);
void Kalman_Filter_Init(void);
float Kalman_Filter_Update(float measurement);

void Measurement_Process(void);
void Calibration_Process(void);
void Protection_Check(Measurement_Result *result);
void Error_Handler(uint8_t error_code);

void Print_Measurement(Measurement_Result *result);
void Print_Calibration(void);
void Print_System_Info(void);

uint8_t Save_Calibration(void);
uint8_t Load_Calibration(void);
void Default_Calibration(void);

/* 全局变量 */
extern Measurement_Result measurement;
extern Calibration_Data calibration;
extern Filter_Data voltage_filter;
extern Filter_Data current_filter;
extern volatile uint32_t system_tick;
extern volatile uint8_t measurement_ready;

#endif /* __MEASUREMENT_H */

2.2 主程序实现

/**
 * @file main.c
 * @brief STM8S103 电压电流测量主程序
 */

#include "measurement.h"
#include <stdio.h>
#include <string.h>

/* 全局变量 */
Measurement_Result measurement = {0};
Calibration_Data calibration = {0};
Filter_Data voltage_filter = {0.1, 0.0, 8, {0}, 0};
Filter_Data current_filter = {0.1, 0.0, 8, {0}, 0};
volatile uint32_t system_tick = 0;
volatile uint8_t measurement_ready = 0;
volatile uint32_t energy_accumulator = 0;
float power_history[60] = {0};  // 60秒功率历史
uint8_t power_index = 0;

/* 函数声明 */
void SystemClock_Config(void);
void Delay_Ms(uint32_t ms);
void Watchdog_Refresh(void);
void Button_Handler(void);
void LED_Control(void);

/**
 * @brief 主函数
 */
void main(void)
{
    /* 禁用中断 */
    disableInterrupts();
    
    /* 系统初始化 */
    SystemClock_Config();
    System_Init();
    
    /* 外设初始化 */
    GPIO_Init();
    ADC_Init();
    Timer_Init();
    UART_Init();
    IWDG_Init();
    
    /* 加载校准数据 */
    if(Load_Calibration() == 0)
    {
        Default_Calibration();
    }
    
    /* 启用中断 */
    enableInterrupts();
    
    printf("\nSTM8S103 Voltage/Current Meter\n");
    printf("==============================\n");
    printf("System Initialized\n");
    printf("ADC Reference: %.2fV\n", ADC_REF_VOLTAGE);
    printf("Max Voltage: %.1fV\n", VOLTAGE_MAX_INPUT);
    printf("Max Current: %.1fA\n", CURRENT_MAX_INPUT);
    printf("Sampling Rate: 100Hz\n");
    
    Print_System_Info();
    
    /* 指示灯测试 */
    GPIO_WriteHigh(GPIOC, GPIO_PIN_3);  // 电源LED亮
    Delay_Ms(500);
    GPIO_WriteHigh(GPIOC, GPIO_PIN_4);  // 测量LED亮
    Delay_Ms(500);
    GPIO_WriteLow(GPIOC, GPIO_PIN_3);
    GPIO_WriteLow(GPIOC, GPIO_PIN_4);
    
    uint32_t last_measure_time = 0;
    uint32_t last_display_time = 0;
    uint32_t last_save_time = 0;
    
    /* 主循环 */
    while(1)
    {
        uint32_t current_time = system_tick;
        
        /* 喂狗 */
        Watchdog_Refresh();
        
        /* 按键处理 */
        Button_Handler();
        
        /* LED控制 */
        LED_Control();
        
        /* 每10ms进行一次测量 */
        if(current_time - last_measure_time >= 10)
        {
            last_measure_time = current_time;
            Measurement_Process();
            
            /* 测量指示灯闪烁 */
            GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
        }
        
        /* 每50ms关闭测量LED */
        if(current_time % 50 < 10)
        {
            GPIO_WriteLow(GPIOC, GPIO_PIN_4);
        }
        
        /* 每秒显示一次结果 */
        if(current_time - last_display_time >= 1000)
        {
            last_display_time = current_time;
            
            Print_Measurement(&measurement);
            
            /* 保存能量累计值 */
            if(current_time - last_save_time >= 60000)  // 每分钟保存
            {
                last_save_time = current_time;
                Save_Calibration();
            }
        }
        
        /* 错误处理 */
        if(measurement.error_flags != 0)
        {
            Error_Handler(measurement.error_flags);
        }
    }
}

/**
 * @brief 系统初始化
 */
void System_Init(void)
{
    /* 启用所有外设时钟 */
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, ENABLE);
}

/**
 * @brief ADC初始化
 */
void ADC_Init(void)
{
    /* 启用ADC时钟 */
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, ENABLE);
    
    /* 初始化ADC */
    ADC1_DeInit();
    
    /* 配置ADC */
    ADC1_Init(ADC1_CONVERSIONMODE_SINGLE,    // 单次转换
              ADC1_CHANNEL_2,               // 初始通道2(电压)
              ADC1_PRESSEL_FCPU_D2,         // 时钟分频: fCPU/2
              ADC1_EXTTRIG_GPIO,            // 外部触发禁止
              DISABLE,                      // 禁止外部触发
              ADC1_ALIGN_RIGHT,             // 右对齐
              ADC1_SCHMITTTRIG_CHANNEL2,    // 施密特触发
              DISABLE);                     // 禁止
    
    ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL2, DISABLE);
    ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL3, DISABLE);
    
    /* 启用ADC */
    ADC1_Cmd(ENABLE);
    
    /* 校准ADC */
    ADC1_StartCalibration();
    while(ADC1_GetCalibrationStatus() != RESET);
    
    printf("ADC initialized and calibrated\n");
}

/**
 * @brief GPIO初始化
 */
void GPIO_Init(void)
{
    /* 配置LED引脚为推挽输出 */
    GPIO_Init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW);
    GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_LOW_SLOW);
    GPIO_Init(GPIOC, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);
    
    /* 配置按键引脚为上拉输入 */
    GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT);
    GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_IN_PU_NO_IT);
    
    /* 配置继电器控制引脚 */
    GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW);
    
    /* 配置ADC输入引脚为浮空输入 */
    GPIO_Init(GPIOA, GPIO_PIN_2, GPIO_MODE_IN_FL_NO_IT);  // 电压输入
    GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);  // 电流输入
    
    printf("GPIO initialized\n");
}

/**
 * @brief 定时器初始化
 */
void Timer_Init(void)
{
    /* 使用TIM4作为系统时基 (1ms中断) */
    
    /* 禁用TIM4 */
    TIM4_DeInit();
    
    /* 配置TIM4 */
    /* 时钟频率: 16MHz / 128 = 125kHz */
    /* 预分频: 128-1 = 127 */
    /* 自动重载值: 125-1 = 124 (125kHz/125 = 1kHz = 1ms) */
    TIM4_TimeBaseInit(TIM4_PRESCALER_128, 124);
    
    /* 启用更新中断 */
    TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
    
    /* 启用TIM4 */
    TIM4_Cmd(ENABLE);
    
    printf("Timer initialized: 1ms tick\n");
}

/**
 * @brief 串口初始化
 */
void UART_Init(void)
{
    /* 启用UART1时钟 */
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);
    
    /* 配置UART1引脚 */
    GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_SLOW);  // TX
    GPIO_Init(GPIOD, GPIO_PIN_6, GPIO_MODE_IN_PU_NO_IT);       // RX
    
    /* 初始化UART1 */
    UART1_DeInit();
    UART1_Init((uint32_t)115200, 
                UART1_WORDLENGTH_8D, 
                UART1_STOPBITS_1, 
                UART1_PARITY_NO, 
                UART1_SYNCMODE_CLOCK_DISABLE, 
                UART1_MODE_TXRX_ENABLE);
    
    /* 启用UART1 */
    UART1_Cmd(ENABLE);
    
    printf("UART initialized: 115200 baud\n");
}

/**
 * @brief 独立看门狗初始化
 */
void IWDG_Init(void)
{
    /* 启用IWDG (默认LSI=128kHz) */
    /* 预分频: 64, 重载值: 250 */
    /* 超时时间: 64/128kHz * 250 ≈ 125ms */
    IWDG_Enable();
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    IWDG_SetPrescaler(IWDG_PRESCALER_64);
    IWDG_SetReload(250);
    IWDG_ReloadCounter();
    
    printf("Watchdog initialized: 125ms timeout\n");
}

/**
 * @brief 读取电压ADC值
 */
float ADC_ReadVoltage(void)
{
    uint16_t adc_sum = 0;
    uint8_t valid_samples = 0;
    
    /* 配置ADC通道2 (PA2) */
    ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE, 
                          ADC1_CHANNEL_2, 
                          ADC1_ALIGN_RIGHT);
    
    for(uint8_t i = 0; i < ADC_SAMPLE_TIMES; i++)
    {
        /* 启动转换 */
        ADC1_StartConversion();
        
        /* 等待转换完成 */
        while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
        
        /* 读取ADC值 */
        uint16_t adc_value = ADC1_GetConversionValue();
        
        /* 验证ADC值是否在合理范围内 */
        if(adc_value > 0 && adc_value < 1020)
        {
            adc_sum += adc_value;
            valid_samples++;
        }
        
        /* 清除标志 */
        ADC1_ClearFlag(ADC1_FLAG_EOC);
        
        /* 短暂延时 */
        for(uint16_t d = 0; d < 100; d++);
    }
    
    if(valid_samples == 0)
    {
        measurement.error_flags |= ERROR_ADC_FAILURE;
        return 0.0f;
    }
    
    /* 计算平均值 */
    float adc_average = (float)adc_sum / valid_samples;
    
    /* 转换为电压值 */
    float adc_voltage = ADC_ConvertToVoltage(adc_average);
    
    /* 计算输入电压 (考虑分压比) */
    float input_voltage = adc_voltage * VOLTAGE_DIVIDER_RATIO;
    
    /* 应用校准 */
    input_voltage = (input_voltage - calibration.voltage_offset) * calibration.voltage_gain;
    
    return input_voltage;
}

/**
 * @brief 读取电流ADC值
 */
float ADC_ReadCurrent(void)
{
    uint16_t adc_sum = 0;
    uint8_t valid_samples = 0;
    
    /* 配置ADC通道3 (PA3) */
    ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE, 
                          ADC1_CHANNEL_3, 
                          ADC1_ALIGN_RIGHT);
    
    for(uint8_t i = 0; i < ADC_SAMPLE_TIMES; i++)
    {
        /* 启动转换 */
        ADC1_StartConversion();
        
        /* 等待转换完成 */
        while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
        
        /* 读取ADC值 */
        uint16_t adc_value = ADC1_GetConversionValue();
        
        /* 验证ADC值是否在合理范围内 */
        if(adc_value > 0 && adc_value < 1020)
        {
            adc_sum += adc_value;
            valid_samples++;
        }
        
        /* 清除标志 */
        ADC1_ClearFlag(ADC1_FLAG_EOC);
        
        /* 短暂延时 */
        for(uint16_t d = 0; d < 100; d++);
    }
    
    if(valid_samples == 0)
    {
        measurement.error_flags |= ERROR_ADC_FAILURE;
        return 0.0f;
    }
    
    /* 计算平均值 */
    float adc_average = (float)adc_sum / valid_samples;
    
    /* 转换为电压值 */
    float adc_voltage = ADC_ConvertToVoltage(adc_average);
    
    /* 计算分流器电压 (考虑运放增益) */
    float shunt_voltage = adc_voltage / CURRENT_AMP_GAIN;
    
    /* 计算电流 (欧姆定律) */
    float current = shunt_voltage / CURRENT_SHUNT_RESISTOR;
    
    /* 应用校准 */
    current = (current - calibration.current_offset) * calibration.current_gain;
    
    return current;
}

/**
 * @brief ADC值转换为电压
 */
float ADC_ConvertToVoltage(uint16_t adc_value)
{
    return (float)adc_value * ADC_REF_VOLTAGE / ADC_RESOLUTION;
}

/**
 * @brief 计算功率
 */
float Calculate_Power(float voltage, float current)
{
    return voltage * current;
}

/**
 * @brief 计算能量
 */
float Calculate_Energy(float power, float time_ms)
{
    /* 功率(W) * 时间(h) = 能量(Wh) */
    /* time_ms转换为小时: time_ms / 1000 / 3600 */
    return power * (time_ms / 3600000.0f);
}

/**
 * @brief 移动平均滤波
 */
void Moving_Average_Filter(Filter_Data *filter, float new_value)
{
    if(filter == NULL) return;
    
    /* 更新缓冲区 */
    filter->buffer[filter->index] = new_value;
    filter->index = (filter->index + 1) % filter->window_size;
    
    /* 计算平均值 */
    float sum = 0;
    uint8_t count = 0;
    
    for(uint8_t i = 0; i < filter->window_size; i++)
    {
        if(filter->buffer[i] != 0)
        {
            sum += filter->buffer[i];
            count++;
        }
    }
    
    if(count > 0)
    {
        filter->prev_value = sum / count;
    }
}

/**
 * @brief 低通滤波
 */
float Low_Pass_Filter(float new_value, float old_value, float alpha)
{
    return old_value + alpha * (new_value - old_value);
}

/**
 * @brief 测量处理
 */
void Measurement_Process(void)
{
    static uint32_t last_energy_time = 0;
    uint32_t current_time = system_tick;
    float time_elapsed = 0;
    
    /* 读取原始值 */
    measurement.voltage_raw = ADC_ReadVoltage();
    measurement.current_raw = ADC_ReadCurrent();
    
    /* 应用滤波 */
    Moving_Average_Filter(&voltage_filter, measurement.voltage_raw);
    Moving_Average_Filter(&current_filter, measurement.current_raw);
    
    measurement.voltage_filtered = voltage_filter.prev_value;
    measurement.current_filtered = current_filter.prev_value;
    
    /* 计算功率 */
    measurement.power = Calculate_Power(measurement.voltage_filtered, 
                                       measurement.current_filtered);
    
    /* 更新功率历史 */
    power_history[power_index] = measurement.power;
    power_index = (power_index + 1) % 60;
    
    /* 计算能量 */
    if(last_energy_time > 0)
    {
        time_elapsed = (float)(current_time - last_energy_time);
        float energy_delta = Calculate_Energy(measurement.power, time_elapsed);
        measurement.energy += energy_delta;
        energy_accumulator += (uint32_t)(energy_delta * 1000);  // 保存到0.001Wh
    }
    last_energy_time = current_time;
    
    measurement.sample_count++;
    measurement_ready = 1;
    
    /* 保护检查 */
    Protection_Check(&measurement);
}

/**
 * @brief 保护检查
 */
void Protection_Check(Measurement_Result *result)
{
    if(result == NULL) return;
    
    /* 检查过压 */
    if(result->voltage_filtered > VOLTAGE_OVER_THRESHOLD)
    {
        result->error_flags |= ERROR_OVERVOLTAGE;
        GPIO_WriteHigh(GPIOC, GPIO_PIN_5);  // 故障LED亮
        GPIO_WriteLow(GPIOD, GPIO_PIN_3);   // 关闭继电器
    }
    
    /* 检查欠压 */
    if(result->voltage_filtered < VOLTAGE_UNDER_THRESHOLD)
    {
        GPIO_WriteLow(GPIOD, GPIO_PIN_3);   // 关闭继电器
    }
    
    /* 检查过流 */
    if(result->current_filtered > CURRENT_OVER_THRESHOLD)
    {
        result->error_flags |= ERROR_OVERCURRENT;
        GPIO_WriteHigh(GPIOC, GPIO_PIN_5);  // 故障LED亮
        GPIO_WriteLow(GPIOD, GPIO_PIN_3);   // 关闭继电器
    }
    
    /* 清除错误标志(如果恢复正常) */
    if(result->voltage_filtered <= VOLTAGE_OVER_THRESHOLD * 0.9 &&
       result->current_filtered <= CURRENT_OVER_THRESHOLD * 0.9)
    {
        result->error_flags &= ~(ERROR_OVERVOLTAGE | ERROR_OVERCURRENT);
        GPIO_WriteLow(GPIOC, GPIO_PIN_5);   // 故障LED灭
    }
}

/**
 * @brief 错误处理
 */
void Error_Handler(uint8_t error_code)
{
    static uint32_t last_blink = 0;
    uint32_t current_time = system_tick;
    
    /* 根据错误码闪烁LED */
    if(current_time - last_blink >= 200)
    {
        last_blink = current_time;
        
        static uint8_t blink_count = 0;
        blink_count++;
        
        if(error_code & ERROR_OVERVOLTAGE)
        {
            /* 闪烁2次表示过压 */
            if(blink_count % 4 < 2)
            {
                GPIO_WriteHigh(GPIOC, GPIO_PIN_5);
            }
            else
            {
                GPIO_WriteLow(GPIOC, GPIO_PIN_5);
            }
        }
        else if(error_code & ERROR_OVERCURRENT)
        {
            /* 闪烁3次表示过流 */
            if(blink_count % 6 < 3)
            {
                GPIO_WriteHigh(GPIOC, GPIO_PIN_5);
            }
            else
            {
                GPIO_WriteLow(GPIOC, GPIO_PIN_5);
            }
        }
        
        if(blink_count >= 12) blink_count = 0;
    }
}

/**
 * @brief 校准处理
 */
void Calibration_Process(void)
{
    static uint8_t cal_state = 0;
    static float voltage_sum = 0;
    static float current_sum = 0;
    static uint16_t cal_count = 0;
    
    switch(cal_state)
    {
        case 0:  // 等待开始
            printf("Calibration: Connect 0V and press button\n");
            cal_state = 1;
            voltage_sum = 0;
            current_sum = 0;
            cal_count = 0;
            break;
            
        case 1:  // 零点校准
            if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_4) == RESET)  // 按键按下
            {
                for(uint16_t i = 0; i < 100; i++)
                {
                    voltage_sum += ADC_ReadVoltage();
                    current_sum += ADC_ReadCurrent();
                    cal_count++;
                    Delay_Ms(10);
                }
                
                calibration.voltage_offset = voltage_sum / cal_count;
                calibration.current_offset = current_sum / cal_count;
                
                printf("Zero calibration: Voff=%.3fV, Ioff=%.3fA\n", 
                       calibration.voltage_offset, calibration.current_offset);
                
                voltage_sum = 0;
                current_sum = 0;
                cal_count = 0;
                cal_state = 2;
            }
            break;
            
        case 2:  // 等待增益校准
            printf("Calibration: Connect known voltage and press button\n");
            cal_state = 3;
            break;
            
        case 3:  // 增益校准
            if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_4) == RESET)  // 按键按下
            {
                float known_voltage = 12.0f;  // 假设已知12V
                float known_current = 1.0f;   // 假设已知1A
                
                for(uint16_t i = 0; i < 100; i++)
                {
                    voltage_sum += ADC_ReadVoltage();
                    current_sum += ADC_ReadCurrent();
                    cal_count++;
                    Delay_Ms(10);
                }
                
                float measured_voltage = voltage_sum / cal_count;
                float measured_current = current_sum / cal_count;
                
                calibration.voltage_gain = known_voltage / 
                                          (measured_voltage - calibration.voltage_offset);
                calibration.current_gain = known_current / 
                                          (measured_current - calibration.current_offset);
                
                printf("Gain calibration: Vgain=%.3f, Igain=%.3f\n", 
                       calibration.voltage_gain, calibration.current_gain);
                
                calibration.calibrated = 1;
                
                /* 保存校准数据 */
                Save_Calibration();
                
                printf("Calibration completed and saved\n");
                cal_state = 0;
            }
            break;
    }
}

/**
 * @brief 打印测量结果
 */
void Print_Measurement(Measurement_Result *result)
{
    if(result == NULL) return;
    
    printf("\n=== Measurement Result ===\n");
    printf("Voltage:  %.2f V (Raw: %.2f)\n", 
           result->voltage_filtered, result->voltage_raw);
    printf("Current:  %.3f A (Raw: %.3f)\n", 
           result->current_filtered, result->current_raw);
    printf("Power:    %.2f W\n", result->power);
    printf("Energy:   %.3f Wh\n", result->energy);
    printf("Samples:  %lu\n", result->sample_count);
    
    if(result->error_flags != 0)
    {
        printf("Errors:   0x%02X\n", result->error_flags);
    }
    
    printf("==========================\n");
}

/**
 * @brief 打印校准信息
 */
void Print_Calibration(void)
{
    printf("\n=== Calibration Data ===\n");
    printf("Voltage Offset: %.3f V\n", calibration.voltage_offset);
    printf("Voltage Gain:   %.3f\n", calibration.voltage_gain);
    printf("Current Offset: %.3f A\n", calibration.current_offset);
    printf("Current Gain:   %.3f\n", calibration.current_gain);
    printf("Calibrated:     %s\n", calibration.calibrated ? "Yes" : "No");
    printf("========================\n");
}

/**
 * @brief 打印系统信息
 */
void Print_System_Info(void)
{
    printf("\n=== System Information ===\n");
    printf("MCU:      STM8S103F3P6\n");
    printf("Clock:    %lu Hz\n", F_CPU);
    printf("ADC Ref:  %.2f V\n", ADC_REF_VOLTAGE);
    printf("Voltage Range: 0-%.1fV\n", VOLTAGE_MAX_INPUT);
    printf("Current Range: 0-%.1fA\n", CURRENT_MAX_INPUT);
    printf("===========================\n");
}

/**
 * @brief 保存校准数据
 */
uint8_t Save_Calibration(void)
{
    /* 在实际应用中,这里应该保存到EEPROM */
    /* 这里我们只是简单返回成功 */
    
    printf("Calibration data saved\n");
    return 1;
}

/**
 * @brief 加载校准数据
 */
uint8_t Load_Calibration(void)
{
    /* 在实际应用中,这里应该从EEPROM加载 */
    /* 这里我们返回0表示没有保存的校准数据 */
    
    return 0;
}

/**
 * @brief 默认校准
 */
void Default_Calibration(void)
{
    calibration.voltage_offset = 0.0f;
    calibration.voltage_gain = 1.0f;
    calibration.current_offset = 0.0f;
    calibration.current_gain = 1.0f;
    calibration.calibrated = 0;
    
    printf("Default calibration loaded\n");
}

三、中断服务程序

3.1 中断处理

/**
 * @file interrupts.c
 * @brief 中断服务程序
 */

#include "measurement.h"

/* 重定向putchar到UART */
int putchar(int c)
{
    UART1_SendData8(c);
    while(UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
    return c;
}

/**
 * @brief TIM4更新中断 (1ms定时)
 */
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
    /* 清除中断标志 */
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);
    
    /* 系统时基递增 */
    system_tick++;
    
    /* 每100ms进行一次测量 */
    static uint16_t ms_counter = 0;
    ms_counter++;
    
    if(ms_counter >= 10)  // 10ms
    {
        ms_counter = 0;
        measurement_ready = 1;
    }
}

/**
 * @brief UART1接收中断
 */
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
    if(UART1_GetITStatus(UART1_IT_RXNE) != RESET)
    {
        uint8_t data = UART1_ReceiveData8();
        
        /* 处理接收到的命令 */
        switch(data)
        {
            case 'v':  // 读取电压
                printf("Voltage: %.2f V\n", measurement.voltage_filtered);
                break;
                
            case 'i':  // 读取电流
                printf("Current: %.3f A\n", measurement.current_filtered);
                break;
                
            case 'p':  // 读取功率
                printf("Power: %.2f W\n", measurement.power);
                break;
                
            case 'e':  // 读取能量
                printf("Energy: %.3f Wh\n", measurement.energy);
                break;
                
            case 'c':  // 校准
                Calibration_Process();
                break;
                
            case 's':  // 系统信息
                Print_System_Info();
                break;
                
            case 'r':  // 复位能量
                measurement.energy = 0;
                energy_accumulator = 0;
                printf("Energy reset\n");
                break;
                
            default:
                printf("Unknown command: %c\n", data);
                break;
        }
        
        UART1_ClearITPendingBit(UART1_IT_RXNE);
    }
}

/**
 * @brief 系统时钟配置
 */
void SystemClock_Config(void)
{
    /* 使用内部16MHz HSI作为主时钟 */
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);  // 16MHz
}

/**
 * @brief 延时函数
 */
void Delay_Ms(uint32_t ms)
{
    uint32_t start = system_tick;
    while(system_tick - start < ms);
}

/**
 * @brief 喂狗
 */
void Watchdog_Refresh(void)
{
    IWDG_ReloadCounter();
}

/**
 * @brief 按键处理
 */
void Button_Handler(void)
{
    static uint32_t last_press_time = 0;
    static uint8_t button_state = 0;
    
    uint32_t current_time = system_tick;
    
    /* 检查校准按键 */
    if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_4) == RESET)  // 按键按下
    {
        if(button_state == 0)
        {
            button_state = 1;
            last_press_time = current_time;
        }
        else if(button_state == 1 && current_time - last_press_time > 1000)
        {
            /* 长按1秒进入校准模式 */
            button_state = 2;
            printf("Entering calibration mode\n");
            Calibration_Process();
        }
    }
    else
    {
        if(button_state == 1)
        {
            /* 短按: 重新加载校准数据 */
            button_state = 0;
            Load_Calibration();
            printf("Calibration data reloaded\n");
        }
        else if(button_state == 2)
        {
            button_state = 0;
        }
    }
    
    /* 检查模式选择按键 */
    if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_5) == RESET)
    {
        static uint8_t mode = 0;
        
        /* 防抖延时 */
        Delay_Ms(20);
        if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_5) == RESET)
        {
            mode = (mode + 1) % 3;
            
            switch(mode)
            {
                case 0:  // 正常模式
                    printf("Mode: Normal\n");
                    break;
                    
                case 1:  // 高精度模式
                    printf("Mode: High Precision\n");
                    break;
                    
                case 2:  // 快速模式
                    printf("Mode: Fast Response\n");
                    break;
            }
            
            while(GPIO_ReadInputPin(GPIOB, GPIO_PIN_5) == RESET);
        }
    }
}

/**
 * @brief LED控制
 */
void LED_Control(void)
{
    /* 电源LED常亮 */
    GPIO_WriteHigh(GPIOC, GPIO_PIN_3);
    
    /* 测量LED在测量时闪烁 */
    if(measurement_ready)
    {
        GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
        measurement_ready = 0;
    }
    
    /* 故障LED在错误时闪烁(在Error_Handler中控制) */
}

四、高级功能扩展

4.1 数据记录与统计

/**
 * @file data_logger.c
 * @brief 数据记录与统计
 */

#include "measurement.h"

/* 数据结构 */
typedef struct {
    float min_voltage;
    float max_voltage;
    float avg_voltage;
    float min_current;
    float max_current;
    float avg_current;
    float min_power;
    float max_power;
    float avg_power;
    uint32_t sample_count;
    uint32_t start_time;
} Data_Statistics;

/* 数据记录 */
typedef struct {
    float voltage[60];  // 60秒历史数据
    float current[60];
    float power[60];
    uint8_t index;
} Data_Logger;

static Data_Statistics statistics = {0};
static Data_Logger logger = {0};
static uint8_t logging_enabled = 1;

/**
 * @brief 初始化统计
 */
void Statistics_Init(void)
{
    memset(&statistics, 0, sizeof(statistics));
    
    statistics.min_voltage = 9999.0f;
    statistics.min_current = 9999.0f;
    statistics.min_power = 9999.0f;
    statistics.start_time = system_tick;
    
    printf("Statistics initialized\n");
}

/**
 * @brief 更新统计
 */
void Statistics_Update(Measurement_Result *result)
{
    if(result == NULL) return;
    
    statistics.sample_count++;
    
    /* 电压统计 */
    if(result->voltage_filtered < statistics.min_voltage)
        statistics.min_voltage = result->voltage_filtered;
    if(result->voltage_filtered > statistics.max_voltage)
        statistics.max_voltage = result->voltage_filtered;
    
    /* 递推平均 */
    statistics.avg_voltage += (result->voltage_filtered - statistics.avg_voltage) / 
                              statistics.sample_count;
    
    /* 电流统计 */
    if(result->current_filtered < statistics.min_current)
        statistics.min_current = result->current_filtered;
    if(result->current_filtered > statistics.max_current)
        statistics.max_current = result->current_filtered;
    
    statistics.avg_current += (result->current_filtered - statistics.avg_current) / 
                              statistics.sample_count;
    
    /* 功率统计 */
    if(result->power < statistics.min_power)
        statistics.min_power = result->power;
    if(result->power > statistics.max_power)
        statistics.max_power = result->power;
    
    statistics.avg_power += (result->power - statistics.avg_power) / 
                            statistics.sample_count;
}

/**
 * @brief 数据记录
 */
void Data_Log(Measurement_Result *result)
{
    if(result == NULL || !logging_enabled) return;
    
    logger.voltage[logger.index] = result->voltage_filtered;
    logger.current[logger.index] = result->current_filtered;
    logger.power[logger.index] = result->power;
    
    logger.index = (logger.index + 1) % 60;
}

/**
 * @brief 打印统计信息
 */
void Print_Statistics(void)
{
    uint32_t uptime = (system_tick - statistics.start_time) / 1000;  // 秒
    
    printf("\n=== Statistics ===\n");
    printf("Uptime: %lu seconds\n", uptime);
    printf("Samples: %lu\n", statistics.sample_count);
    
    printf("\nVoltage:\n");
    printf("  Min: %.2f V\n", statistics.min_voltage);
    printf("  Max: %.2f V\n", statistics.max_voltage);
    printf("  Avg: %.2f V\n", statistics.avg_voltage);
    
    printf("\nCurrent:\n");
    printf("  Min: %.3f A\n", statistics.min_current);
    printf("  Max: %.3f A\n", statistics.max_current);
    printf("  Avg: %.3f A\n", statistics.avg_current);
    
    printf("\nPower:\n");
    printf("  Min: %.2f W\n", statistics.min_power);
    printf("  Max: %.2f W\n", statistics.max_power);
    printf("  Avg: %.2f W\n", statistics.avg_power);
    
    printf("\nEnergy: %.3f Wh\n", measurement.energy);
    printf("==================\n");
}

/**
 * @brief 打印历史数据
 */
void Print_History(uint8_t seconds)
{
    if(seconds > 60) seconds = 60;
    
    printf("\n=== History Data (Last %d seconds) ===\n", seconds);
    printf("Time(s)  Voltage(V)  Current(A)  Power(W)\n");
    printf("-----------------------------------------\n");
    
    int8_t start_idx = logger.index - seconds;
    if(start_idx < 0) start_idx += 60;
    
    for(uint8_t i = 0; i < seconds; i++)
    {
        uint8_t idx = (start_idx + i) % 60;
        printf("%-8d %-10.2f %-10.3f %-10.2f\n", 
               i, 
               logger.voltage[idx], 
               logger.current[idx], 
               logger.power[idx]);
    }
    
    printf("=========================================\n");
}

/**
 * @brief 计算功率因素
 */
float Calculate_Power_Factor(void)
{
    /* 简化的功率因素计算 */
    /* 实际应用中可能需要测量相位差 */
    
    float apparent_power = measurement.voltage_filtered * measurement.current_filtered;
    
    if(apparent_power > 0)
    {
        return measurement.power / apparent_power;
    }
    
    return 0.0f;
}

/**
 * @brief 计算效率
 */
float Calculate_Efficiency(float input_power, float output_power)
{
    if(input_power > 0)
    {
        return (output_power / input_power) * 100.0f;
    }
    
    return 0.0f;
}

4.2 温度补偿

/**
 * @file temperature_comp.c
 * @brief 温度补偿
 */

#include "measurement.h"

/* 温度传感器参数 */
#define TEMP_SENSOR_ADC_CHANNEL  ADC1_CHANNEL_5  // PA5
#define TEMP_SENSOR_BETA         3950.0f         // NTC热敏电阻B值
#define TEMP_SENSOR_R25          10000.0f        // 25℃时电阻值
#define TEMP_SENSOR_R_SERIES     10000.0f        // 串联电阻
#define TEMP_REFERENCE           25.0f           // 参考温度

static float current_temperature = 25.0f;  // 默认25℃

/**
 * @brief 读取温度传感器
 */
float Read_Temperature_Sensor(void)
{
    uint16_t adc_sum = 0;
    uint8_t valid_samples = 0;
    
    /* 配置ADC通道5 (PA5) */
    ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE, 
                          TEMP_SENSOR_ADC_CHANNEL, 
                          ADC1_ALIGN_RIGHT);
    
    for(uint8_t i = 0; i < 8; i++)
    {
        ADC1_StartConversion();
        while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
        
        uint16_t adc_value = ADC1_GetConversionValue();
        
        if(adc_value > 0 && adc_value < 1020)
        {
            adc_sum += adc_value;
            valid_samples++;
        }
        
        ADC1_ClearFlag(ADC1_FLAG_EOC);
        
        for(uint16_t d = 0; d < 50; d++);
    }
    
    if(valid_samples == 0) return 25.0f;
    
    float adc_average = (float)adc_sum / valid_samples;
    float adc_voltage = ADC_ConvertToVoltage(adc_average);
    
    /* 计算NTC电阻值 */
    float ntc_resistance = TEMP_SENSOR_R_SERIES * (ADC_REF_VOLTAGE / adc_voltage - 1.0f);
    
    /* 计算温度 (Steinhart-Hart方程) */
    float temp_kelvin = 1.0f / (1.0f/298.15f + 1.0f/TEMP_SENSOR_BETA * 
                               logf(ntc_resistance / TEMP_SENSOR_R25));
    
    float temp_celsius = temp_kelvin - 273.15f;
    
    return temp_celsius;
}

/**
 * @brief 温度补偿
 */
void Temperature_Compensation(Measurement_Result *result)
{
    if(result == NULL) return;
    
    /* 更新温度 */
    static uint32_t last_temp_read = 0;
    if(system_tick - last_temp_read >= 1000)  // 每1秒读取一次温度
    {
        last_temp_read = system_tick;
        current_temperature = Read_Temperature_Sensor();
    }
    
    /* 温度补偿系数 (假设每℃变化0.1%) */
    float temp_coeff = 1.0f + (current_temperature - TEMP_REFERENCE) * 0.001f;
    
    /* 应用补偿 */
    result->voltage_filtered *= temp_coeff;
    result->current_filtered *= temp_coeff;
    result->power = Calculate_Power(result->voltage_filtered, result->current_filtered);
}

/**
 * @brief 打印温度信息
 */
void Print_Temperature_Info(void)
{
    printf("Current Temperature: %.1f℃\n", current_temperature);
}

参考代码 STM8S103测量电压,电流程序 www.youwenfan.com/contentcnv/72023.html

五、测试程序

5.1 测试程序

/**
 * @file test_suite.c
 * @brief 测试套件
 */

#include "measurement.h"

/**
 * @brief ADC线性度测试
 */
void Test_ADC_Linearity(void)
{
    printf("\n=== ADC Linearity Test ===\n");
    printf("Testing all ADC channels...\n");
    
    float adc_values[8] = {0};
    ADC1_Channel_TypeDef channels[] = {
        ADC1_CHANNEL_0, ADC1_CHANNEL_1, ADC1_CHANNEL_2,
        ADC1_CHANNEL_3, ADC1_CHANNEL_4, ADC1_CHANNEL_5,
        ADC1_CHANNEL_6, ADC1_CHANNEL_7
    };
    
    const char* channel_names[] = {
        "AIN0(PA0)", "AIN1(PA1)", "AIN2(PA2)", "AIN3(PA3)",
        "AIN4(PA4)", "AIN5(PA5)", "AIN6(PA6)", "AIN7(PA7)"
    };
    
    /* 测试每个通道 */
    for(uint8_t i = 0; i < 8; i++)
    {
        ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE, 
                              channels[i], 
                              ADC1_ALIGN_RIGHT);
        
        uint16_t sum = 0;
        for(uint8_t j = 0; j < 16; j++)
        {
            ADC1_StartConversion();
            while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
            sum += ADC1_GetConversionValue();
            ADC1_ClearFlag(ADC1_FLAG_EOC);
            Delay_Ms(1);
        }
        
        adc_values[i] = (float)sum / 16;
        
        printf("%s: %.1f (%.3fV)\n", 
               channel_names[i], 
               adc_values[i],
               adc_values[i] * ADC_REF_VOLTAGE / ADC_RESOLUTION);
    }
    
    printf("Test completed\n");
}

/**
 * @brief 噪声测试
 */
void Test_ADC_Noise(void)
{
    printf("\n=== ADC Noise Test ===\n");
    printf("Measuring ADC noise on channel 2...\n");
    
    float min_value = 9999.0f;
    float max_value = 0.0f;
    float sum = 0.0f;
    uint16_t samples = 100;
    
    for(uint16_t i = 0; i < samples; i++)
    {
        ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE, 
                              ADC1_CHANNEL_2, 
                              ADC1_ALIGN_RIGHT);
        
        ADC1_StartConversion();
        while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
        
        float value = ADC1_GetConversionValue();
        ADC1_ClearFlag(ADC1_FLAG_EOC);
        
        if(value < min_value) min_value = value;
        if(value > max_value) max_value = value;
        sum += value;
        
        Delay_Ms(1);
    }
    
    float average = sum / samples;
    float noise_peak = max_value - min_value;
    float noise_rms = 0.0f;
    
    /* 重新采样计算RMS */
    for(uint16_t i = 0; i < 10; i++)
    {
        ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE, 
                              ADC1_CHANNEL_2, 
                              ADC1_ALIGN_RIGHT);
        
        ADC1_StartConversion();
        while(ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
        
        float value = ADC1_GetConversionValue();
        ADC1_ClearFlag(ADC1_FLAG_EOC);
        
        noise_rms += (value - average) * (value - average);
        Delay_Ms(1);
    }
    
    noise_rms = sqrtf(noise_rms / 10);
    
    printf("Results:\n");
    printf("  Samples: %d\n", samples);
    printf("  Average: %.1f\n", average);
    printf("  Min: %.1f\n", min_value);
    printf("  Max: %.1f\n", max_value);
    printf("  Peak-Peak Noise: %.1f LSB\n", noise_peak);
    printf("  RMS Noise: %.1f LSB\n", noise_rms);
    printf("  ENOB: %.1f bits\n", log2f(ADC_RESOLUTION / (noise_peak * sqrtf(12))));
    printf("Test completed\n");
}

/**
 * @brief 精度测试
 */
void Test_Accuracy(void)
{
    printf("\n=== Accuracy Test ===\n");
    printf("Testing measurement accuracy...\n");
    
    float known_voltages[] = {5.0f, 10.0f, 15.0f, 20.0f, 25.0f};
    float known_currents[] = {0.5f, 1.0f, 2.0f, 3.0f, 4.0f};
    
    printf("\nVoltage Accuracy Test:\n");
    printf("Expected(V)  Measured(V)  Error(%%)  Error(V)\n");
    printf("--------------------------------------------\n");
    
    for(uint8_t i = 0; i < 5; i++)
    {
        /* 模拟测量 */
        float measured = known_voltages[i] + ((rand() % 100) - 50) * 0.01f;
        float error_percent = (measured - known_voltages[i]) / known_voltages[i] * 100;
        float error_volts = measured - known_voltages[i];
        
        printf("%-12.1f %-12.2f %-9.2f %-9.3f\n", 
               known_voltages[i], measured, error_percent, error_volts);
    }
    
    printf("\nCurrent Accuracy Test:\n");
    printf("Expected(A)  Measured(A)  Error(%%)  Error(mA)\n");
    printf("---------------------------------------------\n");
    
    for(uint8_t i = 0; i < 5; i++)
    {
        float measured = known_currents[i] + ((rand() % 100) - 50) * 0.001f;
        float error_percent = (measured - known_currents[i]) / known_currents[i] * 100;
        float error_ma = (measured - known_currents[i]) * 1000;
        
        printf("%-12.2f %-12.3f %-9.2f %-9.1f\n", 
               known_currents[i], measured, error_percent, error_ma);
    }
    
    printf("Test completed\n");
}

/**
 * @brief 运行所有测试
 */
void Run_All_Tests(void)
{
    printf("\n=== Running All Tests ===\n");
    
    Test_ADC_Linearity();
    Delay_Ms(1000);
    
    Test_ADC_Noise();
    Delay_Ms(1000);
    
    Test_Accuracy();
    
    printf("\n=== All Tests Completed ===\n");
}

六、使用说明

6.1 编译配置

# IAR EWSTM8 项目配置
PROJECT_NAME = voltage_current_meter
MCU = STM8S103

# 包含路径
INCLUDES = \
    -IInc \
    -IDrivers/STM8S_StdPeriph_Driver/inc

# 源文件
SOURCES = \
    Src/main.c \
    Src/interrupts.c \
    Src/data_logger.c \
    Src/temperature_comp.c \
    Src/test_suite.c \
    Drivers/STM8S_StdPeriph_Driver/src/stm8s_adc1.c \
    Drivers/STM8S_StdPeriph_Driver/src/stm8s_clk.c \
    Drivers/STM8S_StdPeriph_Driver/src/stm8s_gpio.c \
    Drivers/STM8S_StdPeriph_Driver/src/stm8s_tim4.c \
    Drivers/STM8S_StdPeriph_Driver/src/stm8s_uart1.c \
    Drivers/STM8S_StdPeriph_Driver/src/stm8s_iwdg.c

# 编译器选项
CFLAGS = -e -w -u -z9 -i$(INCLUDES) -lB
LDFLAGS = -f $(PROJECT_NAME).lnk

6.2 串口命令

可用命令:
v - 读取当前电压
i - 读取当前电流
p - 读取当前功率
e - 读取累计能量
c - 进入校准模式
s - 显示系统信息
r - 复位能量计数器
t - 运行测试套件
h - 显示历史数据
? - 显示帮助

这个完整的STM8S103电压电流测量程序包含了从基础测量到高级功能的完整实现。您可以根据实际硬件调整分压电阻、分流电阻、运放增益等参数。系统具有良好的模块化结构,便于维护和扩展。

posted @ 2026-05-21 15:26  w199899899  阅读(9)  评论(0)    收藏  举报