基于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], &litudes[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
七、注意事项
- 浮点运算性能:51单片机浮点运算较慢,建议使用查表法或定点数运算
- 内存限制:51内部RAM有限,大数据需使用xdata
- 精度问题:使用单精度浮点可能引入误差,关键计算可考虑双精度
- 实时性:采样率不宜过高,确保计算实时性
- 抗干扰:工业环境需添加数字滤波和看门狗
八、扩展功能建议
- 数据存储:添加EEPROM存储历史数据
- 网络通信:通过以太网/WiFi模块上传数据
- 谐波分析:扩展FFT计算谐波含量
- 功率计算:计算三相有功、无功、视在功率
- 故障录波:记录故障前后数据波形