基于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); // 每秒检测一次
}
}
七、硬件设计建议
- 电源滤波:
- 输入滤波:10μF电解电容 + 0.1μF陶瓷电容
- 电源监控:添加TPS3823-33DBVR看门狗芯片
- 信号完整性:
- 电流采样路径阻抗<0.5Ω
- 电压采样添加RC低通滤波器(1kΩ+100nF)
- PCB布局:
- 模拟地和数字地分割
- 高频信号走线最短化
- 参考平面完整性
八、调试工具推荐
- 协议分析仪:使用Total Phase Aardvark验证Modbus通信
- 电流检测:Keysight N2891A电流探头
- 示波器: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);
}
}
十、工程部署建议
-
编译配置:
# Makefile配置示例 MCU = fm3318 F_CPU = 16000000 CFLAGS = -Os -mcpu=cortex-m3 -mthumb -DUSE_HAL_DRIVER LDFLAGS = -TSTM32F30x_FLASH.ld -specs=nosys.specs -
版本控制:
# Git提交示例 git add . git commit -m "v1.2.0: 添加三相电能计量功能" git tag v1.2.0

浙公网安备 33010602011771号