基于51单片机的三相不平衡度计算程序

基于51单片机的三相不平衡度计算程序

一、系统设计概述

1.1 功能描述

本程序在51单片机平台上实现三相电压/电流的不平衡度计算,包括:

1.2 硬件连接

51单片机 (如STC89C52)
├── ADC接口 (ADC0804/ADS1115) → 三相电压/电流采样
├── LCD1602/12864 → 结果显示
├── 矩阵键盘 → 参数设置
├── RS485/RS232 → 与上位机通信
└── 蜂鸣器 → 越限报警

二、核心算法实现

2.1 三相不平衡度计算公式

2.1.1 对称分量法

对于三相系统 ,对称分量计算如下:

正序分量

负序分量

零序分量

其中旋转因子

2.1.2 不平衡度定义

负序不平衡度

零序不平衡度

三、51单片机C语言实现

3.1 数据类型定义

/**
 * @file three_phase_unbalance.c
 * @brief 三相不平衡度计算程序(51单片机平台)
 */

#include <reg52.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

/* 复数结构体定义 */
typedef struct {
    float real;     // 实部
    float imag;     // 虚部
} Complex;

/* 三相电压结构体 */
typedef struct {
    Complex Ua;     // A相电压
    Complex Ub;     // B相电压
    Complex Uc;     // C相电压
} ThreePhaseVoltage;

/* 不平衡度结果结构体 */
typedef struct {
    float unbalance_negative;   // 负序不平衡度(%)
    float unbalance_zero;       // 零序不平衡度(%)
    Complex U1;                 // 正序分量
    Complex U2;                 // 负序分量
    Complex U0;                 // 零序分量
} UnbalanceResult;

/* 旋转因子定义 */
#define A_REAL  -0.5f           // a = -0.5 + j0.866
#define A_IMAG   0.8660254f     // √3/2
#define A2_REAL -0.5f           // a² = -0.5 - j0.866
#define A2_IMAG -0.8660254f

3.2 对称分量计算函数

/**
 * @brief 计算三相电压的对称分量
 * @param voltage 三相电压
 * @param result 存储计算结果
 */
void calculate_symmetric_components(ThreePhaseVoltage *voltage, 
                                    UnbalanceResult *result)
{
    Complex a, a2;      // 旋转因子a和a²
    Complex temp;
    
    /* 初始化旋转因子 */
    a.real = A_REAL;
    a.imag = A_IMAG;
    a2.real = A2_REAL;
    a2.imag = A2_IMAG;
    
    /* 计算a*Ub */
    complex_multiply(&(voltage->Ub), &a, &temp);
    
    /* 计算a²*Uc */
    complex_multiply(&(voltage->Uc), &a2, &temp);
    
    /* 1. 计算正序分量 U1 = (Ua + a*Ub + a²*Uc) / 3 */
    result->U1.real = voltage->Ua.real;
    result->U1.imag = voltage->Ua.imag;
    
    // 加上 a*Ub
    complex_multiply(&(voltage->Ub), &a, &temp);
    result->U1.real += temp.real;
    result->U1.imag += temp.imag;
    
    // 加上 a²*Uc
    complex_multiply(&(voltage->Uc), &a2, &temp);
    result->U1.real += temp.real;
    result->U1.imag += temp.imag;
    
    // 除以3
    result->U1.real /= 3.0f;
    result->U1.imag /= 3.0f;
    
    /* 2. 计算负序分量 U2 = (Ua + a²*Ub + a*Uc) / 3 */
    result->U2.real = voltage->Ua.real;
    result->U2.imag = voltage->Ua.imag;
    
    // 加上 a²*Ub
    complex_multiply(&(voltage->Ub), &a2, &temp);
    result->U2.real += temp.real;
    result->U2.imag += temp.imag;
    
    // 加上 a*Uc
    complex_multiply(&(voltage->Uc), &a, &temp);
    result->U2.real += temp.real;
    result->U2.imag += temp.imag;
    
    // 除以3
    result->U2.real /= 3.0f;
    result->U2.imag /= 3.0f;
    
    /* 3. 计算零序分量 U0 = (Ua + Ub + Uc) / 3 */
    result->U0.real = voltage->Ua.real + voltage->Ub.real + voltage->Uc.real;
    result->U0.imag = voltage->Ua.imag + voltage->Ub.imag + voltage->Uc.imag;
    result->U0.real /= 3.0f;
    result->U0.imag /= 3.0f;
    
    /* 4. 计算不平衡度 */
    float mag_U1 = complex_magnitude(&(result->U1));
    float mag_U2 = complex_magnitude(&(result->U2));
    float mag_U0 = complex_magnitude(&(result->U0));
    
    if(mag_U1 > 0.001f)  // 避免除零
    {
        result->unbalance_negative = (mag_U2 / mag_U1) * 100.0f;
        result->unbalance_zero = (mag_U0 / mag_U1) * 100.0f;
    }
    else
    {
        result->unbalance_negative = 0.0f;
        result->unbalance_zero = 0.0f;
    }
}

3.3 复数运算支持函数

/**
 * @brief 复数乘法
 * @param a 复数a
 * @param b 复数b
 * @param result 结果
 */
void complex_multiply(Complex *a, Complex *b, Complex *result)
{
    result->real = a->real * b->real - a->imag * b->imag;
    result->imag = a->real * b->imag + a->imag * b->real;
}

/**
 * @brief 计算复数幅度
 * @param c 复数
 * @return 幅度值
 */
float complex_magnitude(Complex *c)
{
    return sqrt(c->real * c->real + c->imag * c->imag);
}

/**
 * @brief 计算复数相位角(度)
 * @param c 复数
 * @return 相位角(-180° ~ 180°)
 */
float complex_phase(Complex *c)
{
    if(c->real == 0.0f && c->imag == 0.0f)
        return 0.0f;
    
    float angle = atan2(c->imag, c->real) * 180.0f / 3.1415926f;
    
    /* 归一化到-180°~180° */
    if(angle > 180.0f) angle -= 360.0f;
    if(angle < -180.0f) angle += 360.0f;
    
    return angle;
}

3.4 数据处理模块

/* 全局变量定义 */
#define SAMPLE_POINTS 128       // 每周期采样点数
#define NUM_PHASES    3         // 三相

float voltage_samples[NUM_PHASES][SAMPLE_POINTS];  // 电压采样值
float current_samples[NUM_PHASES][SAMPLE_PHASES];  // 电流采样值
float frequency = 50.0f;                           // 电网频率(Hz)

/**
 * @brief 从采样值计算相量(幅值和相位)
 * @param samples 采样数组
 * @param amplitude 幅值
 * @param phase 相位(度)
 */
void calculate_phasor(float samples[], float *amplitude, float *phase)
{
    float sum_real = 0.0f;
    float sum_imag = 0.0f;
    int i;
    
    /* 使用DFT计算基波分量 */
    for(i = 0; i < SAMPLE_POINTS; i++)
    {
        float angle = 2.0f * 3.1415926f * i / SAMPLE_POINTS;
        sum_real += samples[i] * cos(angle);
        sum_imag += samples[i] * sin(angle);
    }
    
    /* 计算幅值和相位 */
    *amplitude = sqrt(sum_real*sum_real + sum_imag*sum_imag) * 2.0f / SAMPLE_POINTS;
    
    if(sum_real == 0.0f && sum_imag == 0.0f)
        *phase = 0.0f;
    else
        *phase = atan2(sum_imag, sum_real) * 180.0f / 3.1415926f;
}

/**
 * @brief 处理三相数据
 * @param result 存储不平衡度结果
 */
void process_three_phase_data(UnbalanceResult *result)
{
    float amplitudes[3], phases[3];
    ThreePhaseVoltage voltages;
    int i;
    
    /* 计算各相幅值和相位 */
    for(i = 0; i < 3; i++)
    {
        calculate_phasor(voltage_samples[i], &amplitudes[i], &phases[i]);
    }
    
    /* 转换为复数形式 */
    for(i = 0; i < 3; i++)
    {
        float phase_rad = phases[i] * 3.1415926f / 180.0f;
        
        switch(i)
        {
            case 0:  // A相
                voltages.Ua.real = amplitudes[i] * cos(phase_rad);
                voltages.Ua.imag = amplitudes[i] * sin(phase_rad);
                break;
                
            case 1:  // B相
                voltages.Ub.real = amplitudes[i] * cos(phase_rad);
                voltages.Ub.imag = amplitudes[i] * sin(phase_rad);
                break;
                
            case 2:  // C相
                voltages.Uc.real = amplitudes[i] * cos(phase_rad);
                voltages.Uc.imag = amplitudes[i] * sin(phase_rad);
                break;
        }
    }
    
    /* 计算对称分量和不平衡度 */
    calculate_symmetric_components(&voltages, result);
}

3.5 主程序框架

/* 硬件接口定义 */
sbit RS = P2^0;      // LCD寄存器选择
sbit RW = P2^1;      // LCD读写
sbit EN = P2^2;      // LCD使能
sbit BUZZER = P3^7;  // 蜂鸣器
sbit LED_ALARM = P1^0; // 报警LED

/* 阈值定义 */
#define UNBALANCE_THRESHOLD 2.0f  // 不平衡度阈值2%

/**
 * @brief 初始化系统
 */
void system_init(void)
{
    /* 定时器初始化 */
    TMOD = 0x11;      // 定时器0、1工作模式1
    TH0 = 0xFC;       // 1ms定时
    TL0 = 0x18;
    TR0 = 1;          // 启动定时器0
    ET0 = 1;          // 允许定时器0中断
    
    /* 串口初始化 */
    SCON = 0x50;      // 模式1,允许接收
    PCON = 0x00;      // SMOD=0
    TH1 = 0xFD;       // 9600波特率 @11.0592MHz
    TL1 = 0xFD;
    TR1 = 1;          // 启动定时器1
    
    /* 外部中断初始化 */
    IT0 = 1;          // 边沿触发
    IT1 = 1;
    EX0 = 1;          // 允许外部中断0
    EX1 = 1;          // 允许外部中断1
    
    /* 全局中断使能 */
    EA = 1;
    
    /* LCD初始化 */
    lcd_init();
    
    /* 初始化蜂鸣器和LED */
    BUZZER = 0;
    LED_ALARM = 0;
}

/**
 * @brief 主函数
 */
void main(void)
{
    UnbalanceResult result;
    char display_buffer[20];
    
    /* 系统初始化 */
    system_init();
    
    /* 显示欢迎信息 */
    lcd_clear();
    lcd_write_string("3-Phase Unbalance");
    lcd_set_cursor(2, 1);
    lcd_write_string("Monitor System");
    delay_ms(2000);
    
    while(1)
    {
        /* 1. 采集三相数据(通过ADC或串口) */
        acquire_three_phase_data();
        
        /* 2. 计算不平衡度 */
        process_three_phase_data(&result);
        
        /* 3. 显示结果 */
        lcd_clear();
        lcd_write_string("U2%:");
        sprintf(display_buffer, "%.2f", result.unbalance_negative);
        lcd_write_string(display_buffer);
        
        lcd_set_cursor(2, 1);
        lcd_write_string("U0%:");
        sprintf(display_buffer, "%.2f", result.unbalance_zero);
        lcd_write_string(display_buffer);
        
        /* 4. 检查越限并报警 */
        if(result.unbalance_negative > UNBALANCE_THRESHOLD || 
           result.unbalance_zero > UNBALANCE_THRESHOLD)
        {
            alarm_trigger();
        }
        else
        {
            alarm_clear();
        }
        
        /* 5. 发送数据到上位机 */
        send_to_uart(&result);
        
        /* 6. 延时等待下一次计算 */
        delay_ms(1000);  // 每秒更新一次
    }
}

3.6 数据采集与通信模块

/**
 * @brief 模拟ADC数据采集(实际项目中替换为真实ADC读取)
 */
void acquire_three_phase_data(void)
{
    /* 模拟三相电压数据(220V, 50Hz,带不平衡) */
    float time = 0.0f;
    float dt = 1.0f / (frequency * SAMPLE_POINTS);
    int i, j;
    
    for(i = 0; i < SAMPLE_POINTS; i++)
    {
        time = i * dt;
        
        /* A相电压:220V,0°相位 */
        voltage_samples[0][i] = 220.0f * sqrt(2) * 
                               sin(2.0f * 3.1415926f * frequency * time);
        
        /* B相电压:215V,120°相位(不平衡) */
        voltage_samples[1][i] = 215.0f * sqrt(2) * 
                               sin(2.0f * 3.1415926f * frequency * time + 2.0944f);
        
        /* C相电压:225V,240°相位 */
        voltage_samples[2][i] = 225.0f * sqrt(2) * 
                               sin(2.0f * 3.1415926f * frequency * time + 4.1888f);
    }
}

/**
 * @brief 通过串口发送数据
 */
void send_to_uart(UnbalanceResult *result)
{
    printf("U1: %.2f∠%.1f°V\r\n", 
           complex_magnitude(&(result->U1)), 
           complex_phase(&(result->U1)));
           
    printf("U2: %.2f∠%.1f°V\r\n", 
           complex_magnitude(&(result->U2)), 
           complex_phase(&(result->U2)));
           
    printf("U0: %.2f∠%.1f°V\r\n", 
           complex_magnitude(&(result->U0)), 
           complex_phase(&(result->U0)));
           
    printf("Unbalance: %.2f%% (U2), %.2f%% (U0)\r\n", 
           result->unbalance_negative, 
           result->unbalance_zero);
           
    printf("--------------------------------\r\n");
}

3.7 报警处理模块

/**
 * @brief 触发报警
 */
void alarm_trigger(void)
{
    static int alarm_count = 0;
    
    BUZZER = 1;        // 蜂鸣器响
    LED_ALARM = 1;     // LED亮
    
    alarm_count++;
    
    /* 长时间报警后自动复位 */
    if(alarm_count > 300)  // 约5分钟
    {
        alarm_clear();
        alarm_count = 0;
    }
}

/**
 * @brief 清除报警
 */
void alarm_clear(void)
{
    BUZZER = 0;        // 蜂鸣器关闭
    LED_ALARM = 0;     // LED灭
}

3.8 实时时钟与数据记录

/* 时间结构体 */
typedef struct {
    unsigned char hour;
    unsigned char minute;
    unsigned char second;
} TimeStruct;

TimeStruct current_time = {0, 0, 0};
unsigned int day_count = 0;

/**
 * @brief 定时器0中断服务程序(1ms定时)
 */
void timer0_isr(void) interrupt 1
{
    static unsigned int ms_count = 0;
    
    /* 重装初值 */
    TH0 = 0xFC;
    TL0 = 0x18;
    
    ms_count++;
    
    /* 更新时间 */
    if(ms_count >= 1000)  // 1秒
    {
        ms_count = 0;
        current_time.second++;
        
        if(current_time.second >= 60)
        {
            current_time.second = 0;
            current_time.minute++;
            
            if(current_time.minute >= 60)
            {
                current_time.minute = 0;
                current_time.hour++;
                
                if(current_time.hour >= 24)
                {
                    current_time.hour = 0;
                    day_count++;
                }
            }
        }
    }
}

四、LCD显示驱动

/**
 * @file lcd1602.c
 * @brief LCD1602显示驱动
 */

#include <intrins.h>

/* LCD命令定义 */
#define LCD_CMD_CLEAR     0x01
#define LCD_CMD_HOME      0x02
#define LCD_CMD_ENTRY     0x06
#define LCD_CMD_DISPLAY   0x0C
#define LCD_CMD_SHIFT     0x10
#define LCD_CMD_FUNCTION  0x38

/**
 * @brief 忙检测
 */
void lcd_busy(void)
{
    P0 = 0xFF;      // 准备读状态
    RS = 0;         // 命令
    RW = 1;         // 读
    EN = 1;
    _nop_();
    while(P0 & 0x80);  // 检测BF位
    EN = 0;
}

/**
 * @brief 写命令
 */
void lcd_write_cmd(unsigned char cmd)
{
    lcd_busy();
    RS = 0;         // 命令
    RW = 0;         // 写
    EN = 0;
    P0 = cmd;
    EN = 1;
    _nop_();
    EN = 0;
}

/**
 * @brief 写数据
 */
void lcd_write_data(unsigned char dat)
{
    lcd_busy();
    RS = 1;         // 数据
    RW = 0;         // 写
    EN = 0;
    P0 = dat;
    EN = 1;
    _nop_();
    EN = 0;
}

/**
 * @brief LCD初始化
 */
void lcd_init(void)
{
    delay_ms(15);
    lcd_write_cmd(0x38);  // 8位数据,2行显示,5×7点阵
    delay_ms(5);
    lcd_write_cmd(0x38);
    delay_ms(5);
    lcd_write_cmd(0x38);
    
    lcd_write_cmd(0x08);  // 关闭显示
    lcd_write_cmd(0x01);  // 清屏
    lcd_write_cmd(0x06);  // 光标右移
    lcd_write_cmd(0x0C);  // 开显示,关光标
    
    delay_ms(2);
}

/**
 * @brief 清屏
 */
void lcd_clear(void)
{
    lcd_write_cmd(LCD_CMD_CLEAR);
    delay_ms(2);
}

/**
 * @brief 设置光标位置
 * @param line 行号(1或2)
 * @param column 列号(0-15)
 */
void lcd_set_cursor(unsigned char line, unsigned char column)
{
    unsigned char addr;
    
    if(line == 1)
        addr = 0x80 + column;  // 第一行
    else
        addr = 0xC0 + column;  // 第二行
        
    lcd_write_cmd(addr);
}

/**
 * @brief 显示字符串
 */
void lcd_write_string(char *str)
{
    while(*str != '\0')
    {
        lcd_write_data(*str);
        str++;
    }
}

五、工程优化与调试

5.1 内存优化(51资源有限)

/* 使用xdata扩展内存 */
#include <absacc.h>

#define XDATA_RAM_SIZE 1024
xdata float voltage_buffer[3][32];  // 使用外部RAM

/* 使用code存储常量 */
code const float sin_table[32] = {
    0.0000, 0.1951, 0.3827, 0.5556, 0.7071, 0.8315, 0.9239, 0.9808,
    1.0000, 0.9808, 0.9239, 0.8315, 0.7071, 0.5556, 0.3827, 0.1951,
    0.0000, -0.1951, -0.3827, -0.5556, -0.7071, -0.8315, -0.9239, -0.9808,
    -1.0000, -0.9808, -0.9239, -0.8315, -0.7071, -0.5556, -0.3827, -0.1951
};

5.2 快速算法优化

/**
 * @brief 快速计算幅值(避免开方运算)
 * @param real 实部
 * @param imag 虚部
 * @return 近似幅值
 */
float fast_magnitude(float real, float imag)
{
    float abs_real = fabs(real);
    float abs_imag = fabs(imag);
    
    if(abs_real > abs_imag)
        return abs_real + 0.4f * abs_imag;
    else
        return abs_imag + 0.4f * abs_real;
}

5.3 滤波算法

/* 移动平均滤波 */
#define FILTER_SIZE 5

float moving_average_filter(float new_sample)
{
    static float buffer[FILTER_SIZE] = {0};
    static int index = 0;
    float sum = 0;
    int i;
    
    buffer[index] = new_sample;
    index = (index + 1) % FILTER_SIZE;
    
    for(i = 0; i < FILTER_SIZE; i++)
    {
        sum += buffer[i];
    }
    
    return sum / FILTER_SIZE;
}

六、测试示例

6.1 测试主程序

/**
 * @brief 测试程序
 */
void test_three_phase_unbalance(void)
{
    ThreePhaseVoltage test_voltage;
    UnbalanceResult result;
    
    /* 设置测试数据 */
    /* 模拟三相电压:Ua=220∠0°, Ub=210∠-120°, Uc=230∠120° */
    test_voltage.Ua.real = 220.0f;
    test_voltage.Ua.imag = 0.0f;
    
    test_voltage.Ub.real = 210.0f * cos(-2.0944f);  // -120°
    test_voltage.Ub.imag = 210.0f * sin(-2.0944f);
    
    test_voltage.Uc.real = 230.0f * cos(2.0944f);   // 120°
    test_voltage.Uc.imag = 230.0f * sin(2.0944f);
    
    /* 计算不平衡度 */
    calculate_symmetric_components(&test_voltage, &result);
    
    /* 打印结果 */
    printf("Test Result:\r\n");
    printf("U1 Magnitude: %.2f V, Phase: %.1f°\r\n", 
           complex_magnitude(&result.U1), 
           complex_phase(&result.U1));
           
    printf("U2 Magnitude: %.2f V, Phase: %.1f°\r\n", 
           complex_magnitude(&result.U2), 
           complex_phase(&result.U2));
           
    printf("U0 Magnitude: %.2f V, Phase: %.1f°\r\n", 
           complex_magnitude(&result.U0), 
           complex_phase(&result.U0));
           
    printf("Negative Unbalance: %.2f%%\r\n", result.unbalance_negative);
    printf("Zero Unbalance: %.2f%%\r\n", result.unbalance_zero);
    
    if(result.unbalance_negative > 2.0f)
    {
        printf("WARNING: Negative unbalance exceeds limit!\r\n");
    }
}

参考代码 三相不平衡c语言程序(51平台) www.youwenfan.com/contentcnu/70580.html

七、注意事项

  1. 浮点运算性能:51单片机浮点运算较慢,建议使用查表法或定点数运算
  2. 内存限制:51内部RAM有限,大数据需使用xdata
  3. 精度问题:使用单精度浮点可能引入误差,关键计算可考虑双精度
  4. 实时性:采样率不宜过高,确保计算实时性
  5. 抗干扰:工业环境需添加数字滤波和看门狗

八、扩展功能建议

  1. 数据存储:添加EEPROM存储历史数据
  2. 网络通信:通过以太网/WiFi模块上传数据
  3. 谐波分析:扩展FFT计算谐波含量
  4. 功率计算:计算三相有功、无功、视在功率
  5. 故障录波:记录故障前后数据波形

专注于matlab/simulink,电子电路,编程