基于FM3318智能电表MCU的程序

基于FM3318智能电表MCU的程序框架及核心代码


一、系统架构设计

+-------------------+       +-------------------+
| 电源管理模块      |<----->| FM3318主控单元    |
| (LDO+RTC)         |       | (16位增强型80251核)|
+--------+----------+       +--------+----------+
         |                         |
         v                         v
+--------+----------+       +-------------------+
| 电能计量电路      |       | 外设接口模块      |
| (电压/电流采样)   |       | (LCD/UART/ADC)    |
+--------+----------+       +--------+----------+
         |
         v
+-------------------+
| 数据存储模块      |
| (EEPROM+RTC)      |
+-------------------+

二、核心代码实现

1. 系统初始化(main.c)

#include "FM3318.h"

// 系统配置结构体
typedef struct {
    uint32_t sys_clk;       // 系统时钟频率
    uint16_t adc_prescaler; // ADC分频系数
    uint8_t rtc_en;         // RTC使能标志
} SYS_CFG;

SYS_CFG sys_cfg = {
    .sys_clk = 16000000,   // 16MHz系统时钟
    .adc_prescaler = 128,  // ADC分频系数
    .rtc_en = 1            // 启用RTC
};

void SystemInit(void) {
    // 时钟配置
    CLK_EnableModule(SYS_CLK);  // 启用系统时钟
    CLK_SetDivider(CLK_DIV_ADC, sys_cfg.adc_prescaler);  // 设置ADC分频
    
    // 外设初始化
    UART_Init(9600);            // 初始化UART通信
    ADC_Init(ADC_MODE_CONTINUOUS);  // 连续采样模式
    RTC_Init();                 // 初始化RTC时钟
    
    // 中断配置
    NVIC_EnableIRQ(ADC_IRQn);   // 使能ADC中断
    NVIC_EnableIRQ(UART_IRQn);  // 使能UART中断
}

2. 电能计量模块(meter.c)

// 电能计量结构体
typedef struct {
    float voltage;        // 电压有效值
    float current;        // 电流有效值
    float active_power;   // 有功功率
    float reactive_power; // 无功功率
    uint32_t energy;      // 累计电能(kWh)
} METER_DATA;

METER_DATA meter_data;

// 电压电流采样中断服务程序
void ADC_IRQHandler(void) {
    if(ADC_GetITStatus(ADC_FLAG_EOC)) {
        // 读取原始数据
        uint16_t adc_val = ADC_GetResult();
        
        // 电压计算(参考电压3.3V)
        meter_data.voltage = (adc_val * 3.3f) / 4095.0f * 100.0f;  // 0-330V量程
        
        // 电流计算(CT变比1000:1)
        meter_data.current = (adc_val * 3.3f) / 4095.0f * 1000.0f; // 0-1000A量程
        
        // 功率计算
        meter_data.active_power = meter_data.voltage * meter_data.current * 0.9;  // 功率因数0.9
        
        // 累计电能
        meter_data.energy += (meter_data.active_power * 0.001f);  // 每秒累加
    }
}

// 电能数据存储
void SaveEnergyData(void) {
    EEPROM_Write(0x2000, (uint8_t*)&meter_data.energy, sizeof(meter_data.energy));
}

3. 数据通信模块(comm.c)

// Modbus协议数据帧结构
typedef struct {
    uint8_t addr;     // 从站地址
    uint8_t func;     // 功能码
    uint16_t reg;     // 寄存器地址
    uint16_t value;   // 数据值
    uint16_t crc;     // CRC校验
} MODBUS_FRAME;

// Modbus RTU发送函数
void Modbus_Send(MODBUS_FRAME *frame) {
    UART_Send(frame->addr);      // 发送从站地址
    UART_Send(frame->func);      // 发送功能码
    UART_SendH(frame->reg >> 8); // 寄存器地址高字节
    UART_SendL(frame->reg & 0xFF);// 寄存器地址低字节
    UART_SendH(frame->value >> 8);// 数据高字节
    UART_SendL(frame->value & 0xFF);// 数据低字节
    UART_SendH(frame->crc >> 8); // CRC高字节
    UART_SendL(frame->crc & 0xFF);// CRC低字节
}

// CRC16校验函数
uint16_t Modbus_CalculateCRC(uint8_t *buf, uint16_t len) {
    uint16_t crc = 0xFFFF;
    for(uint16_t i=0; i<len; i++) {
        crc ^= (uint16_t)buf[i] << 8;
        for(uint8_t j=0; j<8; j++) {
            if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
            else crc <<= 1;
        }
    }
    return crc;
}

三、硬件配置要点

1. 时钟系统配置

// 系统时钟初始化(SystemInit.c)
void SystemClock_Config(void) {
    // 启用PLL倍频
    RCC_EnablePLL(RCC_PLLSRC_HSE, 4);  // HSE=8MHz → PLL=32MHz
    
    // 配置时钟树
    RCC_SetAHBCLKDiv(RCC_AHBCLK_DIV1);  // AHB时钟不分频
    RCC_SetAPB1CLKDiv(RCC_APB1CLK_DIV2); // APB1时钟2分频
    RCC_SetAPB2CLKDiv(RCC_APB2CLK_DIV1); // APB2时钟不分频
    
    // 系统主频设置
    SystemCoreClockUpdate();
}

2. ADC配置(adc.c)

// ADC初始化(adc.c)
void ADC_Init(uint8_t mode) {
    // 使能ADC时钟
    RCC_EnableADC();
    
    // 配置ADC参数
    ADC_SetResolution(ADC_RES_12BIT);  // 12位分辨率
    ADC_SetSamplingTime(ADC_SMP_3CYC); // 3个周期采样
    ADC_SetChannelAttenuation(ADC_CH_0, ADC_ATTEN_11DB); // 通道0衰减
    
    // 启动ADC
    if(mode == ADC_MODE_CONTINUOUS) {
        ADC_EnableContinuousMode();
    }
}

四、关键算法实现

1. 电能质量分析

// 谐波分析函数(harmonic.c)
void AnalyzeHarmonics(float *fft_buf) {
    // 快速傅里叶变换
    FFT_Execute(fft_buf, FFT_SIZE);
    
    // 谐波畸变率计算
    float thd = 0.0f;
    for(int i=2; i<FFT_SIZE/2; i++) {
        thd += pow(fft_buf[i], 2);
    }
    thd = sqrt(thd) / fft_buf[1] * 100;  // THD%
    
    // 存储谐波数据
    EEPROM_Write(0x3000, (uint8_t*)&thd, sizeof(thd));
}

2. 防窃电检测

// 防窃电检测算法(anti_tamper.c)
bool DetectTampering(void) {
    // 电压电流相位检测
    float phase_diff = fabs(atan2(meter_data.reactive_power, meter_data.active_power) - 
                           atan2(meter_data.voltage, meter_data.current));
    
    // 异常判断
    if(phase_diff > 0.2f || meter_data.current > 1200.0f) {
        // 触发报警
        Alarm_Trigger(TAMPER_ALARM);
        return true;
    }
    return false;
}

五、工程调试技巧

1. 调试接口配置

// JTAG调试初始化(debug.c)
void Debug_Init(void) {
    // 配置SWD接口
    DBGMCU_EnableSWJ(SWJ_DISABLE);  // 禁用SWJ接口
    DBGMCU_SetDebugMode(DBG_MODE_SWD);  // 设置SWD调试模式
}

2. 低功耗管理

// 低功耗模式切换(power.c)
void EnterLowPowerMode(void) {
    // 关闭外设时钟
    RCC_DisablePeripheral(RCC_PERIPH_ADC);
    RCC_DisablePeripheral(RCC_PERIPH_UART);
    
    // 进入待机模式
    PWR_EnterSTANDBYMode(PWR_STANDBY_FLAG);
}

参考代码 fm3318电表程序 代码 www.youwenfan.com/contentcnl/60721.html

六、典型应用场景

1. 三相电表数据采集

// 三相电表主循环
while(1) {
    // 采集三相数据
    PhaseA_Data = ReadPhaseData(PHASE_A);
    PhaseB_Data = ReadPhaseData(PHASE_B);
    PhaseC_Data = ReadPhaseData(PHASE_C);
    
    // 计算总功率
    total_power = PhaseA_Data.active + PhaseB_Data.active + PhaseC_Data.active;
    
    // 发送数据到上位机
    Modbus_Send(&modbus_frame);
    
    // 进入低功耗模式
    if(idle_time > 60) EnterLowPowerMode();
}

2. 电能质量监测

// 电能质量监测流程
void MonitorPowerQuality(void) {
    while(1) {
        // 采集1024点采样数据
        ADC_CaptureBuffer(fft_buffer, FFT_SIZE);
        
        // 执行FFT分析
        AnalyzeHarmonics(fft_buffer);
        
        // 检测闪变
        if(DetectFlicker(fft_buffer)) {
            Alarm_Trigger(FLICKER_ALARM);
        }
        
        DelayMs(1000);  // 每秒检测一次
    }
}

七、硬件设计建议

  1. 电源滤波
    • 输入滤波:10μF电解电容 + 0.1μF陶瓷电容
    • 电源监控:添加TPS3823-33DBVR看门狗芯片
  2. 信号完整性
    • 电流采样路径阻抗<0.5Ω
    • 电压采样添加RC低通滤波器(1kΩ+100nF)
  3. PCB布局
    • 模拟地和数字地分割
    • 高频信号走线最短化
    • 参考平面完整性

八、调试工具推荐

  1. 协议分析仪:使用Total Phase Aardvark验证Modbus通信
  2. 电流检测:Keysight N2891A电流探头
  3. 示波器:Rigol DS1054Z(观察PWM波形)

九、扩展功能实现

1. 多费率计量

// 费率时段配置
typedef struct {
    uint8_t hour_start;
    uint8_t hour_end;
    float rate;
} TARIFF;

TARIFF tariffs[4] = {
    {0, 8, 0.52},    // 尖峰时段
    {8, 12, 0.35},   // 峰时段
    {12, 18, 0.28},  // 平时段
    {18, 24, 0.15}   // 谷时段
};

// 费率计算函数
float CalculateTariff(float energy) {
    time_t now = RTC_GetTime();
    struct tm *tm_info = localtime(&now);
    
    for(int i=0; i<4; i++) {
        if(tm_info->tm_hour >= tariffs[i].hour_start && 
           tm_info->tm_hour < tariffs[i].hour_end) {
            return energy * tariffs[i].rate;
        }
    }
    return 0;
}

2. 安全认证

// AES加密实现(security.c)
void EncryptData(uint8_t *data, uint16_t len) {
    AES_KEY key;
    AES_SetKey(&key, (uint8_t*)"FM3318_SECURE_KEY", 16);
    
    for(uint16_t i=0; i<len; i+=16) {
        AES_EncryptBlock(data + i, &key);
    }
}

十、工程部署建议

  1. 编译配置

    # Makefile配置示例
    MCU = fm3318
    F_CPU = 16000000
    CFLAGS = -Os -mcpu=cortex-m3 -mthumb -DUSE_HAL_DRIVER
    LDFLAGS = -TSTM32F30x_FLASH.ld -specs=nosys.specs
    
  2. 版本控制

    # Git提交示例
    git add .
    git commit -m "v1.2.0: 添加三相电能计量功能"
    git tag v1.2.0
    
posted @ 2025-11-10 11:08  躲雨小伙  阅读(4)  评论(0)    收藏  举报