找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2971|回复: 1
收起左侧

合力为HLW8032计量芯片设计资料包 含8266源程序

[复制链接]
ID:320610 发表于 2020-9-12 10:00 | 显示全部楼层 |阅读模式
资料包为深圳市合力为科技的计量芯片HLW8032的应用开发包;包含datasheet,软件参考设计,硬件参考设计,常见问题等文档。笔者已经参考资料包打样了电路板;测试效果还不错,欢迎一起交流,学习!
51hei.png

8266参考代码
1、采样电阻:0.001R
2、电压分压电阻:1M【参考设计资料是1.88M】

源程序如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. /* run this program using the console pauser or add your own getch, system("pause") or input loop */
  4. #define SAMPLE_RESISTANCE_MR    1//使用的采样锰铜电阻mR值

  5. #define UART_IND_HD            0
  6. #define UART_IND_5A            1
  7. #define UART_IND_VK            2
  8. #define UART_IND_VT            5
  9. #define UART_IND_IK            8
  10. #define UART_IND_IT            11
  11. #define UART_IND_PK            14
  12. #define UART_IND_PT            17
  13. #define UART_IND_FG            20
  14. #define UART_IND_EN            21
  15. #define UART_IND_SM            23

  16. #define ARRAY_LEN       3//平滑滤波buf长度
  17. #define COUNT_NUM       1//超时更新数据次数

  18. //8032电能计数脉冲溢出时的数据
  19. #define ENERGY_FLOW_NUM            65536   //电量采集,电能溢出时的脉冲计数值

  20. typedef struct RuningInf_s{
  21.     unsigned short  voltage;//当前电压值,单位为0.1V
  22.     unsigned short  electricity;//当前电流值,单位为0.01A
  23.     unsigned short  power;//当前功率,单位为0.1W
  24.    
  25.     unsigned long   energy;//当前消耗电能值对应的脉冲个数
  26.     unsigned short  energyCurrent;//电能脉冲当前统计值
  27.     unsigned short  energyLast;//电能脉冲上次统计值
  28.     unsigned char   energyFlowFlag;//电能脉冲溢出标致
  29.    
  30.     unsigned long   energyUnit;//0.001度点对应的脉冲个数
  31. }RuningInf_t;

  32. RuningInf_t runingInf;

  33. //获取电压、电流、功率的有限数据
  34. unsigned long getVIPvalue(unsigned long *arr)//更新电压、电流、功率的列表
  35. {
  36.     int maxIndex = 0;
  37.     int minIndex = 0;
  38.     unsigned long sum = 0;
  39.     int j = 0;
  40.     for(j = 1; j<ARRAY_LEN; j++){
  41.         if(arr[maxIndex] <= arr[j]){//避免所有数据一样时minIndex等于maxIndex
  42.             maxIndex = j;
  43.         }
  44.         if(arr[minIndex] > arr[j]){
  45.             minIndex = j;
  46.         }
  47.     }
  48.    
  49.     for(j = 0; j<ARRAY_LEN; j++){
  50.         if((maxIndex == j)||(minIndex == j)){
  51.             continue;
  52.         }
  53.         else{
  54.             return arr[j];
  55.         }
  56.     }
  57. }

  58. int isUpdataNewData(unsigned long *arr,unsigned long dat)//检测电压电流功率是否需要更新
  59. {
  60.     if(arr[0] == dat){
  61.         return 0;
  62.     }
  63.     else{
  64.         return 1;
  65.     }
  66. }

  67. void updataVIPvalue(unsigned long *arr,unsigned long dat)//更新电压、电流、功率的列表
  68. {
  69.     int ii = ARRAY_LEN-1;
  70.     for(ii = ARRAY_LEN-1; ii > 0; ii--){
  71.         arr[ii] = arr[ii-1];
  72.     }
  73.     arr[0] = dat;
  74. }

  75. void resetVIPvalue(unsigned long *arr,unsigned long dat)//更新所有电压、电流、功率的列表
  76. {   
  77.     int ii = ARRAY_LEN-1;
  78.     for(ii = ARRAY_LEN-1; ii >= 0; ii--){
  79.         arr[ii] = dat;
  80.     }
  81. }

  82. int DealUartInf(unsigned char *inDataBuffer,int recvlen)
  83. {
  84.     unsigned char     startFlag     = 0;
  85.    
  86.     unsigned long      voltage_k        = 0;
  87.     unsigned long      voltage_t     = 0;
  88.     unsigned long      voltage       = 0;
  89.     static unsigned long voltage_a[ARRAY_LEN]  = {0};
  90.     static unsigned int  voltageCnt    = 0;

  91.     unsigned long      electricity_k = 0;
  92.     unsigned long      electricity_t = 0;
  93.     unsigned long      electricity   = 0;
  94.     static unsigned long electricity_a[ARRAY_LEN]  = {0};
  95.     static unsigned int  electricityCnt    = 0;

  96.     unsigned long      power_k = 0;
  97.     unsigned long      power_t = 0;
  98.     unsigned long      power      = 0;
  99.     static unsigned long power_a[ARRAY_LEN]= {0};
  100.     static unsigned int  powerCnt    = 0;
  101.     static unsigned long powerNewFlag = 1;
  102.    
  103.     unsigned int      energy_cnt     = 0;
  104.     unsigned char      energyFlowFlag = 0;

  105.     startFlag = inDataBuffer[UART_IND_HD];
  106.     switch(startFlag)
  107.     {
  108.         case 0x55:
  109.             if((inDataBuffer[UART_IND_FG]&0x40) == 0x40){//获取当前电压标致,为1时说明电压检测OK
  110.                 voltage_k = ((inDataBuffer[UART_IND_VK] << 16)|(inDataBuffer[UART_IND_VK+1] << 8)|(inDataBuffer[UART_IND_VK+2]));//电压系数
  111.                 voltage_t = ((inDataBuffer[UART_IND_VT] << 16)|(inDataBuffer[UART_IND_VT+1] << 8)|(inDataBuffer[UART_IND_VT+2]));//电压周期
  112.                
  113.                 if(isUpdataNewData(voltage_a,voltage_t)){
  114.                     updataVIPvalue(voltage_a,voltage_t);
  115.                     voltageCnt = 0;
  116.                 }
  117.                 else{
  118.                     voltageCnt++;
  119.                     if(voltageCnt >= COUNT_NUM){
  120.                         voltageCnt = 0;
  121.                         updataVIPvalue(voltage_a,voltage_t);
  122.                     }
  123.                 }
  124.                 printf("voltage:%d,%d,%d\r\n",voltage_a[0],voltage_a[1],voltage_a[2]);
  125.                 voltage_t = getVIPvalue(voltage_a);
  126.                
  127.                 if(voltage_t == 0){
  128.                     voltage = 0;
  129.                 }
  130.                 else{
  131.                     voltage = voltage_k * 100 / voltage_t;//电压10mV值,避免溢出
  132.                     voltage = voltage * 10;//电压mV值
  133.                 }
  134.                 printf("Vk = %d,Vt = %d,v = %d\r\n",voltage_k,voltage_t,voltage);
  135.             }
  136.             else{
  137.                 printf("%s(%d):V Flag Error\r\n",__func__,__LINE__);
  138.             }
  139.             
  140.             if((inDataBuffer[UART_IND_FG]&0x20) == 0x20){
  141.                 electricity_k = ((inDataBuffer[UART_IND_IK] << 16)|(inDataBuffer[UART_IND_IK+1] << 8)|(inDataBuffer[UART_IND_IK+2]));//电流系数
  142.                 electricity_t = ((inDataBuffer[UART_IND_IT] << 16)|(inDataBuffer[UART_IND_IT+1] << 8)|(inDataBuffer[UART_IND_IT+2]));//电流周期

  143.                 if(isUpdataNewData(electricity_a,electricity_t)){
  144.                     updataVIPvalue(electricity_a,electricity_t);
  145.                     electricityCnt = 0;
  146.                 }
  147.                 else{
  148.                     electricityCnt++;
  149.                     if(electricityCnt >= COUNT_NUM){
  150.                         electricityCnt = 0;
  151.                         updataVIPvalue(electricity_a,electricity_t);
  152.                     }
  153.                 }
  154.                 printf("electricity:%d,%d,%d\r\n",electricity_a[0],electricity_a[1],electricity_a[2]);
  155.                 electricity_t = getVIPvalue(electricity_a);
  156.                
  157.                 if(electricity_t == 0){
  158.                     electricity = 0;
  159.                 }
  160.                 else{
  161.                     electricity = electricity_k * 100 / electricity_t;//电流10mA值,避免溢出
  162.                     electricity = electricity * 10;//电流mA值
  163.                     #if(SAMPLE_RESISTANCE_MR == 1)
  164.                     //由于使用1mR的电阻,电流和功率需要不除以2
  165.                     #elif(SAMPLE_RESISTANCE_MR == 2)
  166.                     //由于使用2mR的电阻,电流和功率需要除以2
  167.                     electricity >>= 1;
  168.                     #endif
  169.                 }
  170.                 printf("Ik = %d,It = %d,I = %d\r\n",electricity_k,electricity_t,electricity);
  171.             }
  172.             else{
  173.                 printf("%s(%d):I Flag Error\r\n",__func__,__LINE__);
  174.             }

  175.             if((inDataBuffer[UART_IND_FG]&0x10) == 0x10){
  176.                 powerNewFlag = 0;
  177.                 power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系数
  178.                 power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
  179.                
  180.                 if(isUpdataNewData(power_a,power_t)){
  181.                     updataVIPvalue(power_a,power_t);
  182.                     powerCnt = 0;
  183.                 }
  184.                 else{
  185.                     powerCnt++;
  186.                     if(powerCnt >= COUNT_NUM){
  187.                         powerCnt = 0;
  188.                         updataVIPvalue(power_a,power_t);
  189.                     }
  190.                 }
  191.                 printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
  192.                 power_t = getVIPvalue(power_a);
  193.                
  194.                 if(power_t == 0){
  195.                     power = 0;
  196.                 }
  197.                 else{
  198.                     power = power_k * 100 / power_t;//功率10mw值,避免溢出
  199.                     power = power * 10;//功率mw值
  200.                     #if(SAMPLE_RESISTANCE_MR == 1)
  201.                     //由于使用1mR的电阻,电流和功率需要不除以2
  202.                     #elif(SAMPLE_RESISTANCE_MR == 2)
  203.                     //由于使用2mR的电阻,电流和功率需要除以2
  204.                     power >>= 1;
  205.                     #endif
  206.                 }
  207.                 printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
  208.             }
  209.             else if(powerNewFlag == 0){
  210.                 power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系数
  211.                 power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
  212.                
  213.                 if(isUpdataNewData(power_a,power_t)){
  214.                     unsigned long powerData = getVIPvalue(power_a);
  215.                     if(power_t > powerData){
  216.                         if((power_t - powerData) > (powerData >> 2)){
  217.                             resetVIPvalue(power_a,power_t);
  218.                         }
  219.                     }
  220.                 }
  221.                 printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
  222.                 power_t = getVIPvalue(power_a);
  223.                
  224.                 if(power_t == 0){
  225.                     power = 0;
  226.                 }
  227.                 else{
  228.                     power = power_k * 100 / power_t;//功率10mw值,避免溢出
  229.                     power = power * 10;//功率mw值
  230.                     #if(SAMPLE_RESISTANCE_MR == 1)
  231.                     //由于使用1mR的电阻,电流和功率需要不除以2
  232.                     #elif(SAMPLE_RESISTANCE_MR == 2)
  233.                     //由于使用2mR的电阻,电流和功率需要除以2
  234.                     power >>= 1;
  235.                     #endif
  236.                 }
  237.                 printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
  238.             }
  239.             
  240.             energyFlowFlag = (inDataBuffer[UART_IND_FG] >> 7);//获取当前电能计数溢出标致
  241.             runingInf.energyCurrent = ((inDataBuffer[UART_IND_EN] << 8)|(inDataBuffer[UART_IND_EN+1]));//更新当前的脉冲计数值
  242.             if(runingInf.energyFlowFlag != energyFlowFlag){//每次计数溢出时更新当前脉冲计数值
  243.                 runingInf.energyFlowFlag = energyFlowFlag;
  244.                 if(runingInf.energyCurrent > runingInf.energyLast){
  245.                     runingInf.energyCurrent = 0;
  246.                 }
  247.                 energy_cnt = runingInf.energyCurrent + ENERGY_FLOW_NUM - runingInf.energyLast;
  248.             }
  249.             else{
  250.                 energy_cnt = runingInf.energyCurrent - runingInf.energyLast;
  251.             }
  252.             runingInf.energyLast = runingInf.energyCurrent;
  253.             runingInf.energy += (energy_cnt * 10);//电能个数累加时扩大10倍,计算电能是除数扩大10倍,保证计算精度
  254.             
  255.             runingInf.energyUnit = 0xD693A400 >> 1;
  256.             runingInf.energyUnit /= (power_k >> 1);//1mR采样电阻0.001度电对应的脉冲个数
  257.             #if(SAMPLE_RESISTANCE_MR == 1)
  258.             //1mR锰铜电阻对应的脉冲个数
  259.             #elif(SAMPLE_RESISTANCE_MR == 2)
  260.             //2mR锰铜电阻对应的脉冲个数
  261.             runingInf.energyUnit = (runingInf.energyUnit << 1);//2mR采样电阻0.001度电对应的脉冲个数
  262.             #endif
  263.             runingInf.energyUnit =runingInf.energyUnit * 10;//0.001度电对应的脉冲个数(计算个数时放大了10倍,所以在这里也要放大10倍)
  264.             
  265.             //电能使用量=runingInf.energy/runingInf.energyUnit;//单位是0.001度
  266.             break;
  267.         
  268.         case 0xAA:
  269.             //芯片未校准
  270.             printf("HLW8032 not check\r\n");
  271.             break;

  272.         default :
  273.             if((startFlag & 0xF1) == 0xF1){//存储区异常,芯片坏了
  274.                 //芯片坏掉,反馈服务器
  275.                 printf("HLW8032 broken\r\n");
  276.             }

  277.             if((startFlag & 0xF2) == 0xF2){//功率异常
  278.                 runingInf.power = 0;//获取到的功率是以0.1W为单位
  279.                 power = 0;
  280.                 //printf("Power Error\r\n");
  281.             }
  282.             else{
  283.                 if((inDataBuffer[UART_IND_FG]&0x10) == 0x10){
  284.                     powerNewFlag = 0;
  285.                     power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系数
  286.                     power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
  287.                     
  288.                     if(isUpdataNewData(power_a,power_t)){
  289.                         updataVIPvalue(power_a,power_t);
  290.                         powerCnt = 0;
  291.                     }
  292.                     else{
  293.                         powerCnt++;
  294.                         if(powerCnt >= COUNT_NUM){
  295.                             powerCnt = 0;
  296.                             updataVIPvalue(power_a,power_t);
  297.                         }
  298.                     }
  299.                     //printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
  300.                     power_t = getVIPvalue(power_a);
  301.                     
  302.                     if(power_t == 0){
  303.                         power = 0;
  304.                     }
  305.                     else{
  306.                         power = power_k * 100 / power_t;//功率10mw值,避免溢出
  307.                         power = power * 10;//功率mw值
  308.                         #if(SAMPLE_RESISTANCE_MR == 1)
  309.                         //由于使用1mR的电阻,电流和功率需要不除以2
  310.                         #elif(SAMPLE_RESISTANCE_MR == 2)
  311.                         //由于使用2mR的电阻,电流和功率需要除以2
  312.                         power >>= 1;
  313.                         #endif
  314.                     }
  315.                     printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
  316.                 }
  317.                 else if(powerNewFlag == 0){
  318.                     power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系数
  319.                     power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
  320.                     
  321.                     if(isUpdataNewData(power_a,power_t)){
  322.                         unsigned long powerData = getVIPvalue(power_a);
  323.                         if(power_t > powerData){
  324.                             if((power_t - powerData) > (powerData >> 2)){
  325.                                 resetVIPvalue(power_a,power_t);
  326.                             }
  327.                         }
  328.                     }
  329.                     //printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
  330.                     power_t = getVIPvalue(power_a);
  331.                     
  332.                     if(power_t == 0){
  333.                         power = 0;
  334.                     }
  335.                     else{
  336.                         power = power_k * 100 / power_t;//功率10mw值,避免溢出
  337.                         power = power * 10;//功率mw值
  338.                         #if(SAMPLE_RESISTANCE_MR == 1)
  339.                         //由于使用1mR的电阻,电流和功率需要不除以2
  340.                         #elif(SAMPLE_RESISTANCE_MR == 2)
  341.                         //由于使用2mR的电阻,电流和功率需要除以2
  342.                         power >>= 1;
  343.                         #endif
  344.                     }
  345.                     printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
  346.                 }
  347.             }

  348.             if((startFlag & 0xF4) == 0xF4){//电流异常
  349.                 runingInf.electricity = 0;//获取到的电流以0.01A为单位               
  350.                 electricity = 0;
  351.             }
  352.             else{
  353.                 if((inDataBuffer[UART_IND_FG]&0x20) == 0x20){
  354.                     electricity_k = ((inDataBuffer[UART_IND_IK] << 16)|(inDataBuffer[UART_IND_IK+1] << 8)|(inDataBuffer[UART_IND_IK+2]));//电流系数
  355.                     electricity_t = ((inDataBuffer[UART_IND_IT] << 16)|(inDataBuffer[UART_IND_IT+1] << 8)|(inDataBuffer[UART_IND_IT+2]));//电流周期

  356.                     if(isUpdataNewData(electricity_a,electricity_t)){
  357.                         updataVIPvalue(electricity_a,electricity_t);
  358.                         electricityCnt = 0;
  359.                     }
  360.                     else{
  361.                         electricityCnt++;
  362.                         if(electricityCnt >= COUNT_NUM){
  363.                             electricityCnt = 0;
  364.                             updataVIPvalue(electricity_a,electricity_t);
  365.                         }
  366.                     }
  367.                     //printf("electricity:%d,%d,%d\r\n",electricity_a[0],electricity_a[1],electricity_a[2]);
  368.                     electricity_t = getVIPvalue(electricity_a);
  369.                     
  370.                     if(electricity_t == 0){
  371.                         electricity = 0;
  372.                     }
  373.                     else{
  374.                         electricity = electricity_k * 100 / electricity_t;//电流10mA值,避免溢出
  375.                         electricity = electricity * 10;//电流mA值
  376.                         #if(SAMPLE_RESISTANCE_MR == 1)
  377.                         //由于使用1mR的电阻,电流和功率需要不除以2
  378.                         #elif(SAMPLE_RESISTANCE_MR == 2)
  379.                         //由于使用2mR的电阻,电流和功率需要除以2
  380.                         electricity >>= 1;
  381.                         #endif
  382.                     }
  383.                     printf("Ik = %d,It = %d,I = %d\r\n",electricity_k,electricity_t,electricity);
  384.                 }
  385.                 else{
  386.                     printf("%s(%d):I Flag Error\r\n",__func__,__LINE__);
  387.                 }
  388.             }
  389.             
  390.             if((startFlag & 0xF8) == 0xF8){//电压异常
  391.                 runingInf.voltage = 0;//获取到的电压是以0.1V为单位               
  392.                 voltage = 0;
  393.             }
  394.             else{
  395.                 if((inDataBuffer[UART_IND_FG]&0x40) == 0x40){//获取当前电压标致,为1时说明电压检测OK
  396.                     voltage_k = ((inDataBuffer[UART_IND_VK] << 16)|(inDataBuffer[UART_IND_VK+1] << 8)|(inDataBuffer[UART_IND_VK+2]));//电压系数
  397.                     voltage_t = ((inDataBuffer[UART_IND_VT] << 16)|(inDataBuffer[UART_IND_VT+1] << 8)|(inDataBuffer[UART_IND_VT+2]));//电压周期
  398.                     
  399.                     if(isUpdataNewData(voltage_a,voltage_t)){
  400.                         updataVIPvalue(voltage_a,voltage_t);
  401.                         voltageCnt = 0;
  402.                     }
  403.                     else{
  404.                         voltageCnt++;
  405.                         if(voltageCnt >= COUNT_NUM){
  406.                             voltageCnt = 0;
  407.                             updataVIPvalue(voltage_a,voltage_t);
  408.                         }
  409.                     }
  410.                     //printf("voltage:%d,%d,%d\r\n",voltage_a[0],voltage_a[1],voltage_a[2]);
  411.                     voltage_t = getVIPvalue(voltage_a);
  412.                     
  413.                     if(voltage_t == 0){
  414.                         voltage = 0;
  415.                     }
  416.                     else{
  417.                         voltage = voltage_k * 100 / voltage_t;//电压10mV值,避免溢出
  418.                         voltage = voltage * 10;//电压mV值
  419.                     }
  420.                     printf("Vk = %d,Vt = %d,v = %d\r\n",voltage_k,voltage_t,voltage);
  421.                 }
  422.                 else{
  423.                     printf("%s(%d):V Flag Error\r\n",__func__,__LINE__);
  424.                 }
  425.             }
  426.             printf("0x%x:V = %d;I = %d;P = %d;\r\n",startFlag,voltage,electricity,power);
  427.             break;
  428.     }
  429.     return 1;
  430. }

  431. int main(int argc, char *argv[]) {
  432.     //模拟8032发送的一包数据 ,220V-5A-1100W
  433.     unsigned char dataTemp[24] = {0x55,0x5A,
  434.                          0x02,0xDE,0xC4,0x00,0x03,0x57,
  435.                          0x00,0x3F,0x66,0x00,0x0C,0xAE,
  436.                          0x52,0x90,0x54,0x00,0x13,0x37,
  437.                          0x71,0x00,0x13,0x61};//串口接收到的 8032发送的一包有效数据
  438.     DealUartInf(dataTemp,24);//处理8032数据
  439.     DealUartInf(dataTemp,24);//处理8032数据
  440.     DealUartInf(dataTemp,24);//处理8032数据
  441.     return 0;
  442. }

复制代码

所有资料51hei提供下载:
合力为HLW8032设计资料包V34.zip (17.82 MB, 下载次数: 126)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:60026 发表于 2023-10-18 21:38 | 显示全部楼层
记号一下!谢谢分享!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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