当前位置: 首页 > news >正文

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寄存器的内容。这些寄存器的具体意义,下一回详细讲解。

http://www.jsqmd.com/news/1177066/

相关文章:

  • closeEvalDialog is not defined、pages.json 语法、硬编码 ID ——记几个低级错误
  • 去烟味喷雾效果好的有哪些?核心特质解析与全场景选购使用指南 - 行业洞察分析师
  • Socket网络编程入门:UDP+TCP双案例手把手教你写服务器
  • 免费开源2D动画制作软件:OpenToonz完整指南
  • Glorytun安全配置详解:保护你的UDP隧道通信的完整策略
  • 快速上手PUBG地图黑客:5分钟搭建实战指南
  • 开心消消乐分数系统详解:如何设计刺激玩家的积分机制
  • 如何用PrivateGPT快速搭建企业级私有化AI应用:完整指南
  • morss部署教程:从本地到云端的完整步骤指南
  • 【Matlab】不确定干扰下无人机鲁棒控制实现
  • 我的第一个工具调用Agent:从零构建“知识库+计算器+时间+文件”四合一智能体
  • 手把手教你学pcie--TLP 长什么样?(不看协议也能懂)
  • 如何利用开源AI框架实现精准时间序列预测:5个关键技术解析
  • Rufus终极指南:三步搞定Windows 11安装,轻松绕过TPM 2.0限制
  • 暑期学习怎么做才有效?别再让孩子“假努力”,这套学习方法正在被家长用起来
  • vagas平台的未来路线图:即将到来的功能与改进
  • MetaTube SDK Go实战案例:构建企业级元数据管理平台的完整方案
  • 【API文档自动化革命】:ChatGPT生成高质量OpenAPI文档的5大实战范式(2024企业级落地指南)
  • Inventory Kamera实战教程:如何一键扫描并导出原神完整库存数据
  • 智能拼版构建柔性与刚性线路板智造
  • 如何快速部署本地大语言模型:TextGen完整使用指南
  • 如何用PyQt-SiliconUI在5分钟内构建专业级桌面应用界面
  • Psychson完全指南:模块化部署Phison 2251-03固件的深度实战手册
  • LocalAI:如何构建自主可控的AI基础设施技术方案?
  • 亲身到店探访杭州亨得利官方名表服务中心|全新地址及服务热线(2026年7月更新) - 亨得利官方
  • JOAL高级使用技巧:10个配置优化提升PT站点做种效率与积分获取
  • 衣服除烟味护理指南:针对领口、袖口等易沾染烟味的部位,详解多场景适用的根源分解型喷雾高效使用方法 - 行业洞察分析师
  • 小红书内容采集神器XHS-Downloader:3分钟掌握无水印下载技巧
  • IEEE 802标准体系
  • vagas的代码审查与质量控制流程解析