資料包為深圳市合力為科技的計量芯片HLW8032的應用開發(fā)包;包含datasheet,軟件參考設計,硬件參考設計,常見問題等文檔。筆者已經參考資料包打樣了電路板;測試效果還不錯,歡迎一起交流,學習!
51hei.png (6.45 KB, 下載次數: 69)
下載附件
2020-9-12 14:31 上傳
8266參考代碼
1、采樣電阻:0.001R
2、電壓分壓電阻:1M【參考設計資料是1.88M】
源程序如下:
- #include <stdio.h>
- #include <stdlib.h>
- /* run this program using the console pauser or add your own getch, system("pause") or input loop */
- #define SAMPLE_RESISTANCE_MR 1//使用的采樣錳銅電阻mR值
- #define UART_IND_HD 0
- #define UART_IND_5A 1
- #define UART_IND_VK 2
- #define UART_IND_VT 5
- #define UART_IND_IK 8
- #define UART_IND_IT 11
- #define UART_IND_PK 14
- #define UART_IND_PT 17
- #define UART_IND_FG 20
- #define UART_IND_EN 21
- #define UART_IND_SM 23
- #define ARRAY_LEN 3//平滑濾波buf長度
- #define COUNT_NUM 1//超時更新數據次數
- //8032電能計數脈沖溢出時的數據
- #define ENERGY_FLOW_NUM 65536 //電量采集,電能溢出時的脈沖計數值
- typedef struct RuningInf_s{
- unsigned short voltage;//當前電壓值,單位為0.1V
- unsigned short electricity;//當前電流值,單位為0.01A
- unsigned short power;//當前功率,單位為0.1W
-
- unsigned long energy;//當前消耗電能值對應的脈沖個數
- unsigned short energyCurrent;//電能脈沖當前統(tǒng)計值
- unsigned short energyLast;//電能脈沖上次統(tǒng)計值
- unsigned char energyFlowFlag;//電能脈沖溢出標致
-
- unsigned long energyUnit;//0.001度點對應的脈沖個數
- }RuningInf_t;
- RuningInf_t runingInf;
- //獲取電壓、電流、功率的有限數據
- unsigned long getVIPvalue(unsigned long *arr)//更新電壓、電流、功率的列表
- {
- int maxIndex = 0;
- int minIndex = 0;
- unsigned long sum = 0;
- int j = 0;
- for(j = 1; j<ARRAY_LEN; j++){
- if(arr[maxIndex] <= arr[j]){//避免所有數據一樣時minIndex等于maxIndex
- maxIndex = j;
- }
- if(arr[minIndex] > arr[j]){
- minIndex = j;
- }
- }
-
- for(j = 0; j<ARRAY_LEN; j++){
- if((maxIndex == j)||(minIndex == j)){
- continue;
- }
- else{
- return arr[j];
- }
- }
- }
- int isUpdataNewData(unsigned long *arr,unsigned long dat)//檢測電壓電流功率是否需要更新
- {
- if(arr[0] == dat){
- return 0;
- }
- else{
- return 1;
- }
- }
- void updataVIPvalue(unsigned long *arr,unsigned long dat)//更新電壓、電流、功率的列表
- {
- int ii = ARRAY_LEN-1;
- for(ii = ARRAY_LEN-1; ii > 0; ii--){
- arr[ii] = arr[ii-1];
- }
- arr[0] = dat;
- }
- void resetVIPvalue(unsigned long *arr,unsigned long dat)//更新所有電壓、電流、功率的列表
- {
- int ii = ARRAY_LEN-1;
- for(ii = ARRAY_LEN-1; ii >= 0; ii--){
- arr[ii] = dat;
- }
- }
- int DealUartInf(unsigned char *inDataBuffer,int recvlen)
- {
- unsigned char startFlag = 0;
-
- unsigned long voltage_k = 0;
- unsigned long voltage_t = 0;
- unsigned long voltage = 0;
- static unsigned long voltage_a[ARRAY_LEN] = {0};
- static unsigned int voltageCnt = 0;
- unsigned long electricity_k = 0;
- unsigned long electricity_t = 0;
- unsigned long electricity = 0;
- static unsigned long electricity_a[ARRAY_LEN] = {0};
- static unsigned int electricityCnt = 0;
- unsigned long power_k = 0;
- unsigned long power_t = 0;
- unsigned long power = 0;
- static unsigned long power_a[ARRAY_LEN]= {0};
- static unsigned int powerCnt = 0;
- static unsigned long powerNewFlag = 1;
-
- unsigned int energy_cnt = 0;
- unsigned char energyFlowFlag = 0;
- startFlag = inDataBuffer[UART_IND_HD];
- switch(startFlag)
- {
- case 0x55:
- if((inDataBuffer[UART_IND_FG]&0x40) == 0x40){//獲取當前電壓標致,為1時說明電壓檢測OK
- voltage_k = ((inDataBuffer[UART_IND_VK] << 16)|(inDataBuffer[UART_IND_VK+1] << 8)|(inDataBuffer[UART_IND_VK+2]));//電壓系數
- voltage_t = ((inDataBuffer[UART_IND_VT] << 16)|(inDataBuffer[UART_IND_VT+1] << 8)|(inDataBuffer[UART_IND_VT+2]));//電壓周期
-
- if(isUpdataNewData(voltage_a,voltage_t)){
- updataVIPvalue(voltage_a,voltage_t);
- voltageCnt = 0;
- }
- else{
- voltageCnt++;
- if(voltageCnt >= COUNT_NUM){
- voltageCnt = 0;
- updataVIPvalue(voltage_a,voltage_t);
- }
- }
- printf("voltage:%d,%d,%d\r\n",voltage_a[0],voltage_a[1],voltage_a[2]);
- voltage_t = getVIPvalue(voltage_a);
-
- if(voltage_t == 0){
- voltage = 0;
- }
- else{
- voltage = voltage_k * 100 / voltage_t;//電壓10mV值,避免溢出
- voltage = voltage * 10;//電壓mV值
- }
- printf("Vk = %d,Vt = %d,v = %d\r\n",voltage_k,voltage_t,voltage);
- }
- else{
- printf("%s(%d):V Flag Error\r\n",__func__,__LINE__);
- }
-
- if((inDataBuffer[UART_IND_FG]&0x20) == 0x20){
- electricity_k = ((inDataBuffer[UART_IND_IK] << 16)|(inDataBuffer[UART_IND_IK+1] << 8)|(inDataBuffer[UART_IND_IK+2]));//電流系數
- electricity_t = ((inDataBuffer[UART_IND_IT] << 16)|(inDataBuffer[UART_IND_IT+1] << 8)|(inDataBuffer[UART_IND_IT+2]));//電流周期
- if(isUpdataNewData(electricity_a,electricity_t)){
- updataVIPvalue(electricity_a,electricity_t);
- electricityCnt = 0;
- }
- else{
- electricityCnt++;
- if(electricityCnt >= COUNT_NUM){
- electricityCnt = 0;
- updataVIPvalue(electricity_a,electricity_t);
- }
- }
- printf("electricity:%d,%d,%d\r\n",electricity_a[0],electricity_a[1],electricity_a[2]);
- electricity_t = getVIPvalue(electricity_a);
-
- if(electricity_t == 0){
- electricity = 0;
- }
- else{
- electricity = electricity_k * 100 / electricity_t;//電流10mA值,避免溢出
- electricity = electricity * 10;//電流mA值
- #if(SAMPLE_RESISTANCE_MR == 1)
- //由于使用1mR的電阻,電流和功率需要不除以2
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //由于使用2mR的電阻,電流和功率需要除以2
- electricity >>= 1;
- #endif
- }
- printf("Ik = %d,It = %d,I = %d\r\n",electricity_k,electricity_t,electricity);
- }
- else{
- printf("%s(%d):I Flag Error\r\n",__func__,__LINE__);
- }
- if((inDataBuffer[UART_IND_FG]&0x10) == 0x10){
- powerNewFlag = 0;
- power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系數
- power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
-
- if(isUpdataNewData(power_a,power_t)){
- updataVIPvalue(power_a,power_t);
- powerCnt = 0;
- }
- else{
- powerCnt++;
- if(powerCnt >= COUNT_NUM){
- powerCnt = 0;
- updataVIPvalue(power_a,power_t);
- }
- }
- printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
- power_t = getVIPvalue(power_a);
-
- if(power_t == 0){
- power = 0;
- }
- else{
- power = power_k * 100 / power_t;//功率10mw值,避免溢出
- power = power * 10;//功率mw值
- #if(SAMPLE_RESISTANCE_MR == 1)
- //由于使用1mR的電阻,電流和功率需要不除以2
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //由于使用2mR的電阻,電流和功率需要除以2
- power >>= 1;
- #endif
- }
- printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
- }
- else if(powerNewFlag == 0){
- power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系數
- power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
-
- if(isUpdataNewData(power_a,power_t)){
- unsigned long powerData = getVIPvalue(power_a);
- if(power_t > powerData){
- if((power_t - powerData) > (powerData >> 2)){
- resetVIPvalue(power_a,power_t);
- }
- }
- }
- printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
- power_t = getVIPvalue(power_a);
-
- if(power_t == 0){
- power = 0;
- }
- else{
- power = power_k * 100 / power_t;//功率10mw值,避免溢出
- power = power * 10;//功率mw值
- #if(SAMPLE_RESISTANCE_MR == 1)
- //由于使用1mR的電阻,電流和功率需要不除以2
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //由于使用2mR的電阻,電流和功率需要除以2
- power >>= 1;
- #endif
- }
- printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
- }
-
- energyFlowFlag = (inDataBuffer[UART_IND_FG] >> 7);//獲取當前電能計數溢出標致
- runingInf.energyCurrent = ((inDataBuffer[UART_IND_EN] << 8)|(inDataBuffer[UART_IND_EN+1]));//更新當前的脈沖計數值
- if(runingInf.energyFlowFlag != energyFlowFlag){//每次計數溢出時更新當前脈沖計數值
- runingInf.energyFlowFlag = energyFlowFlag;
- if(runingInf.energyCurrent > runingInf.energyLast){
- runingInf.energyCurrent = 0;
- }
- energy_cnt = runingInf.energyCurrent + ENERGY_FLOW_NUM - runingInf.energyLast;
- }
- else{
- energy_cnt = runingInf.energyCurrent - runingInf.energyLast;
- }
- runingInf.energyLast = runingInf.energyCurrent;
- runingInf.energy += (energy_cnt * 10);//電能個數累加時擴大10倍,計算電能是除數擴大10倍,保證計算精度
-
- runingInf.energyUnit = 0xD693A400 >> 1;
- runingInf.energyUnit /= (power_k >> 1);//1mR采樣電阻0.001度電對應的脈沖個數
- #if(SAMPLE_RESISTANCE_MR == 1)
- //1mR錳銅電阻對應的脈沖個數
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //2mR錳銅電阻對應的脈沖個數
- runingInf.energyUnit = (runingInf.energyUnit << 1);//2mR采樣電阻0.001度電對應的脈沖個數
- #endif
- runingInf.energyUnit =runingInf.energyUnit * 10;//0.001度電對應的脈沖個數(計算個數時放大了10倍,所以在這里也要放大10倍)
-
- //電能使用量=runingInf.energy/runingInf.energyUnit;//單位是0.001度
- break;
-
- case 0xAA:
- //芯片未校準
- printf("HLW8032 not check\r\n");
- break;
- default :
- if((startFlag & 0xF1) == 0xF1){//存儲區(qū)異常,芯片壞了
- //芯片壞掉,反饋服務器
- printf("HLW8032 broken\r\n");
- }
- if((startFlag & 0xF2) == 0xF2){//功率異常
- runingInf.power = 0;//獲取到的功率是以0.1W為單位
- power = 0;
- //printf("Power Error\r\n");
- }
- else{
- if((inDataBuffer[UART_IND_FG]&0x10) == 0x10){
- powerNewFlag = 0;
- power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系數
- power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
-
- if(isUpdataNewData(power_a,power_t)){
- updataVIPvalue(power_a,power_t);
- powerCnt = 0;
- }
- else{
- powerCnt++;
- if(powerCnt >= COUNT_NUM){
- powerCnt = 0;
- updataVIPvalue(power_a,power_t);
- }
- }
- //printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
- power_t = getVIPvalue(power_a);
-
- if(power_t == 0){
- power = 0;
- }
- else{
- power = power_k * 100 / power_t;//功率10mw值,避免溢出
- power = power * 10;//功率mw值
- #if(SAMPLE_RESISTANCE_MR == 1)
- //由于使用1mR的電阻,電流和功率需要不除以2
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //由于使用2mR的電阻,電流和功率需要除以2
- power >>= 1;
- #endif
- }
- printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
- }
- else if(powerNewFlag == 0){
- power_k = ((inDataBuffer[UART_IND_PK] << 16)|(inDataBuffer[UART_IND_PK+1] << 8)|(inDataBuffer[UART_IND_PK+2]));//功率系數
- power_t = ((inDataBuffer[UART_IND_PT] << 16)|(inDataBuffer[UART_IND_PT+1] << 8)|(inDataBuffer[UART_IND_PT+2]));//功率周期
-
- if(isUpdataNewData(power_a,power_t)){
- unsigned long powerData = getVIPvalue(power_a);
- if(power_t > powerData){
- if((power_t - powerData) > (powerData >> 2)){
- resetVIPvalue(power_a,power_t);
- }
- }
- }
- //printf("power:%d,%d,%d\r\n",power_a[0],power_a[1],power_a[2]);
- power_t = getVIPvalue(power_a);
-
- if(power_t == 0){
- power = 0;
- }
- else{
- power = power_k * 100 / power_t;//功率10mw值,避免溢出
- power = power * 10;//功率mw值
- #if(SAMPLE_RESISTANCE_MR == 1)
- //由于使用1mR的電阻,電流和功率需要不除以2
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //由于使用2mR的電阻,電流和功率需要除以2
- power >>= 1;
- #endif
- }
- printf("Pk = %d,Pt = %d,P = %d\r\n",power_k,power_t,power);
- }
- }
- if((startFlag & 0xF4) == 0xF4){//電流異常
- runingInf.electricity = 0;//獲取到的電流以0.01A為單位
- electricity = 0;
- }
- else{
- if((inDataBuffer[UART_IND_FG]&0x20) == 0x20){
- electricity_k = ((inDataBuffer[UART_IND_IK] << 16)|(inDataBuffer[UART_IND_IK+1] << 8)|(inDataBuffer[UART_IND_IK+2]));//電流系數
- electricity_t = ((inDataBuffer[UART_IND_IT] << 16)|(inDataBuffer[UART_IND_IT+1] << 8)|(inDataBuffer[UART_IND_IT+2]));//電流周期
- if(isUpdataNewData(electricity_a,electricity_t)){
- updataVIPvalue(electricity_a,electricity_t);
- electricityCnt = 0;
- }
- else{
- electricityCnt++;
- if(electricityCnt >= COUNT_NUM){
- electricityCnt = 0;
- updataVIPvalue(electricity_a,electricity_t);
- }
- }
- //printf("electricity:%d,%d,%d\r\n",electricity_a[0],electricity_a[1],electricity_a[2]);
- electricity_t = getVIPvalue(electricity_a);
-
- if(electricity_t == 0){
- electricity = 0;
- }
- else{
- electricity = electricity_k * 100 / electricity_t;//電流10mA值,避免溢出
- electricity = electricity * 10;//電流mA值
- #if(SAMPLE_RESISTANCE_MR == 1)
- //由于使用1mR的電阻,電流和功率需要不除以2
- #elif(SAMPLE_RESISTANCE_MR == 2)
- //由于使用2mR的電阻,電流和功率需要除以2
- electricity >>= 1;
- #endif
- }
- printf("Ik = %d,It = %d,I = %d\r\n",electricity_k,electricity_t,electricity);
- }
- else{
- printf("%s(%d):I Flag Error\r\n",__func__,__LINE__);
- }
- }
-
- if((startFlag & 0xF8) == 0xF8){//電壓異常
- runingInf.voltage = 0;//獲取到的電壓是以0.1V為單位
- voltage = 0;
- }
- else{
- if((inDataBuffer[UART_IND_FG]&0x40) == 0x40){//獲取當前電壓標致,為1時說明電壓檢測OK
- voltage_k = ((inDataBuffer[UART_IND_VK] << 16)|(inDataBuffer[UART_IND_VK+1] << 8)|(inDataBuffer[UART_IND_VK+2]));//電壓系數
- voltage_t = ((inDataBuffer[UART_IND_VT] << 16)|(inDataBuffer[UART_IND_VT+1] << 8)|(inDataBuffer[UART_IND_VT+2]));//電壓周期
-
- if(isUpdataNewData(voltage_a,voltage_t)){
- updataVIPvalue(voltage_a,voltage_t);
- voltageCnt = 0;
- }
- else{
- voltageCnt++;
- if(voltageCnt >= COUNT_NUM){
- voltageCnt = 0;
- updataVIPvalue(voltage_a,voltage_t);
- }
- }
- //printf("voltage:%d,%d,%d\r\n",voltage_a[0],voltage_a[1],voltage_a[2]);
- voltage_t = getVIPvalue(voltage_a);
-
- if(voltage_t == 0){
- voltage = 0;
- }
- else{
- voltage = voltage_k * 100 / voltage_t;//電壓10mV值,避免溢出
- voltage = voltage * 10;//電壓mV值
- }
- printf("Vk = %d,Vt = %d,v = %d\r\n",voltage_k,voltage_t,voltage);
- }
- else{
- printf("%s(%d):V Flag Error\r\n",__func__,__LINE__);
- }
- }
- printf("0x%x:V = %d;I = %d;P = %d;\r\n",startFlag,voltage,electricity,power);
- break;
- }
- return 1;
- }
- int main(int argc, char *argv[]) {
- //模擬8032發(fā)送的一包數據 ,220V-5A-1100W
- unsigned char dataTemp[24] = {0x55,0x5A,
- 0x02,0xDE,0xC4,0x00,0x03,0x57,
- 0x00,0x3F,0x66,0x00,0x0C,0xAE,
- 0x52,0x90,0x54,0x00,0x13,0x37,
- 0x71,0x00,0x13,0x61};//串口接收到的 8032發(fā)送的一包有效數據
- DealUartInf(dataTemp,24);//處理8032數據
- DealUartInf(dataTemp,24);//處理8032數據
- DealUartInf(dataTemp,24);//處理8032數據
- return 0;
- }
復制代碼
所有資料51hei提供下載:
合力為HLW8032設計資料包V34.zip
(17.82 MB, 下載次數: 133)
2020-9-12 09:59 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|