/*========================================================================================================= * File Name : HLW8110.c * Describe : HLW8110 UART 通讯程序,使用USATR2.(HLW8110 code,use USATE2) * Author : Tuqiang * Version : V1.3 * Record : 2019/04/16,V1.2 * Record : 2020/04/02, V1.3 ==========================================================================================================*/ #include "Hlw8110.h" #include "stdio.h" #include "Config.h" #include "SysTick.h" #include "uart.h" #include "Timer.h" #include "mb.h" #include "common.h" #if HLW8110 #define HIGH 1 #define LOW 0 union IntData { unsigned int inte; unsigned char byte[2]; }; union LongData { unsigned long int word; unsigned int inte[2]; unsigned char byte[4]; }; unsigned char u8_TxBuf[10]; unsigned char u8_RxBuf[10]; unsigned char u8_TX_Length; unsigned char u8_RX_Length; unsigned char u8_RX_Index; unsigned char B_Rx_Finish; unsigned char B_Rx_Data_ING; unsigned char B_Read_Error; unsigned int U16_TempData; unsigned int U16_IFData; unsigned int U16_RIFData; unsigned int U16_LineFData; unsigned int U16_AngleData; unsigned int U16_PFData; unsigned int U16_HFConst_RegData; unsigned int U16_RMSIAC_RegData; // A通道电流转换系数 unsigned int U16_RMSIBC_RegData; // B通道电流转换系数 unsigned int U16_RMSUC_RegData; // 电压通道转换系数 unsigned int U16_PowerPAC_RegData; // A通道功率转换系数 unsigned int U16_PowerPBC_RegData; // B通道功率转换系数 unsigned int U16_PowerSC_RegData; // 视在功率转换系数,如果选择A通道,则是A通道视在功率转换系数。A和B通道只能二者选其一 unsigned int U16_EnergyAC_RegData; // A通道有功电能(量)转换系数 unsigned int U16_EnergyBC_RegData; // A通道有功电能(量)转换系数 unsigned int U16_CheckSUM_RegData; // 转换系数的CheckSum unsigned int U16_CheckSUM_Data; // 转换系数计算出来的CheckSum unsigned int U16_Check_SysconReg_Data; unsigned int U16_Check_EmuconReg_Data; unsigned int U16_Check_Emucon2Reg_Data; unsigned long U32_RMSIA_RegData; // A通道电流有效值寄存器 unsigned long U32_RMSU_RegData; // 电压有效值寄存器 unsigned long U32_POWERPA_RegData; // A通道功率有效值寄存器 unsigned long U32_ENERGY_PA_RegData; // A通道有功电能(量)有效值寄存器 unsigned long U32_RMSIB_RegData; // B通道电流有效值寄存器 unsigned long U32_POWERPB_RegData; // B通道功率有效值寄存器 unsigned long U32_ENERGY_PB_RegData; // B通道有功电能(量)有效值寄存器 float F_AC_V; // 电压有效值 float F_AC_I; // A通道电流 float F_AC_P; // A通道有功功率 float F_AC_PS; //see power float F_AC_E; // A通道有功电能(量) float F_AC_BACKUP_E; // A通道电量备份 float F_AC_PF; // 功率因素,A通道和B通道只能选其一 float F_Angle; // 相角,A通道和B通道只能选其一 float F_AC_I_B; // B通道电流有效值 float F_AC_P_B; // B通道有功功率 float F_AC_E_B; // B通道有功电能(量) float F_AC_BACKUP_E_B; // B通道电量备份 float F_AC_LINE_Freq; // 市电线性频率 uint8_t voltage_flag = 0; void Clear_RxBuf(void) { unsigned char i; for(i = 0;i<10;i++) { u8_RxBuf[i] = 0x00; } B_Rx_Data_ING = 0; B_Rx_Finish = FALSE; u8_RX_Index = 0; } unsigned char HLW8110_checkSum_Write(unsigned char u8_Reg_length) { unsigned char i; unsigned char Temp_u8_checksum; unsigned int a; a = 0x0000; Temp_u8_checksum = 0; for (i = 0; i< (u8_Reg_length-1); i++) { a += u8_TxBuf[i]; } a = ~a; Temp_u8_checksum = a & 0xff; return Temp_u8_checksum; } unsigned char HLW8110_checkSum_Read(unsigned char u8_Reg_length) { unsigned char i; unsigned char Temp_u8_checksum; unsigned int a; a = 0x0000; Temp_u8_checksum = 0; for (i = 0; i< (u8_Reg_length-1); i++) { a += u8_RxBuf[i]; } a = a + u8_TxBuf[0] + u8_TxBuf[1]; a = ~a; Temp_u8_checksum = a & 0xff; return Temp_u8_checksum; } void Uart_HLW8110_WriteREG_EN(void) { u8_TX_Length = 4; u8_RX_Length = 0; u8_TxBuf[0] = 0xa5; u8_TxBuf[1] = 0xea; u8_TxBuf[2] = 0xe5; // u8_TxBuf[3] = 0x8b; //checksum u8_TxBuf[3] = HLW8110_checkSum_Write(u8_TX_Length); Start_Send_UartData(u8_TX_Length); } void Uart_HLW8110_WriteREG_DIS(void) { u8_TX_Length = 4; u8_RX_Length = 0; u8_TxBuf[0] = 0xa5; u8_TxBuf[1] = 0xea; u8_TxBuf[2] = 0xdc; // u8_TxBuf[3] = 0x94; //checksum u8_TxBuf[3] = HLW8110_checkSum_Write(u8_TX_Length); Start_Send_UartData(u8_TX_Length); } void Uart_HLW8110_Set_Channel_A(void) { u8_TX_Length = 4; u8_RX_Length = 0; u8_TxBuf[0] = 0xa5; u8_TxBuf[1] = 0xea; u8_TxBuf[2] = 0x5a; // u8_TxBuf[3] = 0x16; //checksum u8_TxBuf[3] = HLW8110_checkSum_Write(u8_TX_Length); Start_Send_UartData(u8_TX_Length); } void Uart_Read_HLW8110_Reg(unsigned char ADDR_Reg,unsigned char u8_reg_length) { u8_TxBuf[0] = 0xa5; u8_TxBuf[1] = ADDR_Reg; u8_TX_Length = 2; u8_RX_Length = u8_reg_length + 1; // +1,是因为接收的数据长度,除了REG值,还有一个校验和数据 Clear_RxBuf(); //清空接收缓冲区 //Awaken_Hlw8110(); //DelayNms(2); Start_Send_UartData(u8_TX_Length); } void Uart_Write_HLW8110_Reg(unsigned char ADDR_Reg,unsigned char u8_reg_length,unsigned long u32_data) { unsigned char i; union LongData Temp_u32_a; u8_TxBuf[0] = 0xa5; u8_TxBuf[1] = ADDR_Reg|0x80; Temp_u32_a.word = u32_data; for (i = 0; i< u8_reg_length; i++) { u8_TxBuf[i+2] = Temp_u32_a.byte[u8_reg_length-1-i]; //STM32,32位MCU,union定义,是低位在前 //u8_TxBuf[i+2] = Temp_u32_a.byte[4-u8_reg_length + i]; //STM8,STC MCU, union定义,是高位在前 } u8_TX_Length = 3 + u8_reg_length ; u8_RX_Length = 0; u8_TxBuf[u8_TX_Length-1] = HLW8110_checkSum_Write(u8_TX_Length); Start_Send_UartData(u8_TX_Length); } void Uart_HLW8110_Reset(void) { u8_TX_Length = 4; u8_RX_Length = 0; u8_TxBuf[0] = 0xa5; u8_TxBuf[1] = 0xea; u8_TxBuf[2] = 0x96; // u8_TxBuf[3] = 0xda; //checksum u8_TxBuf[3] = HLW8110_checkSum_Write(u8_TX_Length); Start_Send_UartData(u8_TX_Length); } unsigned char Judge_CheckSum_HLW8110_Calfactor(void) { unsigned long a; //unsigned int b; //unsigned int c; unsigned char d; //读取RmsIAC、RmsIBC、RmsUC、PowerPAC、PowerPBC、PowerSC、EnergAc、EnergBc的值 Uart_Read_HLW8110_Reg(REG_RMS_IAC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_RMSIAC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("A通道电流转换系数:%x\n " ,U16_RMSIAC_RegData); } Uart_Read_HLW8110_Reg(REG_RMS_IBC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_RMSIBC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("B通道电流转换系数:%x\n " ,U16_RMSIBC_RegData); } Uart_Read_HLW8110_Reg(REG_RMS_UC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_RMSUC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("电压通道转换系数:%x\n " ,U16_RMSUC_RegData); } Uart_Read_HLW8110_Reg(REG_POWER_PAC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_PowerPAC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("A通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } Uart_Read_HLW8110_Reg(REG_POWER_PBC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_PowerPBC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("B通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } Uart_Read_HLW8110_Reg(REG_POWER_SC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_PowerSC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("视在功率转换系数:%x\n " ,U16_PowerSC_RegData); } Uart_Read_HLW8110_Reg(REG_ENERGY_AC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_EnergyAC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("A通道电量转换系数:%x\n " ,U16_EnergyAC_RegData); } Uart_Read_HLW8110_Reg(REG_ENERGY_BC_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_EnergyBC_RegData = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("B通道电量转换系数:%x\n " ,U16_EnergyBC_RegData); } Uart_Read_HLW8110_Reg(REG_CHECKSUM_ADDR,2); DelayNms(50); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_CheckSUM_RegData= (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; // printf("系数校验和:%x\n " ,U16_CheckSUM_RegData); } a = 0; a = ~(0xffff+U16_RMSIAC_RegData + U16_RMSIBC_RegData + U16_RMSUC_RegData + U16_PowerPAC_RegData + U16_PowerPBC_RegData + U16_PowerSC_RegData + U16_EnergyAC_RegData + U16_EnergyBC_RegData ); U16_CheckSUM_Data = a & 0xffff; // printf("计算系数校验和:%x\n " ,U16_CheckSUM_Data); if ( U16_CheckSUM_Data == U16_CheckSUM_RegData) { d = 1; // printf("校验和正确\r\n "); } else { d = 0; // printf("校验和出错\r\n "); } return d; } void Init_HLW8110(void) { //电流通道A设置命令,指定当前用于计算视在功率、功率因数、相角、瞬时有功功率、瞬时视在功率和有功功率过载的信号指示 的通道为通道A for(int i = 0 ; i < 50 ;i++) { Uart_HLW8110_WriteREG_EN(); DelayNms(10); Uart_HLW8110_Set_Channel_A(); DelayNms(10); Uart_Write_HLW8110_Reg(REG_SYSCON_ADDR,2,0x0a04); //开启A通道,关闭B通道,电压通道PGA = 1,电流通道PGA = 16 DelayNms(10); Uart_Write_HLW8110_Reg(REG_EMUCON_ADDR,2,0x0001); //1,使能PFA 脉冲输出和有功电能寄存器累加; // Uart_Write_HLW8110_Reg(REG_EMUCON_ADDR,2,0x0018); //正向和负向过零点均发生变化,ZXD0 = 1,ZXD1 = 1 DelayNms(10); Uart_Write_HLW8110_Reg(REG_EMUCON2_ADDR,2,0x0065); //0x0001是EMUCON2的默认值,waveEn = 1,zxEn = 1,A通道电量寄存器,读后不清0,EPA_CB = 1;打开功率因素检测 DelayNms(10); Uart_HLW8110_WriteREG_DIS(); B_Read_Error = 0; Check_WriteReg_Success(); if (B_Read_Error == 1) { DelayNms(100); }else { break; } } // DelayNms(3); //读取地址是0x6F至0x77的寄存器,验证系数是否正确 // Judge_CheckSum_HLW8110_Calfactor(); uint8_t d = 0; for(int i = 0;i < 3;i++) { d = Judge_CheckSum_HLW8110_Calfactor(); if(d) { break; } } if(d == 0) { U16_RMSIAC_RegData = 0xcad1; U16_RMSIBC_RegData = 0xcacf; U16_RMSUC_RegData = 0xa4c3; U16_PowerPAC_RegData = 0xab47; U16_PowerPBC_RegData = 0xab49; U16_PowerSC_RegData = 0xab41; U16_EnergyAC_RegData = 0xe9cc; U16_EnergyBC_RegData = 0xe9ce; } } void re_check_write_reg_success(void) { Uart_Read_HLW8110_Reg(REG_SYSCON_ADDR,2); DelayNms(10); eMBPoll(); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_Check_SysconReg_Data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); // printf("写入的SysconReg寄存器:%lx\n " ,U16_Check_SysconReg_Data); if(U16_Check_SysconReg_Data == 0x0a04) { }else { B_Read_Error = 1; } } else { // printf("SysconReg寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_EMUCON_ADDR,2); DelayNms(10); eMBPoll(); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_Check_EmuconReg_Data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); // printf("写入的EmuconReg寄存器:%lx\n " ,U16_Check_EmuconReg_Data); if(U16_Check_EmuconReg_Data == 0x0001) { }else { B_Read_Error = 1; } } else { // printf("EmuconReg寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_EMUCON2_ADDR,2); DelayNms(10); eMBPoll(); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_Check_Emucon2Reg_Data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); // printf("写入的Emucon2Reg寄存器寄存器:%lx\n " ,U16_Check_Emucon2Reg_Data); if(U16_Check_Emucon2Reg_Data == 0x0065) { }else { B_Read_Error = 1; } } else { // printf("Emucon2Reg寄存器读取出错\r\n"); B_Read_Error = 1; } } void reinit_hlw8110() { for(int i = 0 ; i < 50 ;i++) { Uart_HLW8110_WriteREG_EN(); DelayNms(10); eMBPoll(); Uart_HLW8110_Set_Channel_A(); DelayNms(10); eMBPoll(); Uart_Write_HLW8110_Reg(REG_SYSCON_ADDR,2,0x0a04); DelayNms(10); eMBPoll(); Uart_Write_HLW8110_Reg(REG_EMUCON_ADDR,2,0x0001); DelayNms(10); eMBPoll(); Uart_Write_HLW8110_Reg(REG_EMUCON2_ADDR,2,0x0065); DelayNms(10); eMBPoll(); Uart_HLW8110_WriteREG_DIS(); B_Read_Error = 0; re_check_write_reg_success(); if(B_Read_Error) { eMBPoll(); DelayNms(100); }else { break; } } } uint8_t Check_WriteReg_Sucess_Addr(uint8_t addr,uint8_t readlen, uint16_t value) { B_Read_Error = 1; Uart_Read_HLW8110_Reg(addr,readlen); DelayNms(10); uint16_t data = 0; if (u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length)) { data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); if(data != value) { B_Read_Error = 0; } } return B_Read_Error; } void Check_WriteReg_Success(void) { Uart_Read_HLW8110_Reg(REG_SYSCON_ADDR,2); DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_Check_SysconReg_Data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); // printf("写入的SysconReg寄存器:%lx\n " ,U16_Check_SysconReg_Data); if(U16_Check_SysconReg_Data == 0x0a04) { }else { B_Read_Error = 1; } } else { // printf("SysconReg寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_EMUCON_ADDR,2); DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_Check_EmuconReg_Data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); // printf("写入的EmuconReg寄存器:%lx\n " ,U16_Check_EmuconReg_Data); if(U16_Check_EmuconReg_Data == 0x0001) { }else { B_Read_Error = 1; } } else { // printf("EmuconReg寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_EMUCON2_ADDR,2); DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_Check_Emucon2Reg_Data = (u8_RxBuf[0]<<8) + (u8_RxBuf[1]); // printf("写入的Emucon2Reg寄存器寄存器:%lx\n " ,U16_Check_Emucon2Reg_Data); if(U16_Check_Emucon2Reg_Data == 0x0065) { }else { B_Read_Error = 1; } } else { // printf("Emucon2Reg寄存器读取出错\r\n"); B_Read_Error = 1; } } void Read_HLW8110_IA(void) { float a; board_t *board = get_board(); Uart_Read_HLW8110_Reg(REG_RMSIA_ADDR,3); //DelayNms(10); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U32_RMSIA_RegData = (unsigned long)(u8_RxBuf[0]<<16) + (unsigned long)(u8_RxBuf[1]<<8) + (unsigned long)(u8_RxBuf[2]); // printf("A通道电流寄存器:%lx\n " ,U32_RMSIA_RegData); } else { // printf("A通道电流寄存器读取出错\r\n"); B_Read_Error = 1; } //A通道电流PGA = 16,电压通道PGA = 1;电流采样电阻1mR,电压采样电阻1M //计算公式,U16_AC_I = (U32_RMSIA_RegData * U16_RMSIAC_RegData)/(电流系数* 2^23) if ((U32_RMSIA_RegData & 0x800000) == 0x800000) { F_AC_I = 0; } else { a = (float)U32_RMSIA_RegData; a = a * U16_RMSIAC_RegData; a = a/0x800000; //电流计算出来的浮点数单位是mA,比如5003.12 //a = a/1; // 1 = 电流系数 #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->i_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->i_k[1]/10000.0); }else { a /= ((float)board->i_k[0]/10000.0); } #endif a = a/1000; //a= 5003ma,a/1000 = 5.003A,单位转换成A a = a * D_CAL_A_I; //D_CAL_A_I是校正系数,默认是1 F_AC_I = a; } } void Read_HLW8110_U(void) { float a; board_t *board = get_board(); Uart_Read_HLW8110_Reg(REG_RMSU_ADDR,3); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U32_RMSU_RegData = (unsigned long)(u8_RxBuf[0]<<16) + (unsigned long)(u8_RxBuf[1]<<8) + (unsigned long)(u8_RxBuf[2]); // printf("电压通道寄存器:%lx\n " ,U32_RMSU_RegData); } else { // printf("电压通道寄存器读取出错\r\n"); B_Read_Error = 1; } //电压 //计算:U16_AC_V = (U32_RMSU_RegData * U16_RMSUC_RegData)/2^23 if ((U32_RMSU_RegData &0x800000) == 0x800000) { F_AC_V = 0; } else { a = (float)U32_RMSU_RegData; a = a*U16_RMSUC_RegData; a = a/0x400000; //a = a/0.31163; // 1 = 电压系数 // a= a * 3.189; #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->v_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->v_k[1]/10000.0); }else { a /= ((float)board->v_k[0]/10000.0); } #endif a = a/100; //计算出a = 22083.12mV,a/100表示220.8312V,电压转换成V a = a*D_CAL_U; //D_CAL_U是校正系数,默认是1, F_AC_V = a; } } void Read_HLW8110_PA(void) { float a; float b; board_t *board = get_board(); Uart_Read_HLW8110_Reg(REG_POWER_PA_ADDR,4); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U32_POWERPA_RegData = (unsigned long)(u8_RxBuf[0]<<24) + (unsigned long)(u8_RxBuf[1]<<16) + (unsigned long)(u8_RxBuf[2]<<8) + (unsigned long)(u8_RxBuf[3]); // printf("A通道功率寄存器:%lx\n " ,U32_POWERPA_RegData); } else { // printf("A通道功率寄存器读取出错\r\n"); B_Read_Error = 1; } if (U32_POWERPA_RegData > 0x80000000) { b = ~U32_POWERPA_RegData; a = (float)b; } else a = (float)U32_POWERPA_RegData; //功率需要分正功和负功 //计算,U16_AC_P = (U32_POWERPA_RegData * U16_PowerPAC_RegData)/(2^31*电压系数*电流系数) //单位为W,比如算出来5000.123,表示5000.123W a = a*U16_PowerPAC_RegData; a = a/0x80000000; //a = a/1; // 1 = 电流系数 #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->i_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->i_k[1]/10000.0); }else { a /= ((float)board->i_k[0]/10000.0); } #endif // a = a/0.31163; //a = a * 3.189; //a = a/1; // 1 = 电压系数 #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->v_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->v_k[1]/10000.0); }else { a /= ((float)board->v_k[0]/10000.0); } #endif a = a * D_CAL_A_P; //D_CAL_A_P是校正系数,默认是1 F_AC_P = a; //单位为W,比如算出来5000.123,表示5000.123W } /*========================================================================================================= * Function : void Read_HLW8110_PSA(void) * Describe : 读取A通道功率 * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ void Read_HLW8110_PSA(void) { float a; float b; board_t *board = get_board(); Uart_Read_HLW8110_Reg(REG_POWER_PAS_ADDR,4); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U32_POWERPA_RegData = (unsigned long)(u8_RxBuf[0]<<24) + (unsigned long)(u8_RxBuf[1]<<16) + (unsigned long)(u8_RxBuf[2]<<8) + (unsigned long)(u8_RxBuf[3]); // printf("A通道功率寄存器:%lx\n " ,U32_POWERPA_RegData); } else { // printf("A通道功率寄存器读取出错\r\n"); B_Read_Error = 1; } if (U32_POWERPA_RegData > 0x80000000) { b = ~U32_POWERPA_RegData; a = (float)b; } else a = (float)U32_POWERPA_RegData; //功率需要分正功和负功 //计算,U16_AC_P = (U32_POWERPA_RegData * U16_PowerPAC_RegData)/(2^31*电压系数*电流系数) //单位为W,比如算出来5000.123,表示5000.123W a = a*U16_PowerPAC_RegData; a = a/0x80000000; //a = a/1; // 1 = 电流系数 //a = a * 3.189; #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->i_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->i_k[1]/10000.0); }else { a /= ((float)board->i_k[0]/10000.0); } #endif //a = a/1; // 1 = 电压系数 //a = a/0.31163; #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->v_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->v_k[1]/10000.0); }else { a /= ((float)board->v_k[0]/10000.0); } #endif a = a * D_CAL_A_P; //D_CAL_A_P是校正系数,默认是1 F_AC_PS = a; //单位为W,比如算出来5000.123,表示5000.123W } void Read_HLW8110_EA(void) { float a; board_t *board = get_board(); Uart_Read_HLW8110_Reg(REG_ENERGY_PA_ADDR,3); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U32_ENERGY_PA_RegData = (unsigned long)(u8_RxBuf[0]<<16) + (unsigned long)(u8_RxBuf[1]<<8) + (unsigned long)(u8_RxBuf[2]); // printf("A通道有功电量寄存器:%lx\n " ,U32_ENERGY_PA_RegData); } else { // printf("A通道有功电量寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_HFCONST_ADDR,2); DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { U16_HFConst_RegData = (unsigned int)(u8_RxBuf[0]<<8) + (unsigned int)(u8_RxBuf[1]); // printf("HFCONST常数 = :%d\n " ,U16_HFConst_RegData); } else { // printf("HFCONST常数寄存器读取出错\r\n"); B_Read_Error = 1; } //电量计算,电量 = (U32_ENERGY_PA_RegData * U16_EnergyAC_RegData * HFCONST) /(K1*K2 * 2^29 * 4096) //HFCONST:默认值是0x1000, HFCONST/(2^29 * 4096) = 0x20000000 a = (float)U32_ENERGY_PA_RegData; a = a*U16_EnergyAC_RegData; a = a/0x20000000; //电量单位是0.001KWH,比如算出来是2.002,表示2.002KWH //a = a/1; // 1 = 电流系数 #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->i_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->i_k[1]/10000.0); }else { a /= ((float)board->i_k[0]/10000.0); } #endif //a= a * 3.189; //a = a/1; // 1 = 电压系数 //a = a/0.31163; #if (AC_3_3 || AC_3_4 || AC_3_3_MON) a /= ((float)board->v_k[voltage_flag]/10000.0); #else if(voltage_flag == 1) { a /= ((float)board->v_k[1]/10000.0); }else { a /= ((float)board->v_k[0]/10000.0); } #endif a = a * D_CAL_A_E; //D_CAL_A_E是校正系数,默认是1 F_AC_E = a; F_AC_BACKUP_E = F_AC_E; } void Read_HLW8110_LineFreq(void) { float a; unsigned long b; Uart_Read_HLW8110_Reg(REG_UFREQ_ADDR,2); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { b = (unsigned long)(u8_RxBuf[0]<<8) + (unsigned long)(u8_RxBuf[1]); // printf("A通道线性频率寄存器:%ld\n " ,b); } else { // printf("A通道线性频率寄存器读取出错\r\n"); B_Read_Error = 1; } if(b!=0) { a = (float)b; a = 3579545/(8*a); F_AC_LINE_Freq = a; }else { F_AC_LINE_Freq = 0; } } void Read_HLW8110_PF(void) { float a; unsigned long b; //测量A通道的功率因素,需要发送EA+5A命令 //测量B通道的功率因素,需要发送EA+A5命令 Uart_Read_HLW8110_Reg(REG_PF_ADDR,3); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { b = (unsigned long)(u8_RxBuf[0]<<16) + (unsigned long)(u8_RxBuf[1]<<8) + (unsigned long)(u8_RxBuf[2]); // printf("A通道功率因素寄存器:%ld\n " ,b); } else { // printf("读取A通道功率因素寄存器出错\r\n"); B_Read_Error = 1; } if (b>0x800000) //为负,容性负载 { a = (float)(0xffffff-b + 1)/0x7fffff; } else { a = (float)b/0x7fffff; } if (F_AC_P < 1) // 小于0.3W,空载或小功率,PF不准 a = 0; //功率因素*100,最大为100,最小负100 F_AC_PF = a; } void Read_HLW8110_Angle(void) { float a; unsigned long b; Uart_Read_HLW8110_Reg(REG_ANGLE_ADDR,2); for(uint8_t i = 0;i < 5;i++) { if(B_Rx_Finish == TRUE) { break; } eMBPoll(); DelayNms(2); } //DelayNms(10); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { b =(unsigned long)(u8_RxBuf[0]<<8) + (unsigned long)(u8_RxBuf[1]); // printf("A通道线相角寄存器:%ld\n " ,b); } else { // printf("A通道线相角寄存器出错\r\n"); B_Read_Error = 1; } if ( F_AC_PF < 55) //线性频率50HZ { a = b; a = a * 0.0805; F_Angle = a; } else { //线性频率60HZ a = b; a = a * 0.0965; F_Angle = a; } if (F_AC_P < 0.5) //功率小于0.5时,说明没有负载,相角为0 { F_Angle = 0; } if (F_Angle < 90) { a = F_Angle; // printf("电流超前电压:%f\n " ,a); } else if (F_Angle < 180) { a = 180-F_Angle; // printf("电流滞后电压:%f\n " ,a); } else if (F_Angle < 360) { a = 360 - F_Angle; // printf("电流滞后电压:%f\n " ,a); } else { a = F_Angle -360; // printf("电流超前电压:%f\n " ,a); } } void Calculate_HLW8110_MeterData(void) { //Check_WriteReg_Success(); uint8_t count = 4; B_Read_Error = 0; do{ B_Read_Error = 0; Read_HLW8110_IA(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_U(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_PA(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_EA(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_LineFreq(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_Angle(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_PF(); }while((B_Read_Error) && (count--)); count = 4; do{ B_Read_Error = 0; Read_HLW8110_PSA(); }while((B_Read_Error) && (count--)); } #endif