找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 26895|回复: 53
收起左侧

功率计量芯片HLW8012硬件PCB与单片机软件源码设计资料下载

  [复制链接]
ID:370666 发表于 2018-7-23 08:18 | 显示全部楼层 |阅读模式
此芯片性能不出差
无标题.png 0.png

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 不是同一参考):
0.png
为什么需要GND和N选择同一参考?
因为 HLW8012 的信号采样采的是 L 和 N 的信号,信号线是以 N 为参考点,HLW8012 的内部采样电路是以 N 为参考点;另外,HLW8012 的供电电源是 5V 和 GND,是以 GND 为参考点,
同一系统需要保证参考点一致,才能进行信号采样,所以必须 GND和 N是同一参考点。 风险提示:如果不进行短接,那么信号端到 8012 的 PIN2 和 PIN 的电压大小是浮压,会有炸机的危险。

正确的非隔离电源电路(GND和N是同一参考) :
0.png
上图是以 N为参考地,那么是否可以使用 L做为参考地?
可以的,如果以L为参考地,那么只需将 L和N对调,其它不变,下图也是正确的。
0.png
1.3.1  单路计量方案
由于电流采样端最大输入信号是 30.9mV,以 测 量10A为例,如需分辩1mA,则相当于30.9mV需要等分 10000份,也就是芯片需要分辨3.09uV的信号,这个信号非常微弱,所以在设计PCB时,需对 GND需要小心处理,将GND噪声干扰降至最低。  一般会对 GND 分两路进行处理,使两个回路不会重合,不会相互影响,当两路回路不重合时,电源部分和数字部分的地噪声就不会影响到计量信号,如下图,电路回路1 和电路回路的走线相互不重合,只在入口处N 汇集于一点,这样数字信号就不会干扰到计量部分。
0.png


计量芯片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 的处理,如果布局不合理,每一路计 量电路就会相互产生干扰。为避免每一路计量电路之间的相互干扰,地线需要采用星形 地线的布局方式,参考布局方法如下:
正确的连接方式:

0.png


单片机源程序如下:


  1. /*=============================================================================
  2.   * File Name             : HLW8012参考例程
  3.   * Describe              : 测量功率、电压、电流及电量参数
  4.   * Author             : 深圳合力为
  5.   * Version             : V1.0
  6. =============================================================================*/
  7. /* Includes -----------------------------------------------------------------*/

  8. //--------------------------------------------------------------------------------------------
  9. //--------------------------------------------------------------------------------------------
  10. //Time1定时器定时,时间基数 = 1ms
  11. #define D_TIME1_20MS                                20               
  12. #define D_TIME1_100MS                                100        
  13. #define D_TIME1_150MS                                150        
  14. #define D_TIME1_200MS                                200        
  15. #define D_TIME1_400MS                                400        
  16. #define D_TIME1_500MS                                500        
  17. #define D_TIME1_1S                                1000                //Time1定时器定时1S时间常数
  18. #define D_TIME1_2S                                2000        
  19. #define D_TIME1_3S                                2000        
  20. #define D_TIME1_4S                                4000        
  21. #define D_TIME1_6S                                6000
  22. #define D_TIME1_8S                                8000
  23. #define D_TIME1_9S                                9000
  24. #define D_TIME1_10S                                10000
  25. #define D_TIME1_20S                                20000


  26. #define D_TIME1_V_OVERFLOW                      500        //Time1定时器,电压溢出常数设定为500mS,溢出说明脉宽周期大于500mS
  27. #define D_TIME1_I_OVERFLOW                        8000           //Time1定时器,电流溢出常数设定为10S,溢出说明脉宽周期大于10S
  28. #define D_TIME1_P_OVERFLOW                        12000           //Time1定时器,功率溢出常数设定为10S(约0.5W最小值),溢出说明脉宽周期大于10S
  29. //#define D_TIME1_P_OVERFLOW                        40000           //Time1定时器,功率溢出常数设定为40S(约0.2W最小值)
  30. #define D_TIME1_CAL_TIME                        36000           //校正时间,记录在此时间内的脉冲数,1000W负载在用电36S时间内耗费0.01度电
  31. //--------------------------------------------------------------------------------------------
  32. //--------------------------------------------------------------------------------------------


  33. //HLW 8012 IO设置
  34. //--------------------------------------------------------------------------------------------
  35. //--------------------------------------------------------------------------------------------
  36. #define IO_HLW8012_CF1_S      PD_ODR_ODR3                //HLW8012 PIN8               
  37. #define IO_HLW8012_CF1        PA_IDR_IDR2                //HLW8012 PIN7        
  38. #define IO_HLW8012_CF         PC_IDR_IDR5                //HLW8012 PIN6
  39. //--------------------------------------------------------------------------------------------
  40. //--------------------------------------------------------------------------------------------        


  41. //工作模式
  42. //--------------------------------------------------------------------------------------------
  43. //--------------------------------------------------------------------------------------------
  44. #define D_ERR_MODE                        0x00        //错误提示模式
  45. #define D_NORMAL_MODE                              0x10            //正常工作模式
  46. #define D_CAL_START_MODE                0x21            //校正模式,启动
  47. #define D_CAL_END_MODE                        0x23            //校正模式,完成
  48. //--------------------------------------------------------------------------------------------
  49. //--------------------------------------------------------------------------------------------


  50. //ROM定义
  51. //--------------------------------------------------------------------------------------------
  52. #define u1      _Bool
  53. #define u8        unsigned char
  54. #define u16        unsigned int
  55. #define u32        unsigned long
  56. //--------------------------------------------------------------------------------------------
  57. //--------------------------------------------------------------------------------------------
  58. union IntData
  59. {
  60.         u16  inte;                        
  61.         u8 byte[2];               
  62. };
  63. union LongData
  64. {
  65.     u32  word;               
  66.     u16  inte[2];               
  67.     u8   byte[4];               
  68. };
  69. //--------------------------------------------------------------------------------------------
  70. //--------------------------------------------------------------------------------------------
  71. u16        U16_P_TotalTimes;                        //当前脉冲 功率测量总时间
  72. u16        U16_V_TotalTimes;                        //当前脉冲 电压测量总时间
  73. u16        U16_I_TotalTimes;                        //当前脉冲 电流测量总时间

  74. u16        U16_P_OneCycleTime;                        //功率测量时间参数
  75. u16        U16_V_OneCycleTime;                        //电压测量时间参数
  76. u16        U16_I_OneCycleTime;                        //电流测量时间参数

  77. u16        U16_P_Last_OneCycleTime;                //功率测量时间参数,上一次数量值
  78. u16        U16_V_Last_OneCycleTime;                //电压测量时间参数,上一次数量值
  79. u16        U16_I_Last_OneCycleTime;                //电流测量时间参数,上一次数量值

  80. u16        U16_P_CNT;                                //功率测量脉冲数量
  81. u16        U16_V_CNT;                                //电压测量脉冲数量
  82. u16        U16_I_CNT;                                //电流测量脉冲数量

  83. u16        U16_P_Last_CNT;                                //功率测量脉冲数量,上一次数量值
  84. u16        U16_V_Last_CNT;                                //电压测量脉冲数量,上一次数量值
  85. u16        U16_I_Last_CNT;                                //电流测量脉冲数量,上一次数量值

  86. u1        B_P_TestOneCycle_Mode;                        //功率测量模式 1:单周期测量,0:1S定时测量
  87. u1        B_V_TestOneCycle_Mode;
  88. u1        B_I_TestOneCycle_Mode;

  89. u1        B_P_Last_TestOneCycle_Mode;
  90. u1        B_V_Last_TestOneCycle_Mode;
  91. u1        B_I_Last_TestOneCycle_Mode;
  92.                     
  93. u1          B_P_OVERFLOW;                               // 功率脉冲周期 溢出标志位
  94. u1          B_V_OVERFLOW;                               // 电压脉冲周期 溢出标志位
  95. u1          B_I_OVERFLOW;                               // 电流脉冲周期 溢出标志位

  96. u1        B_P_Last_OVERFLOW;                       // 功率脉冲周期 溢出标志位
  97. u1          B_V_Last_OVERFLOW;                       // 电压脉冲周期 溢出标志位
  98. u1          B_I_Last_OVERFLOW;                       // 电流脉冲周期 溢出标志位

  99. u1            B_VI_Test_Mode;                                //1:电压测量模式;0:电流测量模式
  100. u16           U16_VI_Test_Times;                                
  101. u16           U16_Cal_Times;        

  102. u16           U16_AC_P;                                //功率值 1000.0W
  103. u16           U16_AC_V;                                //电压值 220.0V
  104. u16           U16_AC_I;                                //电流值 4.545A
  105. u32           U32_AC_E;                                //用电量   0.01度
  106. u32           U32_AC_BACKUP_E;                        //用电量备份        
  107. u8            U8_AC_COS;                                //功率因素 0.00

  108. u16           U16_REF_001_E_Pluse_CNT;                //0.01度电脉冲总数参考值
  109. u16           U16_E_Pluse_CNT;                           //脉冲个数寄存器

  110. u32           U32_Cal_Times;                                 //校正时间

  111. u32           U32_P_REF_PLUSEWIDTH_TIME;              //参考功率 脉冲周期
  112. u32           U32_V_REF_PLUSEWIDTH_TIME;              //参考电压 脉冲周期
  113. u32           U32_I_REF_PLUSEWIDTH_TIME;              //参考电流 脉冲周期

  114. u32           U32_P_CURRENT_PLUSEWIDTH_TIME;              //当前功率 脉冲周期
  115. u32           U32_V_CURRENT_PLUSEWIDTH_TIME;              //当前电压 脉冲周期
  116. u32           U32_I_CURRENT_PLUSEWIDTH_TIME;              //当前电流 脉冲周期

  117. u16           U16_P_REF_Data;                                //参考功率值,如以1000W校正。1000.0W
  118. u16           U16_V_REF_Data;                                //参考电压  220.0V
  119. u16           U16_I_REF_Data;                                //参考电流  1000W,220V条件下是4.545A

  120. u8            U8_CURR_WorkMode;
  121. //--------------------------------------------------------------------------------------------



  122. //--------------------------------------------------------------------------------------------
  123. //--------------------------------------------------------------------------------------------
  124. void main(void)
  125. {
  126.    //初始化MCU
  127.    //初始化ROM
  128.    Init_Rom();
  129.    //读取存放于EEPROM的校正数据
  130.    Read_CalData_EEPROM(); //读取参考功率、参考电压、参考电流的脉冲周期

  131.    while(1)
  132.   {
  133.      if (B_KeyScanEn == TRUE)
  134.      {
  135.         ScaningKey();                        //按键
  136.         KeyFun_NormalMode();
  137.      }
  138.      
  139.      if (U8_CURR_WorkMode == D_NORMAL_MODE)
  140.      {        
  141.         HLW8012_Measure();                //计算功率、电压、电流
  142.      }
  143.      else if (U8_CURR_WorkMode == D_CAL_END_MODE)   //校正模式
  144.      {
  145.             //记录校正值,将当前功率、电压、电流值存入EEPROM;将0.01度电的脉冲数参值也存入EEPROM
  146.             Write_CalData_EEPROM();
  147.             //读取校正值,将用电量清零
  148.             Read_CalData_EEPROM();
  149.             //返回测量模式
  150.             U8_CURR_WorkMode = D_NORMAL_MODE;
  151.      }
  152.         
  153.   }
  154. }


  155. //--------------------------------------------------------------------------------------------
  156. //--------------------------------------------------------------------------------------------
  157. /*=====================================================
  158. * Function : void Init_Rom(void)
  159. * Describe : rom空间初始化
  160. * Input    : none
  161. * Output   : none
  162. * Return   : none
  163. * Record   : 2014/04/14
  164. =====================================================*/
  165. void Init_Rom(void)
  166. {
  167.     U8_CURR_WorkMode = D_NORMAL_MODE;
  168.     U8_DspMode = 0;
  169.    
  170.     U16_AC_P = 0;
  171.     U16_AC_V = 0;
  172.     U16_AC_I = 0;
  173.     U8_AC_COS = 0;


  174.   U16_P_TotalTimes = 0;
  175.   U16_V_TotalTimes = 0;
  176.   U16_I_TotalTimes = 0;

  177.   
  178.   U16_P_OneCycleTime = 0;
  179.   U16_V_OneCycleTime = 0;
  180.   U16_I_OneCycleTime = 0;
  181.   U16_P_Last_OneCycleTime = 0;
  182.   U16_V_Last_OneCycleTime = 0;
  183.   U16_I_Last_OneCycleTime = 0;
  184.   
  185.   U16_P_CNT = 0;
  186.   U16_V_CNT = 0;
  187.   U16_I_CNT = 0;
  188.   U16_P_Last_CNT = 0;
  189.   U16_V_Last_CNT = 0;
  190.   U16_I_Last_CNT = 0;
  191.   
  192. //初始化单周期测量模式
  193.   B_P_TestOneCycle_Mode = 1;
  194.   B_V_TestOneCycle_Mode = 1;
  195.   B_I_TestOneCycle_Mode = 1;
  196.   B_P_Last_TestOneCycle_Mode = 1;
  197.   B_V_Last_TestOneCycle_Mode = 1;
  198.   B_I_Last_TestOneCycle_Mode = 1;

  199. //开始测量,置溢出标志位为1  
  200.   B_P_OVERFLOW = 1;
  201.   B_V_OVERFLOW = 1;
  202.   B_I_OVERFLOW = 1;
  203.   
  204.   B_P_Last_OVERFLOW = 1;
  205.   B_V_Last_OVERFLOW = 1;
  206.   B_I_Last_OVERFLOW = 1;
  207.   
  208. //上电初始化为电压测试模式
  209.   B_VI_Test_Mode = 1;
  210.   IO_HLW8012_CF1_S = 1;
  211.   U16_VI_Test_Times = D_TIME1_2S;
  212.   
  213. //显示初始化
  214.   U8_DspMode = 0;
  215.   B_DIS_EN = FALSE;
  216.   U16_SendUart_Time = 0;
  217.   
  218. }
  219. /*=====================================================
  220. * 函数名称: PC中断,IO---PC5
  221. * 函数功能: CF中断 功率测量
  222. * 输入参数: 无
  223. * 输出参数:
  224. * 返    回:
  225. =====================================================*/
  226.   #pragma vector = 7
  227. __interrupt void PC5_EXTI_Interrupt(void)
  228. {
  229. //功率测量
  230.     U16_P_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零   
  231.     U16_P_CNT++;
  232.     if (B_P_OVERFLOW == TRUE)
  233.     {  
  234.         //从溢出模式转入,开始测量     
  235.         B_P_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  236.         U16_P_TotalTimes = 0;       //清溢出寄存器清零
  237.         U16_P_OneCycleTime = 0;     //清测量寄存器
  238.         U16_P_CNT = 1;              
  239.         B_P_OVERFLOW = FALSE;       //清溢出标志位
  240.     }
  241.     else
  242.     {
  243.         if (B_P_TestOneCycle_Mode == 1)
  244.         {
  245.             if (U16_P_OneCycleTime >= D_TIME1_100MS)
  246.             {
  247.                 //单周期测量模式
  248.                 U16_P_Last_OneCycleTime = U16_P_OneCycleTime;
  249.                 B_P_Last_TestOneCycle_Mode = B_P_TestOneCycle_Mode;
  250.                 B_P_OVERFLOW = FALSE;       //溢出标志位清零
  251.                 B_P_Last_OVERFLOW = B_P_OVERFLOW;
  252.                  //清状态参数,重新开始测试
  253.                 B_P_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  254.                 U16_P_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零
  255.                 U16_P_OneCycleTime = 0;     //清测量寄存器
  256.                 U16_P_CNT = 1;

  257.             }
  258.         }
  259.         else
  260.         {
  261.             if (U16_P_OneCycleTime >= D_TIME1_1S)
  262.             {   
  263.                 U16_P_Last_OneCycleTime = U16_P_OneCycleTime;
  264.                 U16_P_Last_CNT = U16_P_CNT;
  265.                 B_P_Last_TestOneCycle_Mode = B_P_TestOneCycle_Mode;
  266.                 B_P_OVERFLOW = FALSE;       //溢出标志位清零
  267.                 B_P_Last_OVERFLOW = B_P_OVERFLOW;
  268.                 //清状态参数,重新开始测试
  269.                 B_P_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  270.                 U16_P_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零
  271.                 U16_P_OneCycleTime = 0;     //清测量寄存器
  272.                 U16_P_CNT = 1;
  273.             }
  274.         }
  275.     }
  276.    
  277.    
  278. //校正模式
  279.     if (U8_CURR_WorkMode == D_CAL_START_MODE)
  280.     {
  281.         //记录单位时间内的用电量
  282.         U16_E_Pluse_CNT++;
  283.     }
  284.    
  285. //用电量计量,每0.01度电,用电量寄存器增加0.01度
  286.     if (U8_CURR_WorkMode == D_NORMAL_MODE)
  287.     {
  288.         U16_E_Pluse_CNT++;
  289.         if (U16_E_Pluse_CNT == U16_REF_001_E_Pluse_CNT )
  290.         {
  291.             U16_E_Pluse_CNT = 0;
  292.             U32_AC_E++;
  293.         }
  294.     }
  295. }
  296. /*=====================================================
  297. * 函数名称: PD中断,IO---PD2
  298. * 函数功能: CF1中断 电压、电流测量
  299. * 输入参数:
  300. * 输出参数:
  301. * 返    回:
  302. =====================================================*/
  303.   #pragma vector = 8
  304. __interrupt void PD2_EXTI_Interrupt(void)
  305. {
  306.   
  307. //电压测试模式
  308.     if (B_VI_Test_Mode == 1)
  309.     {
  310.         U16_V_TotalTimes = 0;
  311.         U16_V_CNT++;
  312.         if (B_V_OVERFLOW == TRUE)
  313.         {                  
  314.             //从溢出模式转入,开始测量     
  315.             B_V_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  316.             U16_V_TotalTimes = 0;       //清溢出寄存器清零
  317.             U16_V_OneCycleTime = 0;     //清测量寄存器
  318.             U16_V_CNT = 1;              
  319.             B_V_OVERFLOW = FALSE;       //清溢出标志位
  320.         }
  321.         else
  322.         {
  323.             if (B_V_TestOneCycle_Mode == 1)
  324.             {
  325.                 if (U16_V_OneCycleTime >= D_TIME1_100MS)
  326.                 {
  327.                     //单周期测量模式
  328.                     U16_V_Last_OneCycleTime = U16_V_OneCycleTime;
  329.                     B_V_Last_TestOneCycle_Mode = B_V_TestOneCycle_Mode;
  330.                     B_V_OVERFLOW = FALSE;       //溢出标志位清零
  331.                     B_V_Last_OVERFLOW = B_V_OVERFLOW;
  332.                      //清状态参数,重新开始测试
  333.                     B_V_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  334.                     U16_V_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零
  335.                     U16_V_OneCycleTime = 0;     //清测量寄存器
  336.                     U16_V_CNT = 1;
  337.                 }
  338.             }
  339.             else
  340.             {
  341.                 if (U16_V_OneCycleTime >= D_TIME1_200MS)
  342.                 {   
  343.                     U16_V_Last_OneCycleTime = U16_V_OneCycleTime;
  344.                     U16_V_Last_CNT = U16_V_CNT;
  345.                     B_V_Last_TestOneCycle_Mode = B_V_TestOneCycle_Mode;
  346.                     B_V_OVERFLOW = FALSE;       //溢出标志位清零
  347.                     B_V_Last_OVERFLOW = B_V_OVERFLOW;
  348.                     //清状态参数,重新开始测试
  349.                     B_V_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  350.                     U16_V_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零
  351.                     U16_V_OneCycleTime = 0;     //清测量寄存器
  352.                     U16_V_CNT = 1;
  353.                     B_V_OVERFLOW = FALSE;       //溢出标志位清零
  354.                 }
  355.             }
  356.         }
  357.      }

  358. //电流测试模式
  359.     if (B_VI_Test_Mode == 0)
  360.     {
  361.         U16_I_TotalTimes = 0;
  362.         U16_I_CNT++;
  363.         if (B_I_OVERFLOW == TRUE)
  364.         {
  365.             //从溢出模式转入,开始测量     
  366.             B_I_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  367.             U16_I_TotalTimes = 0;       //清溢出寄存器清零
  368.             U16_I_OneCycleTime = 0;     //清测量寄存器
  369.             U16_I_CNT = 1;              
  370.             B_I_OVERFLOW = FALSE;       //清溢出标志位
  371.         }
  372.         else
  373.         {
  374.             if (B_I_TestOneCycle_Mode == 1)
  375.             {
  376.                 if (U16_I_OneCycleTime >= D_TIME1_100MS)
  377.                 {
  378.                     //单周期测量模式
  379.                     U16_I_Last_OneCycleTime = U16_I_OneCycleTime;
  380.                     B_I_Last_TestOneCycle_Mode = B_I_TestOneCycle_Mode;
  381.                     B_I_OVERFLOW = FALSE;       //溢出标志位清零
  382.                     B_I_Last_OVERFLOW = B_I_OVERFLOW;
  383.                      //清状态参数,重新开始测试
  384.                     B_I_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  385.                     U16_I_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零
  386.                     U16_I_OneCycleTime = 0;     //清测量寄存器
  387.                     U16_I_CNT = 1;
  388.                 }
  389.             }
  390.             else
  391.             {
  392.                 if (U16_I_OneCycleTime >= D_TIME1_1S)
  393.                 {   
  394.                     U16_I_Last_OneCycleTime = U16_I_OneCycleTime;
  395.                     U16_I_Last_CNT = U16_I_CNT;
  396.                     B_I_Last_TestOneCycle_Mode = B_I_TestOneCycle_Mode;  
  397.                     B_I_OVERFLOW = FALSE;       //溢出标志位清零
  398.                     B_I_Last_OVERFLOW = B_I_OVERFLOW;
  399.                     //清状态参数,重新开始测试
  400.                     B_I_TestOneCycle_Mode = 0;  //初始化为计数脉冲测量模式
  401.                     U16_I_TotalTimes = 0;       //完成一次有效的测量,溢出寄存器清零
  402.                     U16_I_OneCycleTime = 0;     //清测量寄存器
  403.                     U16_I_CNT = 1;
  404.                 }
  405.             }
  406.         }
  407.     }
  408. }
  409. /*=====================================================
  410. * 函数名称: TIM1
  411. * 函数功能: 测量功率、电压、电流
  412. * 输入参数:
  413. * 输出参数:
  414. * 返    回:
  415. =====================================================*/
  416.   #pragma vector = 13
  417. __interrupt void TIM1_UPD_Interrupt(void)
  418. {
  419. //校正模式
  420.     if (U8_CURR_WorkMode == D_CAL_START_MODE)
  421.     {
  422.         U32_Cal_Times++;//校正时间36S,1000W负载36S时间消耗0.01度电
  423.         if (U32_Cal_Times == D_TIME1_CAL_TIME)
  424.         {
  425.             U8_CURR_WorkMode = D_CAL_END_MODE;                        
  426.             U16_REF_001_E_Pluse_CNT = U16_E_Pluse_CNT;                //记录36S时间内的脉冲数,此脉冲数表示0.01度用电量
  427.         }
  428.     }
  429.    
  430. //功率测量
  431.     if (U16_P_CNT != 0)
  432.     {
  433.         U16_P_OneCycleTime++;
  434.         U16_P_TotalTimes++;
  435.     }  
  436.     if (U16_P_TotalTimes >= D_TIME1_P_OVERFLOW)
  437.     {
  438.         B_P_OVERFLOW = TRUE;                 //溢出,
  439.         B_P_Last_OVERFLOW = B_P_OVERFLOW;
  440.         //清状态参数,重新开始测试
  441.         U16_P_TotalTimes = 0;       //清溢出寄存器
  442.         U16_P_OneCycleTime = 0;
  443.         U16_P_CNT = 0;              //等待下一次中断开始计数
  444.         B_P_TestOneCycle_Mode = 0;   //初始化为计数脉冲测量模式      
  445.     }
  446.     else if (U16_P_OneCycleTime == D_TIME1_100MS)
  447.     {
  448.       if (U16_P_CNT < 2)
  449.       {
  450.         // 100ms内只有一次中断,说明周期>100ms,采用单周期测量模式
  451.         B_P_TestOneCycle_Mode = 1;
  452.       }
  453.       else
  454.       {
  455.          // 100ms内有2次或以上数量脉冲,说明周期<100ms,采用计数脉冲测量模式
  456.          B_P_TestOneCycle_Mode = 0;   
  457.       }
  458.     }
  459.    
  460. //电压、电流测量
  461.     if (B_VI_Test_Mode == 1)
  462.     {
  463.         //电压测量      
  464.         if (U16_V_CNT != 0)
  465.         {
  466.             U16_V_OneCycleTime++;
  467.             U16_V_TotalTimes++;
  468.         }  
  469.         if (U16_V_TotalTimes >= D_TIME1_V_OVERFLOW)
  470.         {
  471.             B_V_OVERFLOW = TRUE;
  472.             B_V_Last_OVERFLOW = B_V_OVERFLOW;
  473.             //清状态参数,重新开始测试
  474.             U16_V_TotalTimes = 0;       //清溢出寄存器
  475.             U16_V_OneCycleTime = 0;
  476.             U16_V_CNT = 0;              
  477.             B_V_TestOneCycle_Mode = 0;   //初始化为计数脉冲测量模式      
  478.         }
  479.         else if (U16_V_OneCycleTime == D_TIME1_100MS)
  480.         {
  481.           if (U16_V_CNT < 2)
  482.           {
  483.             // 100ms内只有一次中断,说明周期>100ms,采用单周期测量模式
  484.             B_V_TestOneCycle_Mode = 1;
  485.           }
  486.           else
  487.           {
  488.              // 100ms内有2次或以上数量脉冲,说明周期<100ms,采用计数脉冲测量模式
  489.              B_V_TestOneCycle_Mode = 0;   
  490.           }
  491.         }
  492.     }
  493.     else
  494.     {
  495.         //电流测量   
  496.         if (U16_I_CNT != 0)
  497.         {
  498.             U16_I_OneCycleTime++;
  499.             U16_I_TotalTimes++;
  500.         }  
  501.         if (U16_I_TotalTimes >= D_TIME1_I_OVERFLOW)
  502.         {
  503.             B_I_OVERFLOW = TRUE;
  504.             B_I_Last_OVERFLOW = B_I_OVERFLOW;
  505.             //清状态参数,重新开始测试
  506.             U16_I_TotalTimes = 0;       //清溢出寄存器
  507.             U16_I_OneCycleTime = 0;
  508.             U16_I_CNT = 0;
  509.             B_I_TestOneCycle_Mode = 0;   //初始化为计数脉冲测量模式      
  510.         }
  511.         else if (U16_I_OneCycleTime == D_TIME1_100MS)
  512.         {
  513.           if (U16_I_CNT < 2)
  514.           {
  515.             // 100ms内只有一次中断,说明周期>100ms,采用单周期测量模式
  516.             B_I_TestOneCycle_Mode = 1;
  517.           }
  518.           else
  519.           {
  520.              // 100ms内有2次或以上数量脉冲,说明周期<100ms,采用计数脉冲测量模式
  521.              B_I_TestOneCycle_Mode = 0;   
  522.           }
  523.         }
  524.     }
  525.       

  526. //电压、电流测量模式切换  B_VI_Test_Mode:(1:电压测量模式) (0:电流测试模式)
  527.     U16_VI_Test_Times--;
  528.     if (U16_VI_Test_Times == 0)
  529.     {
  530.         if (B_VI_Test_Mode == 1)
  531.         {
  532.             //转为电流测量模式
  533.             B_VI_Test_Mode = 0;
  534.             IO_HLW8012_CF1_S = 0;
  535.             U16_VI_Test_Times = D_TIME1_10S;
  536.             
  537.             //清状态参数
  538.             U16_I_TotalTimes = 0;
  539.             U16_I_OneCycleTime = 0;
  540.             U16_I_CNT = 0;
  541.             B_I_OVERFLOW = FALSE;
  542.         }
  543.         else
  544.         {
  545.             //转为电压测量模式
  546.             B_VI_Test_Mode = 1;
  547.             IO_HLW8012_CF1_S = 1;
  548.             U16_VI_Test_Times = D_TIME1_1S;
  549.             
  550.             //清状态参数
  551.             U16_V_TotalTimes = 0;
  552.             U16_V_OneCycleTime = 0;
  553.             U16_V_CNT = 0;
  554.             B_V_OVERFLOW = FALSE;
  555.         }
  556.     }
  557.   
  558. //按键扫描,20mS一次
  559.         U8_KeyScanTimes++;
  560.           if (U8_KeyScanTimes > D_TIME1_20MS)
  561.           {
  562.                       B_KeyScanEn = TRUE;
  563.                   U8_KeyScanTimes = 0;
  564.           }
  565.    
  566. // 每0.5S串口发送一次数据
  567.     U16_SendUart_Time++;
  568.     if (U16_SendUart_Time == D_TIME1_500MS)
  569.     {
  570.         B_DIS_EN = TRUE;
  571.         U16_SendUart_Time = 0;
  572.     }

  573. // Clear TIM1 INT FLAG   
  574.    TIM1_SR1 = 0x00;      
  575. }



  576. /*-------------------------------------------- 功率、电压、电流计算 -------------------------------------------*/


  577. *=====================================================
  578. * Function : void HLW8012_Measure_P(void)
  579. * Describe :
  580. * Input    : none
  581. * Output   : none
  582. * Return   : none
  583. * Record   : 2014/04/14
  584. =====================================================*/
  585. void HLW8012_Measure_P(void)
  586. {
  587.     u32 a;
  588.     u32 b;
  589.     u32 u32_P_Period;
  590.    
  591.     if (B_P_Last_TestOneCycle_Mode == 1)
  592.     {
  593.        //单周期测量模式
  594.        b = U16_P_Last_OneCycleTime;
  595.        b = b*1000;  //ms转换成us
  596.        u32_P_Period = b;   
  597.     }
  598.     else
  599.     {
  600.       //计数脉冲测量模式
  601.       b = U16_P_Last_OneCycleTime;
  602.       b = b*1000;
  603.       u32_P_Period = b/(U16_P_Last_CNT-1);  
  604.     }
  605.    
  606.     U32_P_CURRENT_PLUSEWIDTH_TIME = u32_P_Period;      // 校正时取U32_P_CURRENT_PLUSEWIDTH_TIME参数作为参考值     
  607.     a = U16_P_REF_Data * U32_P_REF_PLUSEWIDTH_TIME;        
  608.     U16_AC_P = a/U32_P_CURRENT_PLUSEWIDTH_TIME;
  609.    
  610.     if (U16_AC_P == 0xffff)     //开机时U32_P_CURRENT_PLUSEWIDTH_TIME = 0,计算溢出
  611.     {
  612.         U16_AC_P = 0;
  613.     }
  614.    
  615.     if (B_P_Last_OVERFLOW == TRUE)
  616.     {
  617.         U16_AC_P = 0;
  618.     }
  619. }
  620. /*=====================================================
  621. * Function : void HLW8012_Measure_V(void)
  622. * Describe :
  623. * Input    : none
  624. * Output   : none
  625. * Return   : none
  626. * Record   : 2014/04/14
  627. =====================================================*/
  628. void HLW8012_Measure_V(void)
  629. {
  630.     u32 a;
  631.     u32 b;
  632.     u32 u32_V_Period;
  633.    
  634.     if (U16_VI_Test_Times < D_TIME1_100MS)
  635.     {
  636.         if (B_V_Last_TestOneCycle_Mode == 1)
  637.         {
  638.             b = U16_V_Last_OneCycleTime;
  639.             u32_V_Period = b * 1000;   //ms转换成us
  640.             U32_V_CURRENT_PLUSEWIDTH_TIME = u32_V_Period;  
  641.         }
  642.         else
  643.         {
  644.              b = U16_V_Last_OneCycleTime;
  645.              b = b*1000;
  646.              u32_V_Period = b/(U16_V_Last_CNT-1);
  647.              //u32_V_Period = b/U16_V_Last_CNT;
  648.              U32_V_CURRENT_PLUSEWIDTH_TIME = u32_V_Period;  
  649.         }
  650.     }
  651.          
  652.     a = U16_V_REF_Data * U32_V_REF_PLUSEWIDTH_TIME;
  653.     U16_AC_V = a/U32_V_CURRENT_PLUSEWIDTH_TIME;
  654.    
  655.     if (U16_AC_V == 0xffff)     //开机时U32_V_CURRENT_PLUSEWIDTH_TIME = 0,计算溢出
  656.     {
  657.         U16_AC_V = 0;
  658.     }
  659.    
  660.     if (B_V_Last_OVERFLOW == TRUE)
  661.     {
  662.         U16_AC_V = 0;
  663.     }
  664.    
  665.     if (U16_AC_P == 0)
  666.     {
  667.         U16_AC_V = 0;
  668.       
  669.     }
  670. }
  671. /*=====================================================
  672. * Function : void HLW8012_Measure_I(void)
  673. * Describe :
  674. * Input    : none
  675. * Output   : none
  676. * Return   : none
  677. * Record   : 2014/04/14
  678. =====================================================*/
  679. void HLW8012_Measure_I(void)
  680. {
  681.     u32 a;
  682.     u32 b;
  683.     u32 u32_I_Period;  
  684.    
  685.     if (U16_VI_Test_Times < D_TIME1_6S)
  686.     {
  687.         if (B_I_Last_TestOneCycle_Mode == 1)
  688.         {

  689.             b = U16_I_Last_OneCycleTime;
  690.             u32_I_Period = b * 1000;   //ms转换成us
  691.             U32_I_CURRENT_PLUSEWIDTH_TIME = u32_I_Period;
  692.         }
  693.         else
  694.         {
  695.              b = U16_I_Last_OneCycleTime;
  696.              b = b*1000;
  697.              u32_I_Period = b/(U16_I_Last_CNT-1);
  698.              //u32_I_Period = b/U16_I_Last_CNT;
  699.              U32_I_CURRENT_PLUSEWIDTH_TIME = u32_I_Period;
  700.         }
  701.     }
  702.    
  703.          
  704.     a = U16_I_REF_Data * U32_I_REF_PLUSEWIDTH_TIME;
  705.     U16_AC_I = a/U32_I_CURRENT_PLUSEWIDTH_TIME;
  706.    
  707.    
  708.     if (U16_AC_I > 180)
  709.     {   
  710.        if (U16_AC_I != 0xffff)
  711.        {
  712.             NOP();
  713.             NOP();
  714.        }
  715.     }
  716.       
  717.     if (U16_AC_P == 0)
  718.     {
  719.         U16_AC_I = 0;
  720.       
  721.     }
  722.    
  723.     if (U16_AC_I == 0xffff)     //开机时U32_I_CURRENT_PLUSEWIDTH_TIME = 0,计算溢出
  724.     {
  725.         U16_AC_I = 0;
  726.     }
  727.    
  728.     if (B_I_OVERFLOW == TRUE)
  729.     {
  730.         U16_AC_I = 0;  
  731.     }
  732. }
  733. /*=====================================================
  734. * Function : void HLW8012_Measure_COS(void)
  735. * Describe :
  736. * Input    : none
  737. * Output   : none
  738. * Return   : none
  739. * Record   : 2014/04/14
  740. =====================================================*/
  741. void HLW8012_Measure_COS(void)
  742. {
  743.   u32 u32_P_Apparent;
  744.   u32 a;
  745.   u8 b;
  746.   u32_P_Apparent = (u32)U16_AC_I*(u32)U16_AC_V;
  747.   u32_P_Apparent = u32_P_Apparent/1000;
  748.   a = U16_AC_P;
  749.   a = a*100;
  750.   
  751.   b = (u8)(a/u32_P_Apparent);
  752.   if (b > 100 )
  753.     U8_AC_COS = 100;                 //由于相位延时造成的功率因素>1的情况,功率因素取值1
  754.   else
  755.     U8_AC_COS = b;
  756. }
  757. /*=====================================================
  758. * Function : void HLW8012_Measure_E(void)
  759. * Describe : 每1度电存储一次
  760. ……………………

  761. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

全部资料51hei下载地址:
HLW8012设计资料REV30.7z (11.34 MB, 下载次数: 675)

评分

参与人数 2黑币 +55 收起 理由
hanm + 5 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:1 发表于 2018-7-24 02:39 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:389627 发表于 2018-8-24 14:02 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:65956 发表于 2018-9-20 15:42 | 显示全部楼层
有没有8032的程序
回复

使用道具 举报

ID:140186 发表于 2018-9-20 16:21 | 显示全部楼层
厉害,对于信号走线这块真的很难搞啊!
回复

使用道具 举报

ID:100247 发表于 2018-9-21 16:54 | 显示全部楼层
谢谢共享!资料很有学习价值!
回复

使用道具 举报

ID:295805 发表于 2018-11-9 12:01 | 显示全部楼层
为贴吧有你这样的人才而骄傲
回复

使用道具 举报

ID:433318 发表于 2018-11-26 11:46 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:439802 发表于 2018-12-5 10:18 | 显示全部楼层
好资料,谢谢
回复

使用道具 举报

ID:58730 发表于 2019-1-19 17:09 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:76408 发表于 2019-2-20 13:20 | 显示全部楼层
谢谢楼主,我正需要这样的资料,辛苦你了!
回复

使用道具 举报

ID:478526 发表于 2019-2-20 15:58 | 显示全部楼层
谢谢楼主,辛苦了。
回复

使用道具 举报

ID:461544 发表于 2019-4-26 22:50 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:461544 发表于 2019-4-26 22:55 | 显示全部楼层
超级崇拜的说
回复

使用道具 举报

ID:384489 发表于 2019-5-14 15:06 | 显示全部楼层
很有参考意义,谢谢分享~
回复

使用道具 举报

ID:463412 发表于 2019-5-15 11:18 | 显示全部楼层
感谢分享 这个资料很珍贵
回复

使用道具 举报

ID:515763 发表于 2019-5-20 17:56 | 显示全部楼层
HLW8012与HLW8032有什么区别么
回复

使用道具 举报

ID:554047 发表于 2019-6-3 19:34 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:563165 发表于 2019-6-15 18:16 | 显示全部楼层
不错 不错 很有帮助。谢谢分享
回复

使用道具 举报

ID:79836 发表于 2019-6-20 09:32 | 显示全部楼层
不错不错 很好 很好
回复

使用道具 举报

ID:79836 发表于 2019-6-20 09:50 | 显示全部楼层
非常棒  学习下  很不错的帖子
回复

使用道具 举报

ID:88154 发表于 2019-7-18 17:46 | 显示全部楼层

非常棒  学习下  很不错的帖子
回复

使用道具 举报

ID:593299 发表于 2019-7-31 20:35 | 显示全部楼层
好多的资料啊。楼主多谢多谢。
回复

使用道具 举报

ID:596829 发表于 2019-8-7 13:52 | 显示全部楼层

厉害,对于信号走线这块真的很难搞啊!
回复

使用道具 举报

ID:600983 发表于 2019-8-17 09:02 | 显示全部楼层
非常棒的资料,谢谢楼主分享
回复

使用道具 举报

ID:567636 发表于 2019-8-17 23:06 | 显示全部楼层
这个资料很好,多谢分享!
回复

使用道具 举报

ID:166646 发表于 2019-8-19 10:24 | 显示全部楼层
谢谢资料让人学习了
回复

使用道具 举报

ID:606369 发表于 2019-9-2 15:37 | 显示全部楼层
楼主有一个问题,就是电路中继电器出来可以直接将火线接入采样电路中吗
回复

使用道具 举报

ID:589517 发表于 2019-9-9 16:37 | 显示全部楼层
太棒了
回复

使用道具 举报

ID:15104 发表于 2019-9-19 19:36 | 显示全部楼层
感谢分享!!!
回复

使用道具 举报

ID:614352 发表于 2019-9-23 09:43 | 显示全部楼层
感谢分享。。。。。。。。
回复

使用道具 举报

ID:620246 发表于 2019-10-7 21:54 | 显示全部楼层

感谢分享。。。。。。。。
回复

使用道具 举报

ID:628639 发表于 2019-10-23 09:04 | 显示全部楼层
不错,先谢楼主!
回复

使用道具 举报

ID:646428 发表于 2019-11-22 09:10 | 显示全部楼层
这个确实给力
回复

使用道具 举报

ID:292097 发表于 2019-12-17 18:28 | 显示全部楼层
非常值得我们参考学习,感谢楼主的无私奉献
回复

使用道具 举报

ID:71421 发表于 2019-12-19 10:34 | 显示全部楼层
厉害!!!连布线的细节都介绍得清清楚楚。
回复

使用道具 举报

ID:71535 发表于 2019-12-22 18:14 | 显示全部楼层

谢谢分享!资料很有学习价值!
回复

使用道具 举报

ID:292097 发表于 2020-1-1 17:10 | 显示全部楼层
不错非常好的作品,值得参考
回复

使用道具 举报

ID:682092 发表于 2020-1-6 14:12 | 显示全部楼层
dw772 发表于 2019-11-4 15:05
版主您好,你提供的文件是不是损坏了,下载下来解压出来是空文件

我也是,下载了之后提示损坏了,解决问题了么?
回复

使用道具 举报

ID:196774 发表于 2020-2-9 21:00 来自手机 | 显示全部楼层
正是需要学习的资料,谢谢整理分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表