用电器分析识别装置(2021 年全国大学生电子设计竞赛H题)
本次设计在当时比赛时获得国二奖项,遂选择毕业后分享。
核心代码链接:CS5463代码
摘要
本设计是非侵入式用电器分析监测装置,可根据同一条线路上的电参数信息分析用电器的类别和工作状态。该装置由主回路模块和用电器分析监测装置模块组成。主回路模块用于将监测装置的取电和监测进行隔离,用电器分析检测模块以STM32为主控,控制高性能电能计量芯片CS5463直接完成电压、电流、功率因数等参数的测量。装置具有学习和分析监测两种工作模式,在学习模式下,测试并存储同一条线路上单件用电器的各种电特征参量,通过AD采样将电器通电后的电流信号变为离散序列,计算序列的FFT变换得到信号的频谱,再通过CS5463测出电器的功率、电流等电气特征的值。其中,电流互感器,电压互感器等需要对通过的原始电压、电流进行减小和转换,并且对于相差较大的电流信号需要选择不同的测量通道,再将频谱和电器特征值进行记录;在分析监测模式下,系统通过计算待测电器信号的频谱及测量所得电气特征值,并与已记录的模板进行匹配,从而判定电气类别,并实时显示电气类别、状态、电流。
关键词:STM32,CS5463,FFT,电气特征。
1.系统方案
1.1 用电器分析识别装置的原理和结构
1.用电器即是交流220V用电器,交流电方向随时间作周期性变化的电流,在一个周期变化的电流,在一个周期内的平均电流为零。不同于直流电,它的方向是会随着时间发生改变的,而直流电没有周期性变化。
2. 市面上的单相用电器检测装置一般分为隔离式和非隔离式,交流电主要的参数为频率,相位和幅值。在本设计中采用完全隔离的电压互感器和电流互感器来采样电压和电流。
3. 本装置的原理就是通过采集用电器流过的电压及电流来判断用电器的功率,再通过采集电压和电流的相位角即功率因数来判断用 电器的类型,比如我们热水器为纯电阻电路,电压和电流同相, 开关电源为非纯电阻电路,电压和电流不同相。
1.2 方案论证
1.2.1 系统供电论证和选择
对于供电只要求电流小于 15mA,对于电压没有要求。
方案一:使用市面普遍使用的阻容降压。阻容降压的工作原理 是利用电容在一定的交流信号频率下产生的容抗来限制最大工作电流。同时在电容器上串联一个阻性元件,则阻性元件两端所得到的电 压和它所产生的功耗完全取决于这个阻性元件的特性电容降压不能用于大功率负载,因为不安全。电容降压不适合动 态负载。同样,电容降压不适合容性和感性负载。
方案二:采用集成 220V 降压,PM01 是一款高效的小型开关 电源,这个模块非常适合小体积产品,AC-DC 模块,最大输出功率为 3W。且符合题意。
1.2.2 采样方法论证和选择
采样方法分为隔离采样和非隔离采样,隔离采样优点为安全,对于整个设备有很好的保护作用,而且抗电网的干扰。缺点是需要采用额外的采样元件,增加成本。非隔离采样优点是结构简单,成本低,以及使用广泛,缺点为对于后一级元件没有保护,对人体有危险。 所以在本系统中采用隔离方案。
1.2.3 采样芯片的型号选择
方案一:HLW8112
HLW8032 是一款高精度的电能计量IC,它采用 CMOS 制造工艺,主要用于单相应用。它能够 测量线电压和电流,并能计算有功功率,视在功率和功率因素。 该器件内部集成了两个∑-Δ型 ADC 和一个高精度的电能计量内核。
方案二:CS5463
CS5463 是一个包含两个ΔΣ模-数转换器(ADC)、功率计算功能、电能到频率转换器和一个串行接口的 完整的功率测量芯片。它可以精确测量瞬时电压,电流和计算IRMS、VRMS、瞬时功率、有功功率、无功功率,用于研制开发单相、2线或3线电表。
综上:相较于HLW8112,CS5463测量的数据更加全面,相较于HLW 8112,CS5463可以使用低成本的分流器或互感器测量电流,使用分压电阻或电压互感器测量电压且可以测出谐波,符合题意。
1.3 设计方案
一款基于STM32的用电器分析识别装置,本设计中采用完全隔离的电压互感器和电流互感器来采样电压和电流,该装置分为隔离式和非隔离式。由主回路模块和用电器分析监测装置模块组成。本装置可以通过学习模式来记录各种用电器的接入,能够识别学习后的用电器种类并显示其电器参数。用电器即是交流 220V 用电器,交流电是指电流方向随时间作 周期性变化的电流,主要的参数为频率,相位和幅值。
2.系统理论分析与计算
2.1 系统理论分析与计算
不会使用CSDN写公式,所以选择直接通过文档截图上传
3.硬件电路设计与程序设计
3.1 硬件电路分析
3.1.1 数据采集模块系统框图
图3- 1 数据采集模块系统框图
3.1.2 系统总框架图
系统总体框图如图所示,提供220V 电压输入给测试点,其中强电电源给CS5463芯片、STM32以及TFT彩屏供电。A、B测试点用来接入单相用电器特性参数测量仪。
图3- 2 系统总框架图
3.2 程序设计
3.2.1 程序功能描述
根据题目要求软件部分主要实现AD采集转换、控制彩屏显示和实现无线传输功能。
1)ADC部分:采集电路中用电器的特征参数(如电压、电流、功率、功率因数等),将其转换成数字量。
2)显示部分:显示用电器编号、工作状态、电流值、电压值等。
3.2.2 程序设计思路
不断采集数据并定义多个变量,将前后采集的数据不断对比,通过判断前后差值是否大于正常电路中该参数的波动幅度,来确定该用电器的工作状态,并输出其状态和参数。
在算法上,我们采用二进制模拟法,通过该方法我们将用电器的打开,关闭,分别对应二进制的0与1。通过C语言for循环遍历数组,从而得出我们预期的结果。如图所示我们通过二进制模拟,可以很清楚的看到用电器状态。
4.测试结果分析
基本要求:可识别七种用电器。可供测试的七种用电器:LED灯泡、交换机、热水壶、电风扇、锅、还有自制电器。
实物图片
图表 2
存在测量误差:由于使用不同的测量电器其内阻不同。因此所得到的电压值范围有所偏移。
数模(A / D)转换得到二进制代码,经过单片机控制响应时间不大于2,及识别代码从而识别用电器类型。通过显示器直接显示电源线上的电特征参数,电器的种类及其工作状态。
电阻自制一件最小电流的用电器,可以识别的最小电流值为5mA。
代码如下:
//--------------------------------------------------------------------------------------------------
// 包含的头文件 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
//--------------------------------------------------------------------------------------------------
#include "MAIN.h" // 包含全局头文件
#include "CS5463x1.h" // 包含外设头文件 CS5463x1-1路单相双向功率/电能芯片
/*
* 作者:PrairieOne
* csdn:PrairieOne
* 邮箱:prairieone1024@163.com
* 嵌入式技术交流群:826251093
*/
//--------------------------------------------------------------------------------------------------
// 宏自定义声明 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
//--------------------------------------------------------------------------------------------------
// CS5463x1 命令
#define CS5463x1_CMD_SYNC0 (0xFE) // CS5463x1 命令 结束串口重新初始化
#define CS5463x1_CMD_SYNC1 (0xFF) // CS5463x1 命令 开始串口重新初始化
#define CS5463x1_CMD_RESET (0x80) // CS5463x1 命令 软件复位
#define CS5463x1_CMD_STARTC (0xE8) // CS5463x1 命令 执行连续计算采集
#define CS5463x1_CMD_STARTS (0xE0) // CS5463x1 命令 执行单次计算采集
// CS5463x1 寄存器
#define CS5463x1_REG_R_CONFR (0x00) // CS5463x1 寄存器 读取 配置寄存器
#define CS5463x1_REG_W_CONFR (0x40) // CS5463x1 寄存器 写入 配置寄存器
#define CS5463x1_REG_R_I (0x0E) // CS5463x1 寄存器 读取 电流瞬时值寄存器
#define CS5463x1_REG_W_I (0x4E) // CS5463x1 寄存器 写入 电流瞬时值寄存器
#define CS5463x1_REG_R_V (0x10) // CS5463x1 寄存器 读取 电压瞬时值寄存器
#define CS5463x1_REG_W_V (0x50) // CS5463x1 寄存器 写入 电压瞬时值寄存器
#define CS5463x1_REG_R_P (0x12) // CS5463x1 寄存器 读取 功率瞬时值寄存器
#define CS5463x1_REG_W_P (0x52) // CS5463x1 寄存器 写入 功率瞬时值寄存器
#define CS5463x1_REG_R_PACTIVE (0x14) // CS5463x1 寄存器 读取 有功功率有效值寄存器
#define CS5463x1_REG_W_PACTIVE (0x54) // CS5463x1 寄存器 写入 有功功率有效值寄存器
#define CS5463x1_REG_R_IRMS (0x16) // CS5463x1 寄存器 读取 电流有效值寄存器
#define CS5463x1_REG_W_IRMS (0x56) // CS5463x1 寄存器 写入 电流有效值寄存器
#define CS5463x1_REG_R_VRMS (0x18) // CS5463x1 寄存器 读取 电压有效值寄存器
#define CS5463x1_REG_W_VRMS (0x58) // CS5463x1 寄存器 写入 电压有效值寄存器
#define CS5463x1_REG_R_FREQUENCY (0x1A) // CS5463x1 寄存器 读取 频率寄存器
#define CS5463x1_REG_W_FREQUENCY (0x5A) // CS5463x1 寄存器 写入 频率寄存器
#define CS5463x1_REG_R_STATUSR (0x1E) // CS5463x1 寄存器 读取 状态寄存器
#define CS5463x1_REG_W_STATUSR (0x5E) // CS5463x1 寄存器 读取 状态寄存器
#define CS5463x1_REG_STATUSR_BIT_DRDY (0x800000) // CS5463x1 状态寄存器 DRDY位 数据就绪
#define CS5463x1_REG_STATUSR_BIT_CRDY (0x100000) // CS5463x1 状态寄存器 CRDY位 转换就绪
#define CS5463x1_REG_STATUSR_BIT_TUP (0x000080) // CS5463x1 状态寄存器 TUP位 温度已更新
#define CS5463x1_REG_R_T (0x26) // CS5463x1 寄存器 读取 温度寄存器
#define CS5463x1_REG_W_ (0x66) // CS5463x1 寄存器 写入 温度寄存器
#define CS5463x1_REG_R_QAVG (0x28) // CS5463x1 寄存器 读取 无功功率平均值寄存器
#define CS5463x1_REG_W_QAVG (0x68) // CS5463x1 寄存器 写入 无功功率平均值寄存器
#define CS5463x1_REG_R_Q (0x2A) // CS5463x1 寄存器 读取 无功功率瞬时值寄存器
#define CS5463x1_REG_W_Q (0x6A) // CS5463x1 寄存器 写入 无功功率瞬时值寄存器
#define CS5463x1_REG_R_IPEAK (0x2C) // CS5463x1 寄存器 读取 电流峰峰值寄存器
#define CS5463x1_REG_W_IPEAK (0x6C) // CS5463x1 寄存器 写入 电流峰峰值寄存器
#define CS5463x1_REG_R_VPEAK (0x2E) // CS5463x1 寄存器 读取 电压峰峰值寄存器
#define CS5463x1_REG_W_VPEAK (0x6E) // CS5463x1 寄存器 写入 电压峰峰值寄存器
#define CS5463x1_REG_R_QTRIG (0x30) // CS5463x1 寄存器 读取 无功功率值寄存器 (用功率三角形计算)
#define CS5463x1_REG_W_QTRIG (0x70) // CS5463x1 寄存器 写入 无功功率值寄存器 (用功率三角形计算)
#define CS5463x1_REG_R_POWERFACTOR (0x32) // CS5463x1 寄存器 读取 功率因数寄存器
#define CS5463x1_REG_W_POWERFACTOR (0x72) // CS5463x1 寄存器 写入 功率因数寄存器
#define CS5463x1_REG_R_S (0x36) // CS5463x1 寄存器 读取 视在功率寄存器
#define CS5463x1_REG_W_S (0x76) // CS5463x1 寄存器 写入 视在功率寄存器
#define CS5463x1_REG_R_PH (0x3A) // CS5463x1 寄存器 读取 谐波有功功率寄存器
#define CS5463x1_REG_W_PH (0x7A) // CS5463x1 寄存器 写入 谐波有功功率寄存器
#define CS5463x1_REG_R_PF (0x3C) // CS5463x1 寄存器 读取 基波有功功率寄存器
#define CS5463x1_REG_W_PF (0x7C) // CS5463x1 寄存器 写入 基波有功功率寄存器
#define CS5463x1_REG_R_QF (0x3E) // CS5463x1 寄存器 读取 基波无功功率寄存器
#define CS5463x1_REG_W_QF (0x7E) // CS5463x1 寄存器 写入 基波无功功率寄存器
//添加的寄存器--------------------------------------------------------
#define READ_MASK 0xBF //读寄存器时的屏蔽码,与(写)地址相与
#define REG_CONFR 0x40 //配置
#define REG_CYCCONT 0x4A //一个计算周期的A/D转换数
#define REG_STATUSR 0x5E //状态
#define REG_MODER 0x64 //操作模式
#define REG_MASKR 0x74 //中断屏蔽
#define REG_CTRLR 0x78 //控制
//--------------------------------------------------------------------------------------------------
// 定义引用变量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
//--------------------------------------------------------------------------------------------------
CS5463x1_t CS5463x1_Info;
//--------------------------------------------------------------------------------------------------
// 硬件端口定义 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// 引用函数声明 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
//--------------------------------------------------------------------------------------------------
void CS5463x1_Init(void);
void CS5463x1_Hardware_Reset(void);
void CS5463x1_Software_Reset(void);
static void CS5463x1_WriteCommad(uint8_t Commad);
static void CS5463x1_WriteRegister_3Byte(uint8_t Register, uint8_t *Buffer);
static void CS5463x1_ReadRegister_3Byte(uint8_t Register, uint8_t *Buffer);
static uint32_t CS5463x1_GetRegisterValue_Status(void);
static void CS5463x1_ResetRegisterValue_Status(void);
//==================================================================================================
// 函数功能: CS5463x1 初始化
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
void CS5463x1_Init(void)
{
uint8_t Buffer[3] = {0x00};
// 芯片复位初始化
CS5463x1_Hardware_Reset();
CS5463x1_Software_Reset();
// 发送同步序列命令
CS5463x1_WriteCommad(CS5463x1_CMD_SYNC1);
CS5463x1_WriteCommad(CS5463x1_CMD_SYNC1);
CS5463x1_WriteCommad(CS5463x1_CMD_SYNC1);
CS5463x1_WriteCommad(CS5463x1_CMD_SYNC1);
CS5463x1_WriteCommad(CS5463x1_CMD_SYNC1);
CS5463x1_WriteCommad(CS5463x1_CMD_SYNC0);
//----------------------
//初始化--配置寄存器
//相位补偿为PC[6:0]=[0000000];
//电流通道增益为Igain=10;
//EWA=0;
//INT中断为低电平有效IMODE:IINV=[00]
//iCPU=0
//K[3:0]=[0001]
Buffer[0] = 0x00;
Buffer[1] = 0x00;
Buffer[2] = 0x01;
CS5463x1_WriteRegister_3Byte(CS5463x1_REG_W_CONFR, Buffer);
//----------------------
//初始化--操作寄存器
Buffer[0] = 0x00; //B0000_0000; //这是什么鬼 可以这样吗?
Buffer[1] = 0x00;//B0000_0000;
Buffer[2] = 0x60;//B0110_0000;
CS5463x1_WriteRegister_3Byte(REG_MODER,Buffer); //#define REG_MODER 0x64 //操作模式
//----------------------
//初始化--电流 交流偏置 校准寄存器
// RW24XX(Buffer,3,EE_IACBIAS,0xA1);
// CS5463x1_WriteRegister_3Byte(REG_IACOFF,Buffer);
//----------------------
//初始化--电流 增益校准寄存器
// RW24XX(Buffer,3,EE_IACGAIN,0xA1);
// CS5463x1_WriteRegister_3Byte(REG_IGN,Buffer);
//----------------------
//初始化--电压 交流偏置 校准寄存器
// RW24XX(Buffer,3,EE_VACBIAS,0xA1);
// CS5463x1_WriteRegister_3Byte(REG_VACOFF,Buffer);
//----------------------
//初始化--电压 增益校准寄存器
// RW24XX(Buffer,3,EE_VACGAIN,0xA1);
// CS5463x1_WriteRegister_3Byte(REG_VGN,Buffer);
//----------------------
Buffer[0] = 0x00;
Buffer[1] = 0x0F;
Buffer[2] = 0xA0; //#define REG_CYCCONT 0x4A //一个计算周期的A/D转换数
CS5463x1_WriteRegister_3Byte(REG_CYCCONT,Buffer); //初始化--CYCLE COUNT 寄存器,4000
//----------------------
//初始化--脉冲速率寄存器
// Buffer[0] = 0x00;
// Buffer[1] = 0x34;
// Buffer[2] = 0x9C;
// CS5463x1_WriteRegister_3Byte(REG_PULRATE,Buffer);
//----------------------
Buffer[0] = 0xFF;
Buffer[1] = 0xFF;
Buffer[2] = 0xFF;
CS5463x1_WriteRegister_3Byte(REG_STATUSR,Buffer); //初始化--状态寄存器 #define REG_STATUSR 0x5E //状态
//----------------------
Buffer[0] = 0x80; //开电流、电压、功率测量完毕中断
Buffer[1] = 0x00;
Buffer[2] = 0x80; //开温度测量完毕中断
CS5463x1_WriteRegister_3Byte(REG_MASKR,Buffer); //初始化--中断屏蔽寄存器 #define REG_MASKR 0x74 //中断屏蔽
//----------------------
Buffer[0] = 0x00;
Buffer[1] = 0x00;
Buffer[2] = 0x00;
CS5463x1_WriteRegister_3Byte(REG_CTRLR,Buffer); //初始化--控制寄存器 #define REG_CTRLR 0x78 //控制
//----------------------
CS5463x1_WriteCommad(CS5463x1_CMD_STARTC); //启动连续转换
DELAY_nMS(500);
}
//==================================================================================================
// 函数功能: CS5463x1 硬件复位
// 函数标记: 外设驱动函数
// 函数说明: 拉低RESET引脚保持至少10US实现芯片复位。
//==================================================================================================
void CS5463x1_Hardware_Reset(void)
{
CS5463x1_RST_GPIO_Output_L();
DELAY_nMS(10);
CS5463x1_RST_GPIO_Output_H();
DELAY_nMS(1000);
}
//==================================================================================================
// 函数功能: CS5463x1 软件复位
// 函数标记: 外设驱动函数
// 函数说明: 掉电/软件复位命令
//==================================================================================================
void CS5463x1_Software_Reset(void)
{
CS5463x1_WriteCommad(CS5463x1_CMD_RESET);
DELAY_nMS(10);
}
//==================================================================================================
// 函数功能: CS5463x1 写入命令 1个字节
// 函数标记: 外设驱动函数
// 函数说明: 第 0 位 默认为0
// 第1~6位 具体地址
// 第 7 位 设置1为读寄存器 设置0为写寄存器
// 地址先发送高位,即第 7 位
//==================================================================================================
static void CS5463x1_WriteCommad(uint8_t Commad)
{
CS5463x1_SPI_ChipSelectEnable(); // 片选使能有效
CS5463x1_SPI_SendReciveByte(Commad); // 写入命令
CS5463x1_SPI_ChipSelectDisable(); // 片选使能无效
}
//==================================================================================================
// 函数功能: CS5463x1 写入寄存器 3个字节
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
static void CS5463x1_WriteRegister_3Byte(uint8_t Register, uint8_t *Buffer)
{
uint8_t i = 0; // 定义局部变量 用于函数循环计数
CS5463x1_SPI_ChipSelectEnable(); // 片选使能有效
CS5463x1_SPI_SendReciveByte(Register); // 写入寄存器地址
for(i=0; i<3; i++)
{
CS5463x1_SPI_SendReciveByte((*(Buffer + i))); // 写入寄存器内容
}
CS5463x1_SPI_ChipSelectDisable(); // 片选使能无效
}
//==================================================================================================
// 函数功能: CS5463x1 读取寄存器 1个字节
// 函数标记: 外设驱动函数
// 函数说明: 第 0 位 默认为0
// 第1~6位 具体地址
// 第 7 位 设置1为读寄存器 设置0为写寄存器
// 地址先发送高位,即第 7 位
//==================================================================================================
static void CS5463x1_ReadRegister_3Byte(uint8_t Register, uint8_t *Buffer)
{
uint8_t i = 0; // 定义局部变量 用于函数循环计数
uint8_t Byte = 0x00; // 定义局部变量 用于函数返回数值
CS5463x1_SPI_ChipSelectEnable(); // 片选使能有效
CS5463x1_SPI_SendReciveByte(Register); // 写入寄存器地址
for(i=0; i<3; i++)
{
Byte = CS5463x1_SPI_SendReciveByte(0xFF); // 读取寄存器内容
(*(Buffer + i)) = Byte; // 提取到指定数组
}
CS5463x1_SPI_ChipSelectDisable(); // 片选使能无效
}
//==================================================================================================
// 函数功能: CS5463x1 获取状态寄存器
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
static uint32_t CS5463x1_GetRegisterValue_Status(void)
{
uint32_t Value = 0x000000;
uint8_t Buffer[3] = {0x00};
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_STATUSR, Buffer);
Value = ((uint32_t)Buffer[0]<<16) | ((uint32_t)Buffer[1]<<8) | ((uint32_t)Buffer[2]);
return Value;
}
//==================================================================================================
// 函数功能: CS5463x1 复位状态寄存器
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
static void CS5463x1_ResetRegisterValue_Status(void)
{
uint8_t Buffer[3] = {0xFF, 0xFF, 0xFF};
CS5463x1_WriteRegister_3Byte(CS5463x1_REG_W_STATUSR, Buffer);
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 电压有效值
// 函数标记: 外设驱动函数
// 函数说明: RMS为Root Mean Square 平方根,即有效值
//==================================================================================================
float CS5463x1_GetVoltageRMS(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 0.5; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取电压有效值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_VRMS, Buffer);
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 电压瞬时值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetVoltageNow(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
uint8_t Flag = 0; // 定义局部变量 用于变量临时保存
// 读取电压瞬时值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_V, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
Flag = 1;
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
if(1 == Flag)
{
Result = 0-Result;
}
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 电压峰峰值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetVoltagePeak(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取电压峰峰值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_VPEAK, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 电流有效值
// 函数标记: 外设驱动函数
// 函数说明: RMS为Root Mean Square 平方根,即有效值
//==================================================================================================
float CS5463x1_GetCurrentRMS(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 0.5; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取电流有效值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_IRMS, Buffer);
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电流比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 电流瞬时值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetCurrentNow(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
uint8_t Flag = 0; // 定义局部变量 用于变量临时保存
// 读取电流有效值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_I, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
Flag = 1;
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电流比例
if(1 == Flag)
{
Result = 0-Result;
}
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 电流峰峰值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetCurrentPeak(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取电流峰峰值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_IPEAK, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电流比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 功率瞬时值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerNow(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
uint8_t Flag = 0; // 定义局部变量 用于变量临时保存
// 读取功率瞬时值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_P, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
Flag = 1;
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
if(1 == Flag)
{
Result = 0-Result;
}
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 有功功率值
// 函数标记: 外设驱动函数
// 函数说明: 有功功率是指单位时间内实际发出或消耗的交流电能量,是周期内的平均功率。
//==================================================================================================
float CS5463x1_GetPowerActive(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取有功功率值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_PACTIVE, Buffer);
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 无功功率值(用功率三角形计算)
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerReactive(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取无功功率
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_QTRIG, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 视在功率值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerApparent(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取视在功率
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_S, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 无功功率瞬时值(90°移相)
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerReactiveNow(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取无功功率瞬时值(90°移相)
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_Q, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 无功功率平均值(90°移相)
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerReactiveAverage(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取无功功率平均值(90°移相)
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_QAVG, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 谐波有功功率值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerActiveHarmonic(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取谐波有功功率值
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_PH, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 基波有功功率值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerActiveFundamental(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 基波有功功率
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_PF, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 基波无功功率值
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerReactiveFundamental(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 基波无功功率
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_QF, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = Result * CS5463x1_FUNCTION_VScale; // 计算电压比例
Result = Result * CS5463x1_FUNCTION_IScale; // 计算电压比例
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 功率因数
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetPowerFactor(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取功率因素寄存器
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_POWERFACTOR, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 交流频率
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetFrequency(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 1.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_FREQUENCY,Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
Result = 4096000/1024*Result;
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值 温度
// 函数标记: 外设驱动函数
// 函数说明: 无
//==================================================================================================
float CS5463x1_GetTemperature(void)
{
uint8_t i = 0, j = 0; // 定义局部变量 用于函数循环计数
float G = 128.0; // 定义局部变量 用于权重计算保存
float Result = 0.0; // 定义局部变量 用于保存函数结果
uint8_t Temp = 0; // 定义局部变量 用于变量临时保存
uint8_t Buffer[3] = {0x00}; // 定义局部变量 用于变量临时保存
// 读取温度寄存器
CS5463x1_ReadRegister_3Byte(CS5463x1_REG_R_T, Buffer);
Temp = Buffer[0];
// 判断是否是负数
if(Temp&0x80)
{
//如果结果为负数 计算原码
Buffer[0] = ~Buffer[0];
Buffer[1] = ~Buffer[1];
Buffer[2] = ~Buffer[2];
}
while(i<3)
{
Temp = Buffer[i];
j = 0;
while(j<8)
{
if(Temp&0x80)
{
Result += G;
}
Temp <<= 1;
j++;
G = G/2;
}
i++;
}
return Result;
}
//==================================================================================================
// 函数功能: CS5463x1 获取数值
// 函数标记: 外设驱动函数
// 函数说明:
//==================================================================================================
uint8_t CS5463x1_GetValue(void)
{
uint32_t State = 0; // 定义局部变量 用于保存运行状态
State = CS5463x1_GetRegisterValue_Status(); // 读取状态寄存器
// 判断状态寄存器数据就绪位是否有效
if(CS5463x1_REG_STATUSR_BIT_DRDY == (State & CS5463x1_REG_STATUSR_BIT_DRDY))
{
// 如果数据就绪位有效
CS5463x1_ResetRegisterValue_Status(); // 复位状态寄存器
CS5463x1_Info.VoltageRMS = CS5463x1_GetVoltageRMS(); // 获取电压有效值
CS5463x1_Info.VoltageNow = CS5463x1_GetVoltageNow(); // 获取电压瞬时值
CS5463x1_Info.VoltagePeak = CS5463x1_GetVoltagePeak(); // 获取电压峰峰值
CS5463x1_Info.CurrentRMS = CS5463x1_GetCurrentRMS(); // 获取电流有效值
CS5463x1_Info.CurrentNow = CS5463x1_GetCurrentNow(); // 获取电流瞬时值
CS5463x1_Info.CurrentPeak = CS5463x1_GetCurrentPeak(); // 获取电流峰峰值
CS5463x1_Info.PowerFactor = CS5463x1_GetPowerFactor(); // 获取功率因素
CS5463x1_Info.Frequency = CS5463x1_GetFrequency(); // 获取交流频率
CS5463x1_Info.PowerNow = CS5463x1_GetPowerNow(); // 获取瞬时功率
CS5463x1_Info.PowerActive = CS5463x1_GetPowerActive(); // 获取有功功率
CS5463x1_Info.PowerReactive = CS5463x1_GetPowerReactive(); // 获取平均无功功率
CS5463x1_Info.PowerApparent = CS5463x1_GetPowerApparent(); // 获取瞬时无功功率
CS5463x1_Info.PowerReactiveNow = CS5463x1_GetPowerReactiveNow(); // 获取功率三角形的无功功率
CS5463x1_Info.PowerReactiveAverage = CS5463x1_GetPowerReactiveAverage(); // 获取视在功率
CS5463x1_Info.PowerActiveHarmonic = CS5463x1_GetPowerActiveHarmonic(); // 获取谐波有功功率
CS5463x1_Info.PowerActiveFundamental = CS5463x1_GetPowerActiveFundamental(); // 获取基波有功功率
CS5463x1_Info.PowerReactiveFundamental = CS5463x1_GetPowerReactiveFundamental(); // 获取基波无功功率
if(CS5463x1_REG_STATUSR_BIT_TUP == (State & CS5463x1_REG_STATUSR_BIT_TUP))
{
CS5463x1_Info.Temperature = CS5463x1_GetTemperature();
}
return CS5463x1_STATE_SUCCESS;
}
else
{
return CS5463x1_STATE_FAILURE;
}
}
遇事不决,可问春风!