HLW8112芯片软件实现代码(12)
2026/7/14 5:11:27 网站建设 项目流程

接前一篇文章:HLW8112芯片软件实现代码(11)

二、寄存器介绍

2. 详述

上一回补讲了官方例程中的主函数,并开始讲解HLW8112_Measure函数。

(2)HLW8112_Measure函数

为了便于理解和回顾,再次贴出HLW8112_Measure函数代码,在HARDWARE\HLW8112-SPI\HLW8112-SPI.c中,如下:

/*===================================================== * Function : void HLW8012_Measure(void); * Describe : * Input : none * Output : none * Return : none * Record : 2018/05/10 =====================================================*/ void HLW8112_Measure(void) { Read_HLW8112_PA_I(); Read_HLW8112_U(); Read_HLW8112_PA(); Read_HLW8112_EA(); Read_HLW8112_PB_I(); Read_HLW8112_PB(); Read_HLW8112_EB(); Read_HLW8112_DC_Offset(); printf("直流参数测量-SPI\r\n"); printf("A通道电能参数\r\n"); printf("U32_AC_V = %f\r\n", U32_AC_V); //电压 printf("U32_AC_I = %f\r\n", U32_AC_I); //A通道电流 printf("U32_AC_P = %f\r\n", U32_AC_P); //A通道功率 printf("U32_AC_E = %f\r\n", U32_AC_E); //A通道电量 printf("B通道电能参数\r\n"); printf("U32_AC_V = %f\r\n", U32_AC_V); //电压 printf("U32_AC_I_B = %f\r\n", U32_AC_I_B); //B通道电流 printf("U32_AC_P_B = %f\r\n", U32_AC_P_B); //B通道功率 printf("U32_AC_E_B = %f\r\n", U32_AC_E_B); //B通道电量 printf("\r\n\r\n"); //插入换行 printf("寄存器数值\r\n"); printf("U16_RMSIA_Offset = %x\r\n", U16_RMSIA_Offset); printf("U16_RMSIB_Offset = %x\r\n", U16_RMSIB_Offset); printf("U16_PAOS_Offset = %x\r\n", U16_PAOS_Offset); printf("U16_PBOS_Offset = %x\r\n", U16_PBOS_Offset); printf("U32_RMSIA_RegData = %x\r\n", U32_RMSIA_RegData); printf("U32_RMSIB_RegData = %x\r\n", U32_RMSIB_RegData); printf("U32_RMSU_RegData = %x\r\n", U32_RMSU_RegData); printf("U32_POWERPA_RegData = %x\r\n", U32_POWERPA_RegData); printf("U32_POWERPB_RegData = %x\r\n", U32_POWERPB_RegData); printf("\r\n\r\n"); //插入换行 }

上一回讲了Read_HLW8112_PA_I(),本回继续往下讲进行解析。

2)Read_HLW8112_U函数

Read_HLW8112_U函数也在HLW8112-SPI.c中,代码如下:

/*===================================================== * Function : void Read_HLW8112_U(void) * Describe : 读取电压 * Input : none * Output : none * Return : none * Record : 2018/05/09 =====================================================*/ void Read_HLW8112_U(void) { //计算公式: U16_AC_V = (U32_RMSU_RegData * U16_RMSUC_RegData) / (电压系数 * 2^23) float a; unsigned long b; U32_RMSU_RegData = Read_HLW8112_RegData(REG_RMSU_ADDR, 3); //读取电压寄存器值 if (U32_RMSU_RegData > 0x800000) { b = ~U32_RMSU_RegData; a = (float)b; } else { a = (float)U32_RMSU_RegData; } // a = (float)U32_RMSU_RegData; a = a * U16_RMSUC_RegData; a = a / 0x400000; //电压计算出来的浮点数单位是1mV,比如22083.12,表示220.8312V a = a / 1; //DEMO板的电压系数 = 1 a = a / 100; a = a * D_CAL_U; //直流测量需要校正,D_CAL_U是校正系数,默认是1 U32_AC_V = a; }

代码中,U32_RMSU_RegData是同文件中的全局变量 ,保存的是电压寄存器的值。

unsigned long U32_RMSU_RegData; //电压寄存器值

REG_RMSU_ADDR宏也在HLW8110.h中定义,如下:

#define REG_RMSU_ADDR 0x26

REG_RMSIA_ADDR对应的是电压有效值寄存器(RmsU)。

电压有效值寄存器(RmsU)的详情如下:

读取了电压有效值之后,保存到U32_RMSU_RegData变量中。接下来判断最高位(Bit23)是否为1。如果为1,则说明是补码,需要取绝对值;如果为0,则是正常值(注意:这里讲解的是直流测量,交流测量另有计算方法)。这一段对应上边代码中的以下部分:

if (U32_RMSU_RegData > 0x800000) { b = ~U32_RMSU_RegData; a = (float)b; } else { a = (float)U32_RMSU_RegData; }

接下来的一系列计算:

a = a * U16_RMSUC_RegData; a = a / 0x400000; //电压计算出来的浮点数单位是1mV,比如22083.12,表示220.8312V a = a / 1; //DEMO板的电压系数 = 1 a = a / 100; a = a * D_CAL_U; //直流测量需要校正,D_CAL_U是校正系数,默认是1

就是按照芯片手册中的计算公式进行的计算:

代码中的第1行:

a = a * U16_RMSUC_RegData;

相当于公式中的RmsUXX * RmsUXXC。

代码中的第2行:

a = a / 0x400000; //电压计算出来的浮点数单位是1mV,比如22083.12,表示220.8312V

相当于公式中的RmsUXX * RmsUXXC / 2^22(注意不是2^23)。

代码中的第3行:

a = a / 1; //DEMO板的电压系数 = 1

相当于再除以K2。这里注意:K2的值视具体的硬件电路确定。官方Demo板中的K2是1(下图红色框中的电压通道的分压电阻比),自己的板子不一定是1了。

代码中的第4行:

a = a / 100;

是将10mV转化为V,因为使用上述公式计算出来的电压单位为10mV(注意不是1mV,除以的是100不是1000)。

代码中的第5行:

a = a * D_CAL_U; //直流测量需要校正,D_CAL_U是校正系数,默认是1

是再通过电压校正系数进行校正。一般该系数取1就好。

下一回继续解析HLW8112_Measure函数中的后续函数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询