HLW8112芯片软件实现代码(8)

📅 2026/7/13 0:01:17 👁️ 阅读次数 📝 编程学习
HLW8112芯片软件实现代码(8)

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

二、寄存器介绍

2. 详述

(1)Init_HLW8112函数

上一回继续结合官方例程讲解常用寄存器的细节。讲解了Init_HLW8112函数的第6、7段代码,本回继续讲解该函数后续内容。为了便于理解和回顾,再次贴出Init_HLW8112函数源码,在HARDWARE\HLW8112-SPI\HLW8112-SPI.c中,如下:

/*===================================================== * Function : void Init_HLW8112(void) * Describe : 初始化8112 * Input : none * Output : none * Return : none * Record : 2018/05/09 =====================================================*/ void Init_HLW8112(void) { unsigned char a; // SPI init delay_ms(100); //STM32 IO init RCC->APB2ENR |= 1 << 2; //使能PORTA时钟 RCC->APB2ENR |= 5 << 6; //使能PORTD时钟 GPIOA->CRL &= 0X000F00FF; //IO状态设置,设置PA7、PA6、PA5、PA3、PA2 GPIOA->CRL |= 0X33308300; //IO状态设置,PA7、PA6、PA5、PA2-输出、PA3-输入 //GPIOD->CRL &= 0XFFF00FFF; //IO状态设置,设置PD11、PD12 //GPIOD->CRL |= 0X00088000; //IO状态设置,PD11、PD12-输入 //STM32 IO init IO_HLW8112_EN = 1; delay_ms(10); IO_HLW8112_CS = HIGH; delay_us(2); delay_us(2); IO_HLW8112_SCLK = LOW; delay_us(2); IO_HLW8112_SDI = LOW; HLW8112_WriteREG_EN(); //打开写8112 Reg // ea + 5a 电流通道A设置命令,指定当前用于计算视在功率、功率因数、相角、 //瞬时有功功率、瞬时视在功率和有功功率过载的信号指示 的通道为通道A IO_HLW8112_CS = LOW; HLW8112_SPI_WriteByte(0xea); HLW8112_SPI_WriteByte(0x5a); IO_HLW8112_CS = HIGH; //写SYSCON REG, 关闭电流通道B,电压通道 PGA = 1,电流通道A PGA = 16; //三路通道满幅值(峰峰值800ma,有效值/1.414 = 565mV) IO_HLW8112_CS = LOW; HLW8112_SPI_WriteReg(REG_SYSCON_ADDR); //HLW8112_SPI_WriteByte(0x0a); //开启电流通道A,PGA = 16 ------高8bit HLW8112_SPI_WriteByte(0x0f); //开启电流通道A和电流通道B PGA = 16;需要在EMUCON中关闭比较器------高8bit HLW8112_SPI_WriteByte(0x04); //-------------低8bit IO_HLW8112_CS = HIGH; //写EMUCON REG, 使能A通道PF脉冲输出和有功能电能寄存器累加 IO_HLW8112_CS = LOW; HLW8112_SPI_WriteReg(REG_EMUCON_ADDR); HLW8112_SPI_WriteByte(0x11); //最高位一定设置成0001,关闭比较器,打开B通道 ,打开dcmode,和关闭高通 HLW8112_SPI_WriteByte(0x73); //打开A通道和B通道电量累计功能 IO_HLW8112_CS = HIGH; //写EMUCON2 REG, 3.4HZ数据输出,选择内部基准,打开过压、过流等功能 //3.4HZ(300ms) 6.8HZ(150ms) 13.65HZ(75ms) 27.3HZ(37.5ms) IO_HLW8112_CS = LOW; HLW8112_SPI_WriteReg(REG_EMUCON2_ADDR); HLW8112_SPI_WriteByte(0x0f); //电量寄存器读后不清 HLW8112_SPI_WriteByte(0xff); IO_HLW8112_CS = HIGH; //关闭所有中断 IO_HLW8112_CS = LOW; HLW8112_SPI_WriteReg(REG_IE_ADDR); HLW8112_SPI_WriteByte(0x00); HLW8112_SPI_WriteByte(0x00); IO_HLW8112_CS = HIGH; HLW8112_WriteREG_DIS(); //关闭写8112 Reg //验证 REG_SYSCON_ADDR和REG_EMUCON_ADDR是否有写入 U16_RMSIAC_RegData = Read_HLW8112_RegData(REG_SYSCON_ADDR, 2); U16_RMSIBC_RegData = Read_HLW8112_RegData(REG_EMUCON2_ADDR, 2); printf("测试寄存器\r\n"); printf("U16_RMSIAC_RegData = %x\n " ,U16_RMSIAC_RegData); printf("U16_RMSIBC_RegData = %x\n " ,U16_RMSIBC_RegData); printf("\r\n\r\n"); //读取RmsIAC、RmsIBC、RmsUC、PowerPAC、PowerPBC、PowerSC、EnergAc、EnergBc的值 U16_RMSIAC_RegData = Read_HLW8112_RegData(REG_RMS_IAC_ADDR,2); //0xcad1 U16_RMSIBC_RegData = Read_HLW8112_RegData(REG_RMS_IBC_ADDR,2); //0xcacf U16_RMSUC_RegData = Read_HLW8112_RegData(REG_RMS_UC_ADDR,2); //0xa4c3 U16_PowerPAC_RegData = Read_HLW8112_RegData(REG_POWER_PAC_ADDR,2); //0xab47 U16_PowerPBC_RegData = Read_HLW8112_RegData(REG_POWER_PBC_ADDR,2); //0xab49 U16_PowerSC_RegData = Read_HLW8112_RegData(REG_POWER_SC_ADDR,2); //0xab41 U16_EnergyAC_RegData = Read_HLW8112_RegData(REG_ENERGY_AC_ADDR,2); //0xe9cc U16_EnergyBC_RegData = Read_HLW8112_RegData(REG_ENERGY_BC_ADDR,2); //0xe9ce printf("系数寄存器\r\n"); printf("U16_RMSIAC_RegData = %x\n", U16_RMSIAC_RegData); printf("U16_RMSIBC_RegData = %x\n", U16_RMSIBC_RegData); printf("U16_RMSUC_RegData = %x\n" , U16_RMSUC_RegData); printf("U16_PowerPAC_RegData = %x\n", U16_PowerPAC_RegData); printf("U16_PowerPBC_RegData = %x\n", U16_PowerPBC_RegData); printf("U16_PowerSC_RegData = %x\n", U16_PowerSC_RegData); printf("U16_EnergyAC_RegData = %x\n", U16_EnergyAC_RegData); printf("U16_EnergyBC_RegData = %x\n", U16_EnergyBC_RegData); a = Judge_CheckSum_HLW8112_Calfactor(); if (a == 1) { printf("系数寄存器校验ok\r\n"); } else { printf("系数寄存器校验fail\r\n"); } }

8)测试写入值

代码片段如下:

//验证 REG_SYSCON_ADDR和REG_EMUCON_ADDR是否有写入 U16_RMSIAC_RegData = Read_HLW8112_RegData(REG_SYSCON_ADDR, 2); U16_RMSIBC_RegData = Read_HLW8112_RegData(REG_EMUCON2_ADDR, 2); printf("测试寄存器\r\n"); printf("U16_RMSIAC_RegData = %x\n " ,U16_RMSIAC_RegData); printf("U16_RMSIBC_RegData = %x\n " ,U16_RMSIBC_RegData); printf("\r\n\r\n");

Read_HLW8112_RegData函数也在stm32-codetest\HARDWARE\HLW8112-SPI\HLW8112-SPI.c中,代码如下:

/*===================================================== * Function : unsigned long Read_HLW8112_RegData(unsigned char ADDR_Reg,unsigned char u8_reg_length) * Describe : 读取寄存器值 * Input : ADDR_Reg,u8_Data_length * Output : u8_Buf[4],寄存器值 * Return : u1(True or False) * Record : 2018/05/09 =====================================================*/ unsigned long Read_HLW8112_RegData(unsigned char ADDR_Reg, unsigned char u8_reg_length) { unsigned char i; union LongData u32_t_data1; IO_HLW8112_CS = LOW; u32_t_data1.word = 0x00000000; //高位在前 HLW8112_SPI_ReadReg(ADDR_Reg); for (i = 0; i<u8_reg_length; i++ ) { u32_t_data1.byte[u8_reg_length-1-i] = HLW8112_SPI_ReadByte(); } IO_HLW8112_CS = HIGH; return u32_t_data1.word; }

HLW8112_SPI_ReadReg函数也在同文件中,代码如下:

/*===================================================== * Function : void HLW8112_SPI_WriteCmd(unsigned char u8_cmd) * Describe : * Input : none * Output : none * Return : none * Record : 2018/05/09 =====================================================*/ void HLW8112_SPI_ReadReg(unsigned char u8_RegAddr) { HLW8112_SPI_WriteByte(u8_RegAddr); }

HLW8112_SPI_ReadByte函数也在同文件中,代码如下:

/*===================================================== * Function : unsigned char HLW8112_SPI_ReadByte(void) * Describe : * Input : none * Output : none * Return : none * Record : 2018/05/09 =====================================================*/ unsigned char HLW8112_SPI_ReadByte(void) { unsigned char i; unsigned char u8_data; u8_data = 0x00; for (i = 0; i < 8; i++) { u8_data <<= 1; IO_HLW8112_SCLK = HIGH; delay_us(10); IO_HLW8112_SCLK = LOW; delay_us(10); if (IO_HLW8112_SDO == HIGH) u8_data |= 0x01; } return u8_data; }

HLW8112_SPI_ReadByte函数没什么好讲的,就是经典的SPI读字节时序。

那么Read_HLW8112_RegData函数的整体功能就是:先通过SPI写入要读取寄存取地址,然后读取寄存器的内容。

对于Init_HLW8112()中的这段测试代码来讲,功能就是通过SPI分别读取REG_SYSCON_ADDR(系统控制寄存器,00H)和REG_EMUCON2_ADDR(计量控制寄存器2)的值,验证一下之前写入的值是否已经正确设置。

UART模式下与读寄存器对应的函数是:hlw8112_read_data()。代码如下:

int hlw8112(UART_HandleTypeDef *huart, uint8_t reg_addr, uint8_t size, uint8_t *buf) { uint8_t rx_data[10] = {0xFF}; uint8_t frame[2] = {0xA5, 0x00}; if (!buf) return -1; frame[1] = reg_addr; HLW8112_SendByte(huart, frame[0]); HLW8112_SendByte(huart, frame[1]); HAL_UART_Receive(huart, &rx_data[0], size, 100); memcpy((void *)buf, (const void *)rx_data, size); return 0; }

9)读取RmsIAC、RmsIBC、RmsUC、PowerPAC、PowerPBC、PowerSC、EnergAc、EnergBc的值

代码片段如下:

//读取RmsIAC、RmsIBC、RmsUC、PowerPAC、PowerPBC、PowerSC、EnergAc、EnergBc的值 U16_RMSIAC_RegData = Read_HLW8112_RegData(REG_RMS_IAC_ADDR,2); //0xcad1 U16_RMSIBC_RegData = Read_HLW8112_RegData(REG_RMS_IBC_ADDR,2); //0xcacf U16_RMSUC_RegData = Read_HLW8112_RegData(REG_RMS_UC_ADDR,2); //0xa4c3 U16_PowerPAC_RegData = Read_HLW8112_RegData(REG_POWER_PAC_ADDR,2); //0xab47 U16_PowerPBC_RegData = Read_HLW8112_RegData(REG_POWER_PBC_ADDR,2); //0xab49 U16_PowerSC_RegData = Read_HLW8112_RegData(REG_POWER_SC_ADDR,2); //0xab41 U16_EnergyAC_RegData = Read_HLW8112_RegData(REG_ENERGY_AC_ADDR,2); //0xe9cc U16_EnergyBC_RegData = Read_HLW8112_RegData(REG_ENERGY_BC_ADDR,2); //0xe9ce printf("系数寄存器\r\n"); printf("U16_RMSIAC_RegData = %x\n", U16_RMSIAC_RegData); printf("U16_RMSIBC_RegData = %x\n", U16_RMSIBC_RegData); printf("U16_RMSUC_RegData = %x\n" , U16_RMSUC_RegData); printf("U16_PowerPAC_RegData = %x\n", U16_PowerPAC_RegData); printf("U16_PowerPBC_RegData = %x\n", U16_PowerPBC_RegData); printf("U16_PowerSC_RegData = %x\n", U16_PowerSC_RegData); printf("U16_EnergyAC_RegData = %x\n", U16_EnergyAC_RegData); printf("U16_EnergyBC_RegData = %x\n", U16_EnergyBC_RegData);

这段代码很好理解,依次获取RmsIAC、RmsIBC、RmsUC、PowerPAC、PowerPBC、PowerSC、EnergAc、EnergBc寄存器的内容。这些寄存器的具体意义,下一回详细讲解。