标题:
合力为HLW8032计量芯片设计资料包 含8266源程序
[打印本页]
作者:
DONGDONG66
时间:
2020-9-12 10:00
标题:
合力为HLW8032计量芯片设计资料包 含8266源程序
资料包为深圳市合力为科技的计量芯片HLW8032的应用开发包;包含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;//电能脉冲当前统计值
unsigned short energyLast;//电能脉冲上次统计值
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){//存储区异常,芯片坏了
//芯片坏掉,反馈服务器
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发送的一包数据 ,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发送的一包有效数据
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
作者:
FQ967
时间:
2023-10-18 21:38
记号一下!谢谢分享!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1