此芯片性能不出差
HLW8012产品应用文档目录
摘要
1 硬件设计
11 参考设计图
111 非隔离采样应用电路
112 隔离采样应用电路
12 器件选型
121 采样电阻选型(非隔离方案)
122 互感器选型(隔离方案)
123 电源芯片选型
13 Layout说明
131 单路计量方案
132 2 路或2 路以上计量方案
2 软件设计
21 HLW8012 输入与输出的关系
22 脉冲频率(周期)的计算方法
23 软件设计流程图
24 参考代码文件
25 校准
3 HLW8012 性能数据
4 FAQ附录
5 硬件自查
1.2.1 采样电阻选型(非隔离方案)
HLW8012 的最大采样电流和采样电阻的大小相关,HLW8012的最大电流采样电压(即PIN2和 PIN3 之间的电压差)是30.9mV,
所以,最大采样电流 = 30.9mV/采样电阻阻值,以图 1 为例,采样电阻阻值为 1mR,则最大采样电流 = 30.9mV/1mR = 30.9A。
采样电阻分为锰铜电阻、鏮铜电阻、合金电阻和精密贴片电阻,一般设计 WIFI PLUG 产品以精密贴片电阻和鏮铜电阻比较多;
1.2.2 互感器选型(隔离方案)
电流互感器
以图2 为例,电流采样电阻R = 1Ω,假设电流互感器T1 的变比是1000:1,互感器的最大测量电流是50A,那么将此互感器接入采样电路,最大的测量电流和电阻有以下关系:
I /1000= 30.9mV/R,
I = (30.9mV/1Ω)*1000 = 30.9A
如果需要测量更大量程的电流,则在选定互感器后,然后调整采样电阻R,使得I*R<30.9mV 即可;
电压互感器
以图 2 为例,电压互感器 T2 的变比是 1000:1000,初级通过 5 个 20K 的电阻串接,初级电流 = 220V/(5*20K) = 2.2mA;T2的次级关联50R 的电阻,那么经过电压互感器 T2 转化成的电压 = 2.2mA*50R = 110mV,芯片 V2P的输入电压信号是110mV; 一般建议V2P的输入信号在100mV至 300mV之间,如果信号输入接近满幅值有效值时(490mV) ,噪声会变大,精度会下降。
1.2.3 电源芯片选型
HLW8012 的供电电源是 5V,工作电流是 3mA,工作电流非常小,所以一般电源都可以满足要求。设计图纸都是以 MPS 的 MP150 为例,还有许多非隔离芯片同样可以满足要求,比如芯朋的 PN8015和 PN8016,夕力杰的SY50281和 SY50282,还有昂宝的OB2222等。 下面以使非隔离电源AP8015为例为例,列举错误应用和正确应用。
错误的非隔离电源电路(GND和N 不是同一参考):
为什么需要GND和N选择同一参考?
因为 HLW8012 的信号采样采的是 L 和 N 的信号,信号线是以 N 为参考点,HLW8012 的内部采样电路是以 N 为参考点;另外,HLW8012 的供电电源是 5V 和 GND,是以 GND 为参考点,
同一系统需要保证参考点一致,才能进行信号采样,所以必须 GND和 N是同一参考点。 风险提示:如果不进行短接,那么信号端到 8012 的 PIN2 和 PIN 的电压大小是浮压,会有炸机的危险。
正确的非隔离电源电路(GND和N是同一参考) :
上图是以 N为参考地,那么是否可以使用 L做为参考地?
可以的,如果以L为参考地,那么只需将 L和N对调,其它不变,下图也是正确的。
1.3.1 单路计量方案
由于电流采样端最大输入信号是 30.9mV,以 测 量10A为例,如需分辩1mA,则相当于30.9mV需要等分 10000份,也就是芯片需要分辨3.09uV的信号,这个信号非常微弱,所以在设计PCB时,需对 GND需要小心处理,将GND噪声干扰降至最低。 一般会对 GND 分两路进行处理,使两个回路不会重合,不会相互影响,当两路回路不重合时,电源部分和数字部分的地噪声就不会影响到计量信号,如下图,电路回路1 和电路回路的走线相互不重合,只在入口处N 汇集于一点,这样数字信号就不会干扰到计量部分。
计量芯片Layout设计规则:
此 layout 设计规则适合于深圳市合力为科技的所有型号计量芯片,如 HLW8012、HLW8032和 HLW8110/HLW8112 等。
单路 PCB设计原则
电能计量芯片属于模拟器件芯片,它不同于数字芯片,对模拟器件的 layout 需要遵 守一些设计原则,以使芯片发挥最大性能,以下共有 10 条设计原则,请尽量遵守,若 不能遵守,可能会引起一些如数值不稳定,小信号噪声大等问题,实际情况以 PCB 样 板实测结果为准。 1、 去藕电容放置规则 芯片电源引脚处的0.1uf的去耦电容尽量靠近芯片的引脚,这样才能起到比较好的滤 波效果。
2、 电压通道设计规则 电压通道电阻分压网络,应呈阶梯式分布,逐渐降压(从输入端降压直至计 量芯片的取样电压),应注意电阻与电阻之间的爬电距离。
3、 电压通道和电流通道应尽可能不进行交叉走线
交叉走线后会引起信号噪声,对于小信号的测量结果不准确,对大信号的影响比较 小,如果必须交叉,也应该是电压通道经过分压(降低电压值)之后的线与电流信号线交 叉,下图是没有交叉的走线。 4、 差分信号线布线规则
a)差分信号线应走平行线,且两条平行走线应当尽量靠近,这样可以减少外部 信号的干扰; b)差分信号线应从采样电阻两端引线,且与采样电阻的 PAD直接相连,差分信
号线路径没有电流回路流过。
正确的走线(从采样电阻 Pad上引出差分信号线)
错误的走线(没有从采样电阻 Pad上引出差分信号线)
上述接法会带来误差,采样电阻 r的阻值实际上己经不是 r了,而是
r+R1+R2,如下图,因为铜皮也是有阻抗的,且铜皮的温度特性非常差,这种接 法带来的结果是在小电流时,信号输出是线性关系,当电流过大时,随着 PCB温度的上升,整个输入量程程的输出信号会成不线性关系。
c)差分信号线有一根线是 GND,应把他当作信号线来看待,不能当做 GND来处 理,更不能同其它 GND线相连(只能在 GND地入口处相连),如下图: 正确的接法:
上述在入口焊盘处相连,实际相当于是 GND入口分出两条线,走星形线,
这样处理实际是避免将 GND的噪声(比如电源的噪声)引入到差分信号端。
错误的接法:
上图是错误的接法,因为电路回路的 GND经过采样电阻再回到入口焊盘 N,这样 会板子上的电源地噪声引入到采样电阻的差分信号上。
多路 PCB 设计原则
在使用多路计量电路的设计中,同样需要注意 GND 的处理,如果布局不合理,每一路计 量电路就会相互产生干扰。为避免每一路计量电路之间的相互干扰,地线需要采用星形 地线的布局方式,参考布局方法如下:
正确的连接方式:
单片机源程序如下:
- /*=============================================================================
- * File Name : HLW8012参考例程
- * Describe : 测量功率、电压、电流及电量参数
- * Author : 深圳合力为
- * Version : V1.0
- =============================================================================*/
- /* Includes -----------------------------------------------------------------*/
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //Time1定时器定时,时间基数 = 1ms
- #define D_TIME1_20MS 20
- #define D_TIME1_100MS 100
- #define D_TIME1_150MS 150
- #define D_TIME1_200MS 200
- #define D_TIME1_400MS 400
- #define D_TIME1_500MS 500
- #define D_TIME1_1S 1000 //Time1定时器定时1S时间常数
- #define D_TIME1_2S 2000
- #define D_TIME1_3S 2000
- #define D_TIME1_4S 4000
- #define D_TIME1_6S 6000
- #define D_TIME1_8S 8000
- #define D_TIME1_9S 9000
- #define D_TIME1_10S 10000
- #define D_TIME1_20S 20000
- #define D_TIME1_V_OVERFLOW 500 //Time1定时器,电压溢出常数设定为500mS,溢出说明脉宽周期大于500mS
- #define D_TIME1_I_OVERFLOW 8000 //Time1定时器,电流溢出常数设定为10S,溢出说明脉宽周期大于10S
- #define D_TIME1_P_OVERFLOW 12000 //Time1定时器,功率溢出常数设定为10S(约0.5W最小值),溢出说明脉宽周期大于10S
- //#define D_TIME1_P_OVERFLOW 40000 //Time1定时器,功率溢出常数设定为40S(约0.2W最小值)
- #define D_TIME1_CAL_TIME 36000 //校正时间,记录在此时间内的脉冲数,1000W负载在用电36S时间内耗费0.01度电
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //HLW 8012 IO设置
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- #define IO_HLW8012_CF1_S PD_ODR_ODR3 //HLW8012 PIN8
- #define IO_HLW8012_CF1 PA_IDR_IDR2 //HLW8012 PIN7
- #define IO_HLW8012_CF PC_IDR_IDR5 //HLW8012 PIN6
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //工作模式
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- #define D_ERR_MODE 0x00 //错误提示模式
- #define D_NORMAL_MODE 0x10 //正常工作模式
- #define D_CAL_START_MODE 0x21 //校正模式,启动
- #define D_CAL_END_MODE 0x23 //校正模式,完成
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //ROM定义
- //--------------------------------------------------------------------------------------------
- #define u1 _Bool
- #define u8 unsigned char
- #define u16 unsigned int
- #define u32 unsigned long
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- union IntData
- {
- u16 inte;
- u8 byte[2];
- };
- union LongData
- {
- u32 word;
- u16 inte[2];
- u8 byte[4];
- };
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- u16 U16_P_TotalTimes; //当前脉冲 功率测量总时间
- u16 U16_V_TotalTimes; //当前脉冲 电压测量总时间
- u16 U16_I_TotalTimes; //当前脉冲 电流测量总时间
- u16 U16_P_OneCycleTime; //功率测量时间参数
- u16 U16_V_OneCycleTime; //电压测量时间参数
- u16 U16_I_OneCycleTime; //电流测量时间参数
- u16 U16_P_Last_OneCycleTime; //功率测量时间参数,上一次数量值
- u16 U16_V_Last_OneCycleTime; //电压测量时间参数,上一次数量值
- u16 U16_I_Last_OneCycleTime; //电流测量时间参数,上一次数量值
- u16 U16_P_CNT; //功率测量脉冲数量
- u16 U16_V_CNT; //电压测量脉冲数量
- u16 U16_I_CNT; //电流测量脉冲数量
- u16 U16_P_Last_CNT; //功率测量脉冲数量,上一次数量值
- u16 U16_V_Last_CNT; //电压测量脉冲数量,上一次数量值
- u16 U16_I_Last_CNT; //电流测量脉冲数量,上一次数量值
- u1 B_P_TestOneCycle_Mode; //功率测量模式 1:单周期测量,0:1S定时测量
- u1 B_V_TestOneCycle_Mode;
- u1 B_I_TestOneCycle_Mode;
- u1 B_P_Last_TestOneCycle_Mode;
- u1 B_V_Last_TestOneCycle_Mode;
- u1 B_I_Last_TestOneCycle_Mode;
-
- u1 B_P_OVERFLOW; // 功率脉冲周期 溢出标志位
- u1 B_V_OVERFLOW; // 电压脉冲周期 溢出标志位
- u1 B_I_OVERFLOW; // 电流脉冲周期 溢出标志位
- u1 B_P_Last_OVERFLOW; // 功率脉冲周期 溢出标志位
- u1 B_V_Last_OVERFLOW; // 电压脉冲周期 溢出标志位
- u1 B_I_Last_OVERFLOW; // 电流脉冲周期 溢出标志位
- u1 B_VI_Test_Mode; //1:电压测量模式;0:电流测量模式
- u16 U16_VI_Test_Times;
- u16 U16_Cal_Times;
- u16 U16_AC_P; //功率值 1000.0W
- u16 U16_AC_V; //电压值 220.0V
- u16 U16_AC_I; //电流值 4.545A
- u32 U32_AC_E; //用电量 0.01度
- u32 U32_AC_BACKUP_E; //用电量备份
- u8 U8_AC_COS; //功率因素 0.00
- u16 U16_REF_001_E_Pluse_CNT; //0.01度电脉冲总数参考值
- u16 U16_E_Pluse_CNT; //脉冲个数寄存器
- u32 U32_Cal_Times; //校正时间
- u32 U32_P_REF_PLUSEWIDTH_TIME; //参考功率 脉冲周期
- u32 U32_V_REF_PLUSEWIDTH_TIME; //参考电压 脉冲周期
- u32 U32_I_REF_PLUSEWIDTH_TIME; //参考电流 脉冲周期
- u32 U32_P_CURRENT_PLUSEWIDTH_TIME; //当前功率 脉冲周期
- u32 U32_V_CURRENT_PLUSEWIDTH_TIME; //当前电压 脉冲周期
- u32 U32_I_CURRENT_PLUSEWIDTH_TIME; //当前电流 脉冲周期
- u16 U16_P_REF_Data; //参考功率值,如以1000W校正。1000.0W
- u16 U16_V_REF_Data; //参考电压 220.0V
- u16 U16_I_REF_Data; //参考电流 1000W,220V条件下是4.545A
- u8 U8_CURR_WorkMode;
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- void main(void)
- {
- //初始化MCU
- //初始化ROM
- Init_Rom();
- //读取存放于EEPROM的校正数据
- Read_CalData_EEPROM(); //读取参考功率、参考电压、参考电流的脉冲周期
-
- while(1)
- {
- if (B_KeyScanEn == TRUE)
- {
- ScaningKey(); //按键
- KeyFun_NormalMode();
- }
-
- if (U8_CURR_WorkMode == D_NORMAL_MODE)
- {
- HLW8012_Measure(); //计算功率、电压、电流
- }
- else if (U8_CURR_WorkMode == D_CAL_END_MODE) //校正模式
- {
- //记录校正值,将当前功率、电压、电流值存入EEPROM;将0.01度电的脉冲数参值也存入EEPROM
- Write_CalData_EEPROM();
- //读取校正值,将用电量清零
- Read_CalData_EEPROM();
- //返回测量模式
- U8_CURR_WorkMode = D_NORMAL_MODE;
- }
-
- }
- }
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- /*=====================================================
- * Function : void Init_Rom(void)
- * Describe : rom空间初始化
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void Init_Rom(void)
- {
- U8_CURR_WorkMode = D_NORMAL_MODE;
- U8_DspMode = 0;
-
- U16_AC_P = 0;
- U16_AC_V = 0;
- U16_AC_I = 0;
- U8_AC_COS = 0;
-
- U16_P_TotalTimes = 0;
- U16_V_TotalTimes = 0;
- U16_I_TotalTimes = 0;
-
- U16_P_OneCycleTime = 0;
- U16_V_OneCycleTime = 0;
- U16_I_OneCycleTime = 0;
- U16_P_Last_OneCycleTime = 0;
- U16_V_Last_OneCycleTime = 0;
- U16_I_Last_OneCycleTime = 0;
-
- U16_P_CNT = 0;
- U16_V_CNT = 0;
- U16_I_CNT = 0;
- U16_P_Last_CNT = 0;
- U16_V_Last_CNT = 0;
- U16_I_Last_CNT = 0;
-
- //初始化单周期测量模式
- B_P_TestOneCycle_Mode = 1;
- B_V_TestOneCycle_Mode = 1;
- B_I_TestOneCycle_Mode = 1;
- B_P_Last_TestOneCycle_Mode = 1;
- B_V_Last_TestOneCycle_Mode = 1;
- B_I_Last_TestOneCycle_Mode = 1;
- //开始测量,置溢出标志位为1
- B_P_OVERFLOW = 1;
- B_V_OVERFLOW = 1;
- B_I_OVERFLOW = 1;
-
- B_P_Last_OVERFLOW = 1;
- B_V_Last_OVERFLOW = 1;
- B_I_Last_OVERFLOW = 1;
-
- //上电初始化为电压测试模式
- B_VI_Test_Mode = 1;
- IO_HLW8012_CF1_S = 1;
- U16_VI_Test_Times = D_TIME1_2S;
-
- //显示初始化
- U8_DspMode = 0;
- B_DIS_EN = FALSE;
- U16_SendUart_Time = 0;
-
- }
- /*=====================================================
- * 函数名称: PC中断,IO---PC5
- * 函数功能: CF中断 功率测量
- * 输入参数: 无
- * 输出参数:
- * 返 回:
- =====================================================*/
- #pragma vector = 7
- __interrupt void PC5_EXTI_Interrupt(void)
- {
- //功率测量
- U16_P_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_P_CNT++;
- if (B_P_OVERFLOW == TRUE)
- {
- //从溢出模式转入,开始测量
- B_P_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_P_TotalTimes = 0; //清溢出寄存器清零
- U16_P_OneCycleTime = 0; //清测量寄存器
- U16_P_CNT = 1;
- B_P_OVERFLOW = FALSE; //清溢出标志位
- }
- else
- {
- if (B_P_TestOneCycle_Mode == 1)
- {
- if (U16_P_OneCycleTime >= D_TIME1_100MS)
- {
- //单周期测量模式
- U16_P_Last_OneCycleTime = U16_P_OneCycleTime;
- B_P_Last_TestOneCycle_Mode = B_P_TestOneCycle_Mode;
- B_P_OVERFLOW = FALSE; //溢出标志位清零
- B_P_Last_OVERFLOW = B_P_OVERFLOW;
- //清状态参数,重新开始测试
- B_P_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_P_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_P_OneCycleTime = 0; //清测量寄存器
- U16_P_CNT = 1;
-
- }
- }
- else
- {
- if (U16_P_OneCycleTime >= D_TIME1_1S)
- {
- U16_P_Last_OneCycleTime = U16_P_OneCycleTime;
- U16_P_Last_CNT = U16_P_CNT;
- B_P_Last_TestOneCycle_Mode = B_P_TestOneCycle_Mode;
- B_P_OVERFLOW = FALSE; //溢出标志位清零
- B_P_Last_OVERFLOW = B_P_OVERFLOW;
- //清状态参数,重新开始测试
- B_P_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_P_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_P_OneCycleTime = 0; //清测量寄存器
- U16_P_CNT = 1;
- }
- }
- }
-
-
- //校正模式
- if (U8_CURR_WorkMode == D_CAL_START_MODE)
- {
- //记录单位时间内的用电量
- U16_E_Pluse_CNT++;
- }
-
- //用电量计量,每0.01度电,用电量寄存器增加0.01度
- if (U8_CURR_WorkMode == D_NORMAL_MODE)
- {
- U16_E_Pluse_CNT++;
- if (U16_E_Pluse_CNT == U16_REF_001_E_Pluse_CNT )
- {
- U16_E_Pluse_CNT = 0;
- U32_AC_E++;
- }
- }
- }
- /*=====================================================
- * 函数名称: PD中断,IO---PD2
- * 函数功能: CF1中断 电压、电流测量
- * 输入参数:
- * 输出参数:
- * 返 回:
- =====================================================*/
- #pragma vector = 8
- __interrupt void PD2_EXTI_Interrupt(void)
- {
-
- //电压测试模式
- if (B_VI_Test_Mode == 1)
- {
- U16_V_TotalTimes = 0;
- U16_V_CNT++;
- if (B_V_OVERFLOW == TRUE)
- {
- //从溢出模式转入,开始测量
- B_V_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_V_TotalTimes = 0; //清溢出寄存器清零
- U16_V_OneCycleTime = 0; //清测量寄存器
- U16_V_CNT = 1;
- B_V_OVERFLOW = FALSE; //清溢出标志位
- }
- else
- {
- if (B_V_TestOneCycle_Mode == 1)
- {
- if (U16_V_OneCycleTime >= D_TIME1_100MS)
- {
- //单周期测量模式
- U16_V_Last_OneCycleTime = U16_V_OneCycleTime;
- B_V_Last_TestOneCycle_Mode = B_V_TestOneCycle_Mode;
- B_V_OVERFLOW = FALSE; //溢出标志位清零
- B_V_Last_OVERFLOW = B_V_OVERFLOW;
- //清状态参数,重新开始测试
- B_V_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_V_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_V_OneCycleTime = 0; //清测量寄存器
- U16_V_CNT = 1;
- }
- }
- else
- {
- if (U16_V_OneCycleTime >= D_TIME1_200MS)
- {
- U16_V_Last_OneCycleTime = U16_V_OneCycleTime;
- U16_V_Last_CNT = U16_V_CNT;
- B_V_Last_TestOneCycle_Mode = B_V_TestOneCycle_Mode;
- B_V_OVERFLOW = FALSE; //溢出标志位清零
- B_V_Last_OVERFLOW = B_V_OVERFLOW;
- //清状态参数,重新开始测试
- B_V_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_V_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_V_OneCycleTime = 0; //清测量寄存器
- U16_V_CNT = 1;
- B_V_OVERFLOW = FALSE; //溢出标志位清零
- }
- }
- }
- }
- //电流测试模式
- if (B_VI_Test_Mode == 0)
- {
- U16_I_TotalTimes = 0;
- U16_I_CNT++;
- if (B_I_OVERFLOW == TRUE)
- {
- //从溢出模式转入,开始测量
- B_I_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_I_TotalTimes = 0; //清溢出寄存器清零
- U16_I_OneCycleTime = 0; //清测量寄存器
- U16_I_CNT = 1;
- B_I_OVERFLOW = FALSE; //清溢出标志位
- }
- else
- {
- if (B_I_TestOneCycle_Mode == 1)
- {
- if (U16_I_OneCycleTime >= D_TIME1_100MS)
- {
- //单周期测量模式
- U16_I_Last_OneCycleTime = U16_I_OneCycleTime;
- B_I_Last_TestOneCycle_Mode = B_I_TestOneCycle_Mode;
- B_I_OVERFLOW = FALSE; //溢出标志位清零
- B_I_Last_OVERFLOW = B_I_OVERFLOW;
- //清状态参数,重新开始测试
- B_I_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_I_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_I_OneCycleTime = 0; //清测量寄存器
- U16_I_CNT = 1;
- }
- }
- else
- {
- if (U16_I_OneCycleTime >= D_TIME1_1S)
- {
- U16_I_Last_OneCycleTime = U16_I_OneCycleTime;
- U16_I_Last_CNT = U16_I_CNT;
- B_I_Last_TestOneCycle_Mode = B_I_TestOneCycle_Mode;
- B_I_OVERFLOW = FALSE; //溢出标志位清零
- B_I_Last_OVERFLOW = B_I_OVERFLOW;
- //清状态参数,重新开始测试
- B_I_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- U16_I_TotalTimes = 0; //完成一次有效的测量,溢出寄存器清零
- U16_I_OneCycleTime = 0; //清测量寄存器
- U16_I_CNT = 1;
- }
- }
- }
- }
- }
- /*=====================================================
- * 函数名称: TIM1
- * 函数功能: 测量功率、电压、电流
- * 输入参数:
- * 输出参数:
- * 返 回:
- =====================================================*/
- #pragma vector = 13
- __interrupt void TIM1_UPD_Interrupt(void)
- {
- //校正模式
- if (U8_CURR_WorkMode == D_CAL_START_MODE)
- {
- U32_Cal_Times++;//校正时间36S,1000W负载36S时间消耗0.01度电
- if (U32_Cal_Times == D_TIME1_CAL_TIME)
- {
- U8_CURR_WorkMode = D_CAL_END_MODE;
- U16_REF_001_E_Pluse_CNT = U16_E_Pluse_CNT; //记录36S时间内的脉冲数,此脉冲数表示0.01度用电量
- }
- }
-
- //功率测量
- if (U16_P_CNT != 0)
- {
- U16_P_OneCycleTime++;
- U16_P_TotalTimes++;
- }
- if (U16_P_TotalTimes >= D_TIME1_P_OVERFLOW)
- {
- B_P_OVERFLOW = TRUE; //溢出,
- B_P_Last_OVERFLOW = B_P_OVERFLOW;
- //清状态参数,重新开始测试
- U16_P_TotalTimes = 0; //清溢出寄存器
- U16_P_OneCycleTime = 0;
- U16_P_CNT = 0; //等待下一次中断开始计数
- B_P_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- }
- else if (U16_P_OneCycleTime == D_TIME1_100MS)
- {
- if (U16_P_CNT < 2)
- {
- // 100ms内只有一次中断,说明周期>100ms,采用单周期测量模式
- B_P_TestOneCycle_Mode = 1;
- }
- else
- {
- // 100ms内有2次或以上数量脉冲,说明周期<100ms,采用计数脉冲测量模式
- B_P_TestOneCycle_Mode = 0;
- }
- }
-
- //电压、电流测量
- if (B_VI_Test_Mode == 1)
- {
- //电压测量
- if (U16_V_CNT != 0)
- {
- U16_V_OneCycleTime++;
- U16_V_TotalTimes++;
- }
- if (U16_V_TotalTimes >= D_TIME1_V_OVERFLOW)
- {
- B_V_OVERFLOW = TRUE;
- B_V_Last_OVERFLOW = B_V_OVERFLOW;
- //清状态参数,重新开始测试
- U16_V_TotalTimes = 0; //清溢出寄存器
- U16_V_OneCycleTime = 0;
- U16_V_CNT = 0;
- B_V_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- }
- else if (U16_V_OneCycleTime == D_TIME1_100MS)
- {
- if (U16_V_CNT < 2)
- {
- // 100ms内只有一次中断,说明周期>100ms,采用单周期测量模式
- B_V_TestOneCycle_Mode = 1;
- }
- else
- {
- // 100ms内有2次或以上数量脉冲,说明周期<100ms,采用计数脉冲测量模式
- B_V_TestOneCycle_Mode = 0;
- }
- }
- }
- else
- {
- //电流测量
- if (U16_I_CNT != 0)
- {
- U16_I_OneCycleTime++;
- U16_I_TotalTimes++;
- }
- if (U16_I_TotalTimes >= D_TIME1_I_OVERFLOW)
- {
- B_I_OVERFLOW = TRUE;
- B_I_Last_OVERFLOW = B_I_OVERFLOW;
- //清状态参数,重新开始测试
- U16_I_TotalTimes = 0; //清溢出寄存器
- U16_I_OneCycleTime = 0;
- U16_I_CNT = 0;
- B_I_TestOneCycle_Mode = 0; //初始化为计数脉冲测量模式
- }
- else if (U16_I_OneCycleTime == D_TIME1_100MS)
- {
- if (U16_I_CNT < 2)
- {
- // 100ms内只有一次中断,说明周期>100ms,采用单周期测量模式
- B_I_TestOneCycle_Mode = 1;
- }
- else
- {
- // 100ms内有2次或以上数量脉冲,说明周期<100ms,采用计数脉冲测量模式
- B_I_TestOneCycle_Mode = 0;
- }
- }
- }
-
- //电压、电流测量模式切换 B_VI_Test_Mode:(1:电压测量模式) (0:电流测试模式)
- U16_VI_Test_Times--;
- if (U16_VI_Test_Times == 0)
- {
- if (B_VI_Test_Mode == 1)
- {
- //转为电流测量模式
- B_VI_Test_Mode = 0;
- IO_HLW8012_CF1_S = 0;
- U16_VI_Test_Times = D_TIME1_10S;
-
- //清状态参数
- U16_I_TotalTimes = 0;
- U16_I_OneCycleTime = 0;
- U16_I_CNT = 0;
- B_I_OVERFLOW = FALSE;
- }
- else
- {
- //转为电压测量模式
- B_VI_Test_Mode = 1;
- IO_HLW8012_CF1_S = 1;
- U16_VI_Test_Times = D_TIME1_1S;
-
- //清状态参数
- U16_V_TotalTimes = 0;
- U16_V_OneCycleTime = 0;
- U16_V_CNT = 0;
- B_V_OVERFLOW = FALSE;
- }
- }
-
- //按键扫描,20mS一次
- U8_KeyScanTimes++;
- if (U8_KeyScanTimes > D_TIME1_20MS)
- {
- B_KeyScanEn = TRUE;
- U8_KeyScanTimes = 0;
- }
-
- // 每0.5S串口发送一次数据
- U16_SendUart_Time++;
- if (U16_SendUart_Time == D_TIME1_500MS)
- {
- B_DIS_EN = TRUE;
- U16_SendUart_Time = 0;
- }
- // Clear TIM1 INT FLAG
- TIM1_SR1 = 0x00;
- }
- /*-------------------------------------------- 功率、电压、电流计算 -------------------------------------------*/
- *=====================================================
- * Function : void HLW8012_Measure_P(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_P(void)
- {
- u32 a;
- u32 b;
- u32 u32_P_Period;
-
- if (B_P_Last_TestOneCycle_Mode == 1)
- {
- //单周期测量模式
- b = U16_P_Last_OneCycleTime;
- b = b*1000; //ms转换成us
- u32_P_Period = b;
- }
- else
- {
- //计数脉冲测量模式
- b = U16_P_Last_OneCycleTime;
- b = b*1000;
- u32_P_Period = b/(U16_P_Last_CNT-1);
- }
-
- U32_P_CURRENT_PLUSEWIDTH_TIME = u32_P_Period; // 校正时取U32_P_CURRENT_PLUSEWIDTH_TIME参数作为参考值
- a = U16_P_REF_Data * U32_P_REF_PLUSEWIDTH_TIME;
- U16_AC_P = a/U32_P_CURRENT_PLUSEWIDTH_TIME;
-
- if (U16_AC_P == 0xffff) //开机时U32_P_CURRENT_PLUSEWIDTH_TIME = 0,计算溢出
- {
- U16_AC_P = 0;
- }
-
- if (B_P_Last_OVERFLOW == TRUE)
- {
- U16_AC_P = 0;
- }
- }
- /*=====================================================
- * Function : void HLW8012_Measure_V(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_V(void)
- {
- u32 a;
- u32 b;
- u32 u32_V_Period;
-
- if (U16_VI_Test_Times < D_TIME1_100MS)
- {
- if (B_V_Last_TestOneCycle_Mode == 1)
- {
- b = U16_V_Last_OneCycleTime;
- u32_V_Period = b * 1000; //ms转换成us
- U32_V_CURRENT_PLUSEWIDTH_TIME = u32_V_Period;
- }
- else
- {
- b = U16_V_Last_OneCycleTime;
- b = b*1000;
- u32_V_Period = b/(U16_V_Last_CNT-1);
- //u32_V_Period = b/U16_V_Last_CNT;
- U32_V_CURRENT_PLUSEWIDTH_TIME = u32_V_Period;
- }
- }
-
- a = U16_V_REF_Data * U32_V_REF_PLUSEWIDTH_TIME;
- U16_AC_V = a/U32_V_CURRENT_PLUSEWIDTH_TIME;
-
- if (U16_AC_V == 0xffff) //开机时U32_V_CURRENT_PLUSEWIDTH_TIME = 0,计算溢出
- {
- U16_AC_V = 0;
- }
-
- if (B_V_Last_OVERFLOW == TRUE)
- {
- U16_AC_V = 0;
- }
-
- if (U16_AC_P == 0)
- {
- U16_AC_V = 0;
-
- }
- }
- /*=====================================================
- * Function : void HLW8012_Measure_I(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_I(void)
- {
- u32 a;
- u32 b;
- u32 u32_I_Period;
-
- if (U16_VI_Test_Times < D_TIME1_6S)
- {
- if (B_I_Last_TestOneCycle_Mode == 1)
- {
- b = U16_I_Last_OneCycleTime;
- u32_I_Period = b * 1000; //ms转换成us
- U32_I_CURRENT_PLUSEWIDTH_TIME = u32_I_Period;
- }
- else
- {
- b = U16_I_Last_OneCycleTime;
- b = b*1000;
- u32_I_Period = b/(U16_I_Last_CNT-1);
- //u32_I_Period = b/U16_I_Last_CNT;
- U32_I_CURRENT_PLUSEWIDTH_TIME = u32_I_Period;
- }
- }
-
-
- a = U16_I_REF_Data * U32_I_REF_PLUSEWIDTH_TIME;
- U16_AC_I = a/U32_I_CURRENT_PLUSEWIDTH_TIME;
-
-
- if (U16_AC_I > 180)
- {
- if (U16_AC_I != 0xffff)
- {
- NOP();
- NOP();
- }
- }
-
- if (U16_AC_P == 0)
- {
- U16_AC_I = 0;
-
- }
-
- if (U16_AC_I == 0xffff) //开机时U32_I_CURRENT_PLUSEWIDTH_TIME = 0,计算溢出
- {
- U16_AC_I = 0;
- }
-
- if (B_I_OVERFLOW == TRUE)
- {
- U16_AC_I = 0;
- }
- }
- /*=====================================================
- * Function : void HLW8012_Measure_COS(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_COS(void)
- {
- u32 u32_P_Apparent;
- u32 a;
- u8 b;
- u32_P_Apparent = (u32)U16_AC_I*(u32)U16_AC_V;
- u32_P_Apparent = u32_P_Apparent/1000;
- a = U16_AC_P;
- a = a*100;
-
- b = (u8)(a/u32_P_Apparent);
- if (b > 100 )
- U8_AC_COS = 100; //由于相位延时造成的功率因素>1的情况,功率因素取值1
- else
- U8_AC_COS = b;
- }
- /*=====================================================
- * Function : void HLW8012_Measure_E(void)
- * Describe : 每1度电存储一次
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
全部资料51hei下载地址:
HLW8012设计资料REV30.7z
(11.34 MB, 下载次数: 689)
|