/*========================================================================================================= * 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 "TM52F1386_bsp.h" #include "sTimeout.h" #include "iap.h" #include "uart2.h" #define HIGH 1 #define LOW 0 //8112A通道或8110通道校正系数 #define D_CAL_U 1000/1000 //电压校正系数 #define D_CAL_A_I 1000/1000 //A通道电流校正系数 #define D_CAL_A_P 1000/1000 //A通道功率校正系数 #define D_CAL_A_E 1000/1000 //A通道电能校正系数 //8112 B通道校正系数 #define D_CAL_B_P 1000/1000 //B通道功率校正系数 #define D_CAL_B_I 1000/1000 //B通道电流校正系数 #define D_CAL_B_E 1000/1000 //B通道电能校正系数 unsigned char HLW8110Msg = 0; //程序状态机 hlw8110_power_t hlw8110_power_data; long int SystemTimer; unsigned char power_data[50]; /*---------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------*/ union IntData { unsigned int inte; unsigned char byte[2]; }; union LongData { unsigned long word_; unsigned int inte_[2]; unsigned char byte_[4]; }; /*---------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------*/ unsigned char u8_TxBuf[10] = {0xA5,0x70}; unsigned char u8_RxBuf[10]; unsigned char u8_TX_Length; unsigned char u8_RX_Length; unsigned char u8_RX_Index = 0; //unsigned char B_ReadReg_Time_EN; // 串口读取寄存器数据,时间计数器标志位,1--开启计数,0--关闭计数 //unsigned char B_Tx_Finish; unsigned char B_Rx_Finish; unsigned char B_Rx_Data_ING; // 接收数据标志位 , < 1:接收数据中,0:未接收到数据 > unsigned char B_Read_Error; // UART读取出据校验和出错,< 1:数据读错,0:数据读取正确 > //unsigned char u8_ReadReg_Index; //unsigned char u8_ReadReg_Time; // 串口读取寄存器数据的时间 /*---------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------*/ 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[3]; // A通道电流转换系数 unsigned int U16_RMSIBC_RegData[3]; // B通道电流转换系数 unsigned int U16_RMSUC_RegData[3]; // 电压通道转换系数 unsigned int U16_PowerPAC_RegData[3]; // A通道功率转换系数 unsigned int U16_PowerPBC_RegData[3]; // B通道功率转换系数 unsigned int U16_PowerSC_RegData[3]; // 视在功率转换系数,如果选择A通道,则是A通道视在功率转换系数。A和B通道只能二者选其一 unsigned int U16_EnergyAC_RegData[3]; // A通道有功电能(量)转换系数 unsigned int U16_EnergyBC_RegData[3]; // A通道有功电能(量)转换系数 unsigned int U16_CheckSUM_RegData[3]; // 转换系数的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_E; // A通道有功电能(量) float F_AC_BACKUP_E; // A通道电量备份 float F_AC_PF; // 功率因素,A通道和B通道只能选其一 float F_Angle; // 相角,A通道和B通道只能选其一 /*---------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------*/ /*========================================================================================================= * Function : void Clear_RxBuf(void) * Describe : 在准备接收串口数据前,清空接收缓存器的数据 * Input : none * Output : none * Return : none * Record : 2019/04/03 =========================================================================================================*/ 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; } /*========================================================================================================= * Function : unsigned char HLW8110_checkSum_Write(unsigned char u8_Reg_length) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 =========================================================================================================*/ 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; } /*========================================================================================================= * Function : unsigned char HLW8110_checkSum_Read(void) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ 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; } /*========================================================================================================= * Function : void Uart_HLW8110_WriteREG_EN(void) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ 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); } /*========================================================================================================= * Function : void Uart_HLW8110_WriteREG_DIS(void) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ 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); } /*========================================================================================================= * Function : void Uart_HLW8110_Set_Channel_A(void) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ 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); } /*========================================================================================================= * Function : void Uart_Read_HLW8110_Reg(unsigned char ADDR_Reg,unsigned char u8_reg_length) * Describe : * Input : * Output : * Return : * Record : 2019/04/04 ==========================================================================================================*/ 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(); //清空接收缓冲区 Start_Send_UartData(u8_TX_Length); } /*========================================================================================================= * Function : void Uart_Write_HLW8110_Reg(unsigned char ADDR_Reg,unsigned char u8_reg_length,unsigned long u32_data) * Describe : 写寄存器命令,u8_reg_length:写入的寄存器数据字节长度 * Input : * Output : * Return : * Record : 2019/04/03 ==========================================================================================================*/ 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); } /*========================================================================================================= * Function : void Uart_HLW8110_Reset(void) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ 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); } /*========================================================================================================= * Function : void Judge_CheckSum_HLW8110_Calfactor(void) * Describe : 验证地址0x70-0x77地址的系数和 * Input : none * Output : none * Return : none * Record : 2019/03/18 ==========================================================================================================*/ unsigned char Judge_CheckSum_HLW8110_Calfactor(unsigned char nun) { 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); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_RMSIAC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; //printf("A通道电流转换系数:%x\n " ,U16_RMSIAC_RegData); } else if(nun == 2) //第二路 { U16_RMSIAC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; //printf("A通道电流转换系数:%x\n " ,U16_RMSIAC_RegData); } else if(nun == 3) //第三路 { U16_RMSIAC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; //printf("A通道电流转换系数:%x\n " ,U16_RMSIAC_RegData); } } Uart_Read_HLW8110_Reg(REG_RMS_IBC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_RMSIBC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; //printf("B通道电流转换系数:%x\n " ,U16_RMSIBC_RegData); } else if(nun == 2) //第二路 { U16_RMSIBC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; //printf("B通道电流转换系数:%x\n " ,U16_RMSIBC_RegData); } else if(nun == 3) //第三路 { U16_RMSIBC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ; //printf("B通道电流转换系数:%x\n " ,U16_RMSIBC_RegData); } } Uart_Read_HLW8110_Reg(REG_RMS_UC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_RMSUC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("电压通道转换系数:%x\n " ,U16_RMSUC_RegData); } else if(nun == 2) //第二路 { U16_RMSUC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("电压通道转换系数:%x\n " ,U16_RMSUC_RegData); } else if(nun == 3) //第三路 { U16_RMSUC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("电压通道转换系数:%x\n " ,U16_RMSUC_RegData); } } Uart_Read_HLW8110_Reg(REG_POWER_PAC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_PowerPAC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("A通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } else if(nun == 2) //第二路 { U16_PowerPAC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("A通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } else if(nun == 3) //第三路 { U16_PowerPAC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("A通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } } Uart_Read_HLW8110_Reg(REG_POWER_PBC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_PowerPBC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("B通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } else if(nun == 2) //第二路 { U16_PowerPBC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("B通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } else if(nun == 3) //第三路 { U16_PowerPBC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("B通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); } } Uart_Read_HLW8110_Reg(REG_POWER_SC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_PowerSC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("视在功率转换系数:%x\n " ,U16_PowerSC_RegData); } else if(nun == 2) //第二路 { U16_PowerSC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("视在功率转换系数:%x\n " ,U16_PowerSC_RegData); } else if(nun == 3) //第三路 { U16_PowerSC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("视在功率转换系数:%x\n " ,U16_PowerSC_RegData); } } Uart_Read_HLW8110_Reg(REG_ENERGY_AC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_EnergyAC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("A通道电量转换系数:%x\n " ,U16_EnergyAC_RegData); } else if(nun == 2) //第二路 { U16_EnergyAC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("A通道电量转换系数:%x\n " ,U16_EnergyAC_RegData); } else if(nun == 3) //第三路 { U16_EnergyAC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("A通道电量转换系数:%x\n " ,U16_EnergyAC_RegData); } } Uart_Read_HLW8110_Reg(REG_ENERGY_BC_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_EnergyBC_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("B通道电量转换系数:%x\n " ,U16_EnergyBC_RegData); } else if(nun == 2) //第二路 { U16_EnergyBC_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("B通道电量转换系数:%x\n " ,U16_EnergyBC_RegData); } else if(nun == 3) //第三路 { U16_EnergyBC_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("B通道电量转换系数:%x\n " ,U16_EnergyBC_RegData); } } Uart_Read_HLW8110_Reg(REG_CHECKSUM_ADDR,2); bsp_delay_ms(30); if ( u8_RxBuf[u8_RX_Length-1] == HLW8110_checkSum_Read(u8_RX_Length) ) { if(nun == 1) //第一路 { U16_CheckSUM_RegData[0] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("系数校验和:%x\n " ,U16_CheckSUM_RegData); } else if(nun == 2) //第二路 { U16_CheckSUM_RegData[1] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("系数校验和:%x\n " ,U16_CheckSUM_RegData); } else if(nun == 3) //第三路 { U16_CheckSUM_RegData[2] = (u8_RxBuf[0]<<8) + u8_RxBuf[1] ;//printf("系数校验和:%x\n " ,U16_CheckSUM_RegData); } } a = 0; if(nun == 1) { a = ~(0xffff+U16_RMSIAC_RegData[0] + U16_RMSIBC_RegData[0] + U16_RMSUC_RegData[0] + U16_PowerPAC_RegData[0] + U16_PowerPBC_RegData[0] + U16_PowerSC_RegData[0] + U16_EnergyAC_RegData[0] + U16_EnergyBC_RegData[0] ); U16_CheckSUM_Data = a & 0xffff; //printf("计算系数校验和:%x\n " ,U16_CheckSUM_Data); if ( U16_CheckSUM_Data == U16_CheckSUM_RegData[0]) { d = 1;//printf("校验和正确\r\n "); } else { d = 0; //printf("校验和出错\r\n "); } } else if(nun == 2) { a = ~(0xffff+U16_RMSIAC_RegData[1] + U16_RMSIBC_RegData[1] + U16_RMSUC_RegData[1] + U16_PowerPAC_RegData[1] + U16_PowerPBC_RegData[1] + U16_PowerSC_RegData[1] + U16_EnergyAC_RegData[1] + U16_EnergyBC_RegData[1] ); U16_CheckSUM_Data = a & 0xffff; //printf("计算系数校验和:%x\n " ,U16_CheckSUM_Data); if ( U16_CheckSUM_Data == U16_CheckSUM_RegData[1]) { d = 1;//printf("校验和正确\r\n "); } else { d = 0; //printf("校验和出错\r\n "); } } else if(nun == 3) { a = ~(0xffff+U16_RMSIAC_RegData[2] + U16_RMSIBC_RegData[2] + U16_RMSUC_RegData[2] + U16_PowerPAC_RegData[2] + U16_PowerPBC_RegData[2] + U16_PowerSC_RegData[2] + U16_EnergyAC_RegData[2] + U16_EnergyBC_RegData[2] ); U16_CheckSUM_Data = a & 0xffff; //printf("计算系数校验和:%x\n " ,U16_CheckSUM_Data); if ( U16_CheckSUM_Data == U16_CheckSUM_RegData[2]) { d = 1;//printf("校验和正确\r\n "); } else { d = 0; //printf("校验和出错\r\n "); } } return d; } /*========================================================================================================= * Function : void Init_HLW8110(void) * Describe : * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ void Init_HLW8110(unsigned char nun) { Uart_HLW8110_WriteREG_EN(); bsp_delay_ms(30); //电流通道A设置命令,指定当前用于计算视在功率、功率因数、相角、瞬时有功功率、瞬时视在功率和有功功率过载的信号指示 的通道为通道A Uart_HLW8110_Set_Channel_A(); bsp_delay_ms(30); Uart_Write_HLW8110_Reg(REG_SYSCON_ADDR,2,0x0a04); //开启A通道,关闭B通道,电压通道PGA = 1,电流通道PGA = 16 bsp_delay_ms(30); Uart_Write_HLW8110_Reg(REG_EMUCON_ADDR,2,0x0001); //1,使能PFA 脉冲输出和有功电能寄存器累加; // Uart_Write_HLW8110_Reg(REG_EMUCON_ADDR,2,0x0018); //正向和负向过零点均发生变化,ZXD0 = 1,ZXD1 = 1 Uart_Write_HLW8110_Reg(REG_EMUCON2_ADDR,2,0x0465); //0x0001是EMUCON2的默认值,waveEn = 1,zxEn = 1,A通道电量寄存器,读后不清0,EPA_CB = 1;打开功率因素检测 bsp_delay_ms(30); Uart_HLW8110_WriteREG_DIS(); bsp_delay_ms(3); //读取地址是0x6F至0x77的寄存器,验证系数是否正确 Judge_CheckSum_HLW8110_Calfactor(nun); } /*========================================================================================================= * Function : void Check_WriteReg_Success(void) * Describe : 检验写入的REG是否正确写入 * Input : none * Output : none * Return : none * Record : 2020/04/02 ==========================================================================================================*/ void Check_WriteReg_Success(void) { Uart_Read_HLW8110_Reg(REG_SYSCON_ADDR,2); bsp_delay_ms(30); 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); } else { //printf("SysconReg寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_EMUCON_ADDR,2); bsp_delay_ms(30); 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); } else { //printf("EmuconReg寄存器读取出错\r\n"); B_Read_Error = 1; } Uart_Read_HLW8110_Reg(REG_EMUCON2_ADDR,2); bsp_delay_ms(30); 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); } else { //printf("Emucon2Reg寄存器读取出错\r\n"); B_Read_Error = 1; } } /*========================================================================================================= * Function : void Read_HLW8112_IA(void) * Describe : 读取A通道电流 * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ void Read_HLW8110_IA(unsigned char nun) { float a; Uart_Read_HLW8110_Reg(REG_RMSIA_ADDR,3); bsp_delay_ms(30); //delay_ms(3); 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) { if(nun == 1) { hlw8110_power_data.F_AC_I[0] = 0; } else if(nun == 2) { hlw8110_power_data.F_AC_I[1] = 0; } else if(nun == 3) { hlw8110_power_data.F_AC_I[2] = 0; } } else { a = (float)U32_RMSIA_RegData; if(nun == 1) { a = a * U16_RMSIAC_RegData[0]; } else if(nun == 2) { a = a * U16_RMSIAC_RegData[1]; } else if(nun == 3) { a = a * U16_RMSIAC_RegData[2]; } //a = a * U16_RMSIAC_RegData; a = a/0x800000; //电流计算出来的浮点数单位是mA,比如5003.12 a = a/1; // 1 = 电流系数 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; if(nun == 1) { hlw8110_power_data.F_AC_I[0] = a; } else if(nun == 2) { hlw8110_power_data.F_AC_I[1] = a; } else if(nun == 3) { hlw8110_power_data.F_AC_I[2] = a; } } } /*========================================================================================================= * Function : void Read_HLW8110_U(void) * Describe : 读取电压 * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ void Read_HLW8110_U(unsigned char nun) { float a; Uart_Read_HLW8110_Reg(REG_RMSU_ADDR,3); bsp_delay_ms(30); //delay_ms(3); 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; if(nun == 1) { hlw8110_power_data.F_AC_V[0] = 0; } else if(nun == 2) { hlw8110_power_data.F_AC_V[1] = 0; } else if(nun == 3) { hlw8110_power_data.F_AC_V[2] = 0; } } else { a = (float)U32_RMSU_RegData; if(nun == 1) { a = a * U16_RMSUC_RegData[0]; } else if(nun == 2) { a = a * U16_RMSUC_RegData[1]; } else if(nun == 3) { a = a * U16_RMSUC_RegData[2]; } // a = a*U16_RMSUC_RegData; a = a/0x400000; a = a/1; // 1 = 电压系数 a = a/100; //计算出a = 22083.12mV,a/100表示220.8312V,电压转换成V a = a*D_CAL_U; //D_CAL_U是校正系数,默认是1, // F_AC_V = a; if(nun == 1) { hlw8110_power_data.F_AC_V[0] = a; } else if(nun == 2) { hlw8110_power_data.F_AC_V[1] = a; } else if(nun == 3) { hlw8110_power_data.F_AC_V[2] = a; } } } /*========================================================================================================= * Function : void Read_HLW8110_PA(void) * Describe : 读取A通道功率 * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ void Read_HLW8110_PA(unsigned char nun) { float a; float b; Uart_Read_HLW8110_Reg(REG_POWER_PA_ADDR,4); bsp_delay_ms(30); //delay_ms(3); 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 (B_Read_Error == 1) { B_Read_Error = 0; Uart_Read_HLW8110_Reg(REG_POWER_PA_ADDR,4); bsp_delay_ms(30); //delay_ms(3); 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 if(nun == 1) { a = a * U16_PowerPAC_RegData[0]; } else if(nun == 2) { a = a * U16_PowerPAC_RegData[1]; } else if(nun == 3) { a = a * U16_PowerPAC_RegData[2]; } //a = a*U16_PowerPAC_RegData; a = a/0x80000000; a = a/1; // 1 = 电流系数 a = a/1; // 1 = 电压系数 a = a * D_CAL_A_P; //D_CAL_A_P是校正系数,默认是1 //F_AC_P = a; //单位为W,比如算出来5000.123,表示5000.123W if(nun == 1) { hlw8110_power_data.F_AC_P[0] = a; } else if(nun == 2) { hlw8110_power_data.F_AC_P[1] = a; } else if(nun == 3) { hlw8110_power_data.F_AC_P[2] = a; } } /*========================================================================================================= * Function : void void Read_HLW8112_EA(void) * Describe : 读取A通道有功电量 * Input : none * Output : none * Return : none * Record : 2019/04/03 ==========================================================================================================*/ void Read_HLW8110_EA(unsigned char nun) { float a; Uart_Read_HLW8110_Reg(REG_ENERGY_PA_ADDR,3); bsp_delay_ms(30); //delay_ms(3); 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); bsp_delay_ms(30); 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; if(nun == 1) { a = a * U16_EnergyAC_RegData[0]; } else if(nun == 2) { a = a * U16_EnergyAC_RegData[1]; } else if(nun == 3) { a = a * U16_EnergyAC_RegData[2]; } //a = a*U16_EnergyAC_RegData; a = a/0x20000000; //电量单位是0.001KWH,比如算出来是2.002,表示2.002KWH a = a/1; // 1 = 电流系数 a = a/1; // 1 = 电压系数 a = a * D_CAL_A_E; //D_CAL_A_E是校正系数,默认是1 // F_AC_E = a; //F_AC_BACKUP_E = F_AC_E; if(nun == 1) { hlw8110_power_data.F_AC_E[0] = a; } else if(nun == 2) { hlw8110_power_data.F_AC_E[1] = a; } else if(nun == 3) { hlw8110_power_data.F_AC_E[2] = a; } } /*========================================================================================================= * Function : void Read_HLW8110_PF(void) * Describe : 读取功率因素 * Input : none * Output : none * Return : none * Record : 2019/03/18 ==========================================================================================================*/ void Read_HLW8110_PF(void) { float a; unsigned long b; //测量A通道的功率因素,需要发送EA+5A命令 //测量B通道的功率因素,需要发送EA+A5命令 Uart_Read_HLW8110_Reg(REG_PF_ADDR,3); bsp_delay_ms(30); 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 < 0.3) // 小于0.3W,空载或小功率,PF不准 a = 0; //功率因素*100,最大为100,最小负100 F_AC_PF = a; } /*========================================================================================================= * Function : void Calculate_HLW8110_MeterData(void); * Describe : * Input : none * Output : none * Return : none * Record : 2018/05/10 ==========================================================================================================*/ void Calculate_HLW8110_MeterData(unsigned char nun) { Check_WriteReg_Success(); Read_HLW8110_IA(nun); Read_HLW8110_U(nun); Read_HLW8110_PA(nun); Read_HLW8110_EA(nun); // Read_HLW8110_LineFreq(); // Read_HLW8110_Angle(); // Read_HLW8110_PF(); /* printf("\r\n"); printf("\r\n"); printf("交流测量,uart通讯方式\r\n"); printf("A通道电流转换系数:%x\n " ,U16_RMSIAC_RegData); printf("B通道电流转换系数:%x\n " ,U16_RMSIBC_RegData); printf("电压通道转换系数:%x\n " ,U16_RMSUC_RegData); printf("A通道功率转换系数:%x\n " ,U16_PowerPAC_RegData); printf("B通道功率转换系数:%x\n " ,U16_PowerPBC_RegData); printf("视在功率转换系数:%x\n " ,U16_PowerSC_RegData); printf("A通道电量转换系数:%x\n " ,U16_EnergyAC_RegData); printf("B通道电量转换系数:%x\n " ,U16_EnergyBC_RegData); printf("转换系数校验和:%x\n " ,U16_CheckSUM_RegData); printf("转换系数计算出的校验和:%x\n " ,U16_CheckSUM_Data); printf("\r\n");//插入换行 printf("A通道电流寄存器:%x\n " ,U32_RMSIA_RegData); printf("电压寄存器:%x\n " ,U32_RMSU_RegData); printf("A通道功率寄存器:%x\n " ,U32_POWERPA_RegData); printf("A通道电量寄存器:%x\n " ,U32_ENERGY_PA_RegData); printf("\r\n");//插入换行 printf("F_AC_I = %f A \n " ,F_AC_I); //电流 printf("F_AC_V = %f V \n " ,F_AC_V); //电压 printf("F_AC_P = %f W \n " ,F_AC_P); //功率 printf("F_AC_BACKUP_E = %f KWH \n " ,F_AC_BACKUP_E); //电量 printf("F_AC_LINE_Freq = %f Hz \n " ,F_AC_LINE_Freq); //市电线性频率 printf("F_Angle = %f\n " ,F_Angle); //L和N的相角 printf("F_AC_PF = %f\n " ,F_AC_PF); //功率因素 printf("\r\n");//插入换行 printf("\r\n");//插入换行 printf("----------------------------------------------\r\n"); printf("----------------------------------------------\r\n"); */ } void Read_Power_Data_handle(void) { int i = 0; switch (HLW8110Msg) { case HLW8110_int: if (sTimeout(&SystemTimer, 100)) // 等待1s初始化8110 { open_first_passageway(); Init_HLW8110(1); open_second_passageway(); Init_HLW8110(2); open_third_passageway(); Init_HLW8110(3); open_first_passageway(); HLW8110Msg++; } break; case HLW8110_1: if (sTimeout(&SystemTimer, 500)) // 等待5s读取第一路数据 { Calculate_HLW8110_MeterData(1); HLW8110Msg++; } break; case HLW8110_2: if (sTimeout(&SystemTimer, 10)) // 等待100ms读取第二路数据 { open_second_passageway(); // 打开第二通道 Calculate_HLW8110_MeterData(2); HLW8110Msg++; } break; case HLW8110_3: if (sTimeout(&SystemTimer, 10)) // 等待100ms读取第三路数据 { open_third_passageway(); // 打开第三通道 Calculate_HLW8110_MeterData(3); HLW8110Msg++; } break; case HLW8110_IDEL: if (sTimeout(&SystemTimer, 2)) // { open_first_passageway(); // 打开第一通道 //增加发送数据给zigbee //增加电量数据保存 for(i = 0; i < 3; i++) { power_data[i*16] = ((long int)hlw8110_power_data.F_AC_V[i] >>24) & 0xFF; power_data[i*16+1] = ((long int)hlw8110_power_data.F_AC_V[i] >>16) & 0xFF; power_data[i*16+2] = ((long int)hlw8110_power_data.F_AC_V[i] >>8) & 0xFF; power_data[i*16+3] = (long int)hlw8110_power_data.F_AC_V[i] & 0xFF; power_data[i*16+4] = ((long int)hlw8110_power_data.F_AC_I[i] >>24) & 0xFF; power_data[i*16+5] = ((long int)hlw8110_power_data.F_AC_I[i] >>16) & 0xFF; power_data[i*16+6] = ((long int)hlw8110_power_data.F_AC_I[i] >>8) & 0xFF; power_data[i*16+7] = (long int)hlw8110_power_data.F_AC_I[i] & 0xFF; power_data[i*16+8] = ((long int)hlw8110_power_data.F_AC_P[i] >>24) & 0xFF; power_data[i*16+9] = ((long int)hlw8110_power_data.F_AC_P[i] >>16) & 0xFF; power_data[i*16+10] = ((long int)hlw8110_power_data.F_AC_P[i] >>8) & 0xFF; power_data[i*16+11] = (long int)hlw8110_power_data.F_AC_P[i] & 0xFF; power_data[i*16+12] = ((long int)hlw8110_power_data.F_AC_E[i] >>24) & 0xFF; power_data[i*16+13] = ((long int)hlw8110_power_data.F_AC_E[i] >>16) & 0xFF; power_data[i*16+14] = ((long int)hlw8110_power_data.F_AC_E[i] >>8) & 0xFF; power_data[i*16+15] = (long int)hlw8110_power_data.F_AC_E[i] & 0xFF; } user_write_INFO_byte(INFO6_ADDR, power_data, 50); HLW8110Msg = HLW8110_1; //返回读取第一路数据 } break; case HLW8110_ERR: HLW8110Msg++; break; default: HLW8110Msg = HLW8110_ERR; // 开机初始化 break; } }