带功率检测功能的代码

This commit is contained in:
ipason 2026-01-08 08:45:31 +08:00
parent d5a4f2a778
commit 92f7b18ac4
6 changed files with 155 additions and 104 deletions

View File

@ -1,6 +1,6 @@
/**
******************************************************************************
* @file power_meter.c
* @file 8f_5aw_powerMeter.c
* @author Motor Control SDK Team, Yuwell Software XiangenWang
* @brief Voice Recognition Module Initialization Section,
including peripheral initialization and message node insertion, etc.
@ -47,14 +47,14 @@
*/
/* USER CODE END Header */
#include "power_meter.h"
#include "8f_5aw_powerMeter.h"
// 提供给外部的采样结果数据
EleC_V_data elec_v_data;
EleC_V_Data elec_v_data;
#if COULOMBMETER_SET_FUNC_ENABLE
#if POWER_METER_SET_FUNC_ENABLE // 使用默认寄存器配置 不修改寄存器内容
/**
* @brief BL0942指定寄存器写入24位数据
* @param addr: (8)
@ -65,25 +65,25 @@ EleC_V_data elec_v_data;
* 3. (++3)8
* 4. 3
*/
static void coulombmeter_write_reg(uint8_t addr, uint8_t* reg_data)
static void power_meter_write_reg(uint8_t addr, uint8_t* reg_data)
{
uint8_t check_sum = 0;
// 1. 下发命令字节 BL0942_ADDR_W
COULOMBMETER_UART_TRANS_BYTE(BL0942_ADDR_W);
POWER_METER_UART_TRANS_BYTE(BL0942_ADDR_W);
// 2. 下发需要写寄存器的地址
COULOMBMETER_UART_TRANS_BYTE(addr);
POWER_METER_UART_TRANS_BYTE(addr);
// 3. 发送需要往寄存器地址写入的数据
COULOMBMETER_UART_TRANS_BYTE(reg_data[0]);
COULOMBMETER_UART_TRANS_BYTE(reg_data[1]);
COULOMBMETER_UART_TRANS_BYTE(reg_data[2]);
POWER_METER_UART_TRANS_BYTE(reg_data[0]);
POWER_METER_UART_TRANS_BYTE(reg_data[1]);
POWER_METER_UART_TRANS_BYTE(reg_data[2]);
// 4. 发送校验和
check_sum = (BL0942_ADDR_W + addr + reg_data[0] + reg_data[1] + reg_data[2]);
check_sum = ~(check_sum & 0xFF);
COULOMBMETER_UART_TRANS_BYTE(check_sum);
POWER_METER_UART_TRANS_BYTE(check_sum);
}
#endif
@ -96,15 +96,15 @@ static void coulombmeter_write_reg(uint8_t addr, uint8_t* reg_data)
* @retval
* @note 1. UART发送帧格式为[(BL0942_ADDR_R)+]
* 2. 150us内通过UART返回4字节数据(3+1)
* 3. 1s执行一次该函数UART接收中断中处理
* 3. 500ms执行一次该函数UART接收中断中处理(400ms刷新一次)
*/
static void coulombmeter_read_reg(uint8_t addr)
static void power_meter_read_reg(uint8_t addr)
{
// 1. 下发命令字节 BL0942_ADDR_R
COULOMBMETER_UART_TRANS_BYTE(BL0942_ADDR_R);
POWER_METER_UART_TRANS_BYTE(BL0942_ADDR_R);
// 2. 下发地址数据
COULOMBMETER_UART_TRANS_BYTE(addr);
POWER_METER_UART_TRANS_BYTE(addr);
}
@ -126,17 +126,17 @@ void User_PowerMeter_Init(void)
FL_GPIO_InitTypeDef GPIO_InitStruct;
// 初始化GPIO
GPIO_InitStruct.pin = COULOMBMETER_UART_RX_GPIO_PIN;
GPIO_InitStruct.pin = POWER_METER_UART_RX_GPIO_PIN;
GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.pull = FL_DISABLE;
GPIO_InitStruct.remapPin = FL_DISABLE;
GPIO_InitStruct.analogSwitch = FL_DISABLE;
FL_GPIO_Init(COULOMBMETER_UART_RX_GPIO_PORT, &GPIO_InitStruct);
FL_GPIO_Init(POWER_METER_UART_RX_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.pin = COULOMBMETER_UART_TX_GPIO_PIN;
FL_GPIO_Init(COULOMBMETER_UART_TX_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.pin = POWER_METER_UART_TX_GPIO_PIN;
FL_GPIO_Init(POWER_METER_UART_TX_GPIO_PORT, &GPIO_InitStruct);
// 初始化串口参数
FL_UART_InitTypeDef UART_InitStruct = {0};
@ -145,20 +145,18 @@ void User_PowerMeter_Init(void)
UART_InitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B; //停止位
UART_InitStruct.parity = FL_UART_PARITY_NONE; //奇偶校验
UART_InitStruct.transferDirection = FL_UART_DIRECTION_TX_RX; //接收-发送使能
FL_UART_Init(COULOMBMETER_USED_UART_NUM, &UART_InitStruct);
FL_UART_Init(POWER_METER_USED_UART_NUM, &UART_InitStruct);
NVIC_DisableIRQ(COULOMBMETER_IRQn);
NVIC_SetPriority(COULOMBMETER_IRQn,2); //中断优先级配置
NVIC_EnableIRQ(COULOMBMETER_IRQn);
NVIC_DisableIRQ(POWER_METER_IRQn);
NVIC_SetPriority(POWER_METER_IRQn,2); //中断优先级配置
NVIC_EnableIRQ(POWER_METER_IRQn);
// 开启接收中断
FL_UART_ClearFlag_RXBuffFull(COULOMBMETER_USED_UART_NUM);
FL_UART_EnableIT_RXBuffFull(COULOMBMETER_USED_UART_NUM);
FL_UART_ClearFlag_RXBuffFull(POWER_METER_USED_UART_NUM);
FL_UART_EnableIT_RXBuffFull(POWER_METER_USED_UART_NUM);
// 清空结果
memset(&elec_v_data, 0, sizeof(elec_v_data));
}
@ -173,27 +171,36 @@ void User_PowerMeter_Init(void)
* 3. UART中断中完成
* 4. /elec_v_data中
*/
void User_Coulombmeter_Data_refresh(void)
void User_Power_refresh(void)
{
static Bus_Mod mod = MOD_CURRENT_METER;
static Bus_Mod mod = MOD_VOLTAGE_METER;
if(mod == MOD_VOLTAGE_METER)
{
mod = MOD_CURRENT_METER;
coulombmeter_read_reg(Addr_V_RMS);
power_meter_read_reg(Addr_V_RMS);
elec_v_data.bus_com_stm = BUS_COM_STATE_WAITE_VOLTAGE; // 转入等待电压数据状态
elec_v_data.current_index = 0;
elec_v_data.voltage_raw = 0;
}else{
}else if(mod == MOD_CURRENT_METER){
mod = MOD_VOLTAGE_METER;
coulombmeter_read_reg(Addr_I_RMS);
mod = MOD_POWER_METER;
power_meter_read_reg(Addr_I_RMS);
elec_v_data.bus_com_stm = BUS_COM_STATE_WAITE_CURRENT; // 转入等待电数据状态
elec_v_data.bus_com_stm = BUS_COM_STATE_WAITE_CURRENT; // 转入等待电数据状态
elec_v_data.current_index = 0;
elec_v_data.current_raw = 0;
}else if(mod == MOD_POWER_METER){
mod = MOD_VOLTAGE_METER;
power_meter_read_reg(Addr_WATT);
elec_v_data.bus_com_stm = BUS_COM_STATE_WAITE_POWER; // 转入等待功率数据状态
elec_v_data.current_index = 0;
elec_v_data.power_raw = 0;
}
}
@ -201,21 +208,21 @@ void User_Coulombmeter_Data_refresh(void)
/**
* @brief UART5中断服务函数
* @brief UART5中断服务函数
* @param
* @retval
* @note 1. (RXBuffFull)
* 2. (BUS_COM_STATE)/
* 2. (BUS_COM_STATE)//
* 3. 3()+1
* 4. (V)/(mA)
* 5. RXBuff寄存器自动清除RXBuffFull标志
* 4. (V)/(mA)/
* 5. RXBuff寄存器自动清除RXBuffFull标志
*/
void UART5_IRQHandler(void)
{
// 接收中断处理
if(FL_UART_IsEnabledIT_RXBuffFull(COULOMBMETER_USED_UART_NUM) &&
FL_UART_IsActiveFlag_RXBuffFull(COULOMBMETER_USED_UART_NUM))
if(FL_UART_IsEnabledIT_RXBuffFull(POWER_METER_USED_UART_NUM) &&
FL_UART_IsActiveFlag_RXBuffFull(POWER_METER_USED_UART_NUM))
{
if(elec_v_data.bus_com_stm == BUS_COM_STATE_WAITE_VOLTAGE)
@ -223,7 +230,7 @@ void UART5_IRQHandler(void)
//接收中断标志可通过读取rxreg寄存器清除
uint8_t tmp_data = 0;
tmp_data = FL_UART_ReadRXBuff(COULOMBMETER_USED_UART_NUM);
tmp_data = FL_UART_ReadRXBuff(POWER_METER_USED_UART_NUM);
if(elec_v_data.current_index < 3)
{
@ -254,7 +261,7 @@ void UART5_IRQHandler(void)
}else if(elec_v_data.bus_com_stm == BUS_COM_STATE_WAITE_CURRENT)
{
uint8_t tmp_data = 0;
tmp_data = FL_UART_ReadRXBuff(COULOMBMETER_USED_UART_NUM);
tmp_data = FL_UART_ReadRXBuff(POWER_METER_USED_UART_NUM);
if(elec_v_data.current_index < 3)
{
@ -282,9 +289,47 @@ void UART5_IRQHandler(void)
}
}else if(elec_v_data.bus_com_stm == BUS_COM_STATE_WAITE_POWER)
{
uint8_t tmp_data = 0;
tmp_data = FL_UART_ReadRXBuff(POWER_METER_USED_UART_NUM);
if(elec_v_data.current_index < 3)
{
elec_v_data.power_raw |= (tmp_data<<(elec_v_data.current_index*8));
}
FL_UART_ClearFlag_RXBuffFull(COULOMBMETER_USED_UART_NUM);
elec_v_data.power_array[elec_v_data.current_index++] = tmp_data;
if(elec_v_data.current_index == 4)
{
uint8_t checkSum = ~((elec_v_data.power_array[0] + elec_v_data.power_array[1] + elec_v_data.power_array[2] + BL0942_ADDR_R + Addr_WATT)&0xFF);
if(elec_v_data.power_array[3] == checkSum)
{
// 校验正确对数据进行赋值
elec_v_data.bus_com_stm = BUS_COM_STATE_IDLE;
// 当接收到的数据为负值时将其转为正值
if(elec_v_data.power_array[2] > 0x7F)
{
elec_v_data.power_raw = ~elec_v_data.power_raw + 1;
}
elec_v_data.bus_active_power_watt = elec_v_data.power_raw * 100 /Power_K;
elec_v_data.power_raw = 0;
elec_v_data.current_index = 0;
}
}
}
FL_UART_ClearFlag_RXBuffFull(POWER_METER_USED_UART_NUM);
}
}

View File

@ -1,7 +1,7 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : power_meter.h
* @file : 8f_5aw_powerMeter.h
* @brief :
* @version : 1.0
* @changelog : version 1.0 2025.12.31
@ -23,8 +23,8 @@
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __COULOMBMETER_H
#define __COULOMBMETER_H
#ifndef __8F_5AW_POWER_METER_H
#define __8F_5AW_POWER_METER_H
#ifdef __cplusplus
extern "C" {
@ -36,23 +36,22 @@ extern "C" {
/************************** 硬件参数重映射 **************************/
/* 对硬件使用进行配置 */
#define COULOMBMETER_USED_UART_NUM UART5
#define COULOMBMETER_UART_TX_GPIO_PORT GPIOC
#define COULOMBMETER_UART_TX_GPIO_PIN FL_GPIO_PIN_5
#define COULOMBMETER_UART_RX_GPIO_PORT GPIOC
#define COULOMBMETER_UART_RX_GPIO_PIN FL_GPIO_PIN_4
// 对硬件进行重定向
#define POWER_METER_USED_UART_NUM UART5
#define POWER_METER_UART_TX_GPIO_PORT GPIOC
#define POWER_METER_UART_TX_GPIO_PIN FL_GPIO_PIN_5
#define POWER_METER_UART_RX_GPIO_PORT GPIOC
#define POWER_METER_UART_RX_GPIO_PIN FL_GPIO_PIN_4
#define COULOMBMETER_IRQn UART5_IRQn
#define POWER_METER_IRQn UART5_IRQn
// CPU阻塞式发送
#define CHECK_TRANS_DONE while(FL_UART_IsActiveFlag_TXShiftBuffEmpty(COULOMBMETER_USED_UART_NUM) != FL_SET){};
#define COULOMBMETER_UART_TRANS_BYTE(x) FL_UART_WriteTXBuff(COULOMBMETER_USED_UART_NUM, x);CHECK_TRANS_DONE;
#define CHECK_TRANS_DONE while(FL_UART_IsActiveFlag_TXShiftBuffEmpty(POWER_METER_USED_UART_NUM) != FL_SET){};
#define POWER_METER_UART_TRANS_BYTE(x) FL_UART_WriteTXBuff(POWER_METER_USED_UART_NUM, x);CHECK_TRANS_DONE;
#define COULOMBMETER_SET_FUNC_ENABLE (0)
#define POWER_METER_SET_FUNC_ENABLE (0)
/************************** 芯片内部寄存器地址定义 **************************/
@ -100,10 +99,10 @@ extern "C" {
// 电流采用1毫欧电阻采样电压采用390K*5+0.51K进行分压,实际测试发现电阻存在偏差,进行微调
// BL0942评估版立创直接贴片合金电阻(台湾厚声MS121WF100NT4E )实际测量比1毫欧偏小约0.93毫欧
#define Power_K 5798; //理论值*0.93
#define Current_K 50243; //理论值*0.93
#define Voltage_K 15883; //
#define Energy_K 4976; //理论值*0.93
#define Power_K 6234; // 理论值
#define Current_K 25121; // 理论值
#define Voltage_K 15883; // 理论值
#define Energy_K 4976; // 理论值
//采用美隆1毫欧贴片合金电阻实际比1毫欧偏大约1.023毫欧
/*
@ -122,6 +121,7 @@ typedef enum
BUS_COM_STATE_IDLE,
BUS_COM_STATE_WAITE_CURRENT,
BUS_COM_STATE_WAITE_VOLTAGE,
BUS_COM_STATE_WAITE_POWER,
BUS_CHECK_ERROR,
BUS_COM_STATE_WAITE_CHECK
@ -131,7 +131,8 @@ typedef enum
typedef enum
{
MOD_CURRENT_METER,
MOD_VOLTAGE_METER
MOD_VOLTAGE_METER,
MOD_POWER_METER
}Bus_Mod;
@ -140,6 +141,10 @@ typedef struct
uint16_t bus_rms_current_mA; // 总线供电电路有效值 单位为mA
uint16_t bus_rms_voltage_V; // 总线供电电压有效值 单位为V
uint16_t bus_active_power_watt; // 总线有功功率 单位为瓦特
uint32_t power_raw;
uint8_t power_array[4];
uint32_t voltage_raw;
uint8_t voltage_array[4];
@ -151,23 +156,24 @@ typedef struct
uint8_t current_index;
}EleC_V_data;
}EleC_V_Data;
extern EleC_V_data elec_v_data;
extern EleC_V_Data elec_v_data; // 周期性刷新该结构体变量中的内容 通过读取变量成员获取当前电压、电流、有功功率
/************************** 外部API函数导出 **************************/
void User_PowerMeter_Init(void);
void UART5_IRQHandler(void);
void User_PowerMeter_Init(void); // 上电后执行一次 用于初始化GPIO UART
void User_Power_refresh(void); // 每500ms以上时间执行一次该函数以刷新elec_v_data中内容。
void User_Coulombmeter_Data_refresh(void);
void UART5_IRQHandler(void);
#ifdef __cplusplus
}
#endif
#endif /* __COULOMBMETER_H */
#endif /* __8F_5AW_POWER_METER_H */
/************************ (C) COPYRIGHT Yuwell *****END OF FILE****/

File diff suppressed because one or more lines are too long

View File

@ -117,10 +117,6 @@
<pMon>Segger\JL2CM3.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGUARM</Key>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>JL2CM3</Key>
@ -308,8 +304,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\8F-3AW-PowerMeter\power_meter.c</PathWithFileName>
<FilenameWithoutPath>power_meter.c</FilenameWithoutPath>
<PathWithFileName>..\8F_5AW_PowerMeter\8f_5aw_powerMeter.c</PathWithFileName>
<FilenameWithoutPath>8f_5aw_powerMeter.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>

View File

@ -340,7 +340,7 @@
<MiscControls></MiscControls>
<Define>FM33LG0XX,USE_FULL_ASSERT</Define>
<Undefine></Undefine>
<IncludePath>..\Drivers\CMSIS;..\Drivers\FM33LG0xx_FL_Driver\Inc;..\Inc;..\MF-config\Inc;..\8F-3AW-PowerMeter</IncludePath>
<IncludePath>..\Drivers\CMSIS;..\Drivers\FM33LG0xx_FL_Driver\Inc;..\Inc;..\MF-config\Inc;..\8F_5AW_PowerMeter</IncludePath>
</VariousControls>
</Cads>
<Aads>
@ -420,9 +420,9 @@
<FilePath>..\Src\fm33lg0xx_fl_common.c</FilePath>
</File>
<File>
<FileName>power_meter.c</FileName>
<FileName>8f_5aw_powerMeter.c</FileName>
<FileType>1</FileType>
<FilePath>..\8F-3AW-PowerMeter\power_meter.c</FilePath>
<FilePath>..\8F_5AW_PowerMeter\8f_5aw_powerMeter.c</FilePath>
</File>
</Files>
</Group>

View File

@ -51,7 +51,7 @@
#include "main.h"
#include "fm33_assert.h"
#include "power_meter.h"
#include "8f_5aw_powerMeter.h"
#define FREQ_CHECK_ENABLE (1) // 选择是否使能频率检查 仅在debug阶段使用
@ -110,7 +110,7 @@ int main(void)
{
FL_DelayMs(1000);
User_Coulombmeter_Data_refresh();
User_Power_refresh();
// LED灯闪烁
FL_GPIO_ToggleOutputPin(GPIOD, FL_GPIO_PIN_5);