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

HLW8112芯片软件实现代码(4)
接前一篇文章HLW8112芯片软件实现代码3二、寄存器介绍2. 详述1Init_HLW8112函数上一回开始结合官方例程讲解常用寄存器的细节。讲解了Init_HLW8112函数的第1段代码本回继续讲解该函数后续内容。为了便于理解和回顾再次贴出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); } }2选择电流A通道代码片段如下// ea 5a 电流通道A设置命令指定当前用于计算视在功率、功率因数、相角、 //瞬时有功功率、瞬时视在功率和有功功率过载的信号指示 的通道为通道A IO_HLW8112_CS LOW; HLW8112_SPI_WriteByte(0xea); HLW8112_SPI_WriteByte(0x5a); IO_HLW8112_CS HIGH;0xEA和0x5A的作用如下对于UART模式也是一样的如下图所示同样SPI模式下只需要发送0xEA0xE5就可以了但UART模式下只发送这两个数据是不够的而是要有一帧完整的协议。UART模式下对应的代码为void hlw8112_select_channel_a(UART_HandleTypeDef *huart) { uint8_t data[1] {0x5A}; hlw8112_send_frame(huart, 0xEA, data, 1); HAL_Delay(1); }3设置系统控制寄存器代码片段如下//写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;REG_SYSCON_ADDR宏在HLW8110.h中定义如下#define REG_SYSCON_ADDR 0x00上边3行代码的意义是先选择寄存器0即系统控制寄存器SYSCON然后写入0x0F04。系统控制寄存器SYSCON的详情如下0x0F04展开为二进制就是0b0000111100000100对应到各个字段就是bit 15~120000。保留。bit 111。表示ADC电压通道U开启。bit 101。表示ADC电流通道B开启。bit 91。表示ADC电流通道A开启。bit 8~6100。电流通道B的PGA16。bit 5~3000。电压通道U的PGA1。bit 2~0100。电流通道A的PGA16。这里对比一下设置值0x0F04与复位值0x0A04的区别。其实就是bit10和bit8设置为0还是设置为1也就是电流通道B是否开启。UART模式下对应的代码为hlw8112_write_enable(Uart2Handle); hlw8112_write_16bit(Uart2Handle, HLW8112_REG_SYSCON, 0x0A04); hlw8112_write_protect(Uart2Handle);void hlw8112_write_16bit(UART_HandleTypeDef *huart, uint8_t reg_addr, uint16_t data) { uint8_t cmd; uint8_t tx_data[2]; cmd 0x80 | (reg_addr 0x7F); tx_data[0] (data 8) 0xFF; tx_data[1] data 0xFF; hlw8112_send_frame(huart, cmd, tx_data, 2); }void hlw112_write_protect(UART_HandleTypeDef *huart) { uint8_t data[1] {0xDC}; hlw8112_send_frame(huart, 0xEA, data, 1); //HAL_Delay(1); }这里顺带提一下0xEA和0xDC的作用如下对于UART模式也是一样的如下图所示写保护0xEA0xDC与写使能0xEA0xE5是一对命令。下一回继续讲解Init_HLW8112函数后续内容。