/********************************************************************************************************* * 模块名称:HT7032_SPI.c * 摘 要:HT7032_SPI驱动文件 * 当前版本:1.0.0 * 作 者:anycrying * 完成日期:2024年04月20日 * 内 容: * 注 意: ********************************************************************************************************** * 取代版本: * 作 者: * 完成日期: * 修改内容: * 修改文件: *********************************************************************************************************/ /********************************************************************************************************* * 包含头文件 *********************************************************************************************************/ #include "HT7032_SPI.h" #include /********************************************************************************************************* * 宏定义 *********************************************************************************************************/ /********************************************************************************************************* * 枚举结构体 *********************************************************************************************************/ //校表参数常数定义-------------------------------------------------------------- static const struct HT7032_CaliPara { uint8_t addr; //寄存器地址 uint16_t rst; //复位参数 uint16_t set; //设置参数 uint8_t mod; //参数类型 }HT7032_CaliPara[] = { {HT7032_w_ModeCfg, 0x89AA, 0xB87E, 0}, //模式相关控制器 开启Ia,Ua,Ib,Ub,Ic,Uc通道ADC,关闭ADC Chop,开启REF chop,Femu=1.8MHz,ref偏置电流7.5uA,有效值更新慢速,稳定慢速, {HT7032_w_PGACtrl, 0x0000, 0x0154, 0}, //ADC增益选择 A,B,C电流通道2倍增益,电压通道2倍增益, {HT7032_w_EMUCfg, 0x0804, 0x78C4, 0}, //EMU模块配置寄存器 视在功率/能量采用PQS方式,3P4W代数和累加,能量读后清零,功率作启动判断,开启有功,无功,视在能量计算 {HT7032_w_PgainA, 0x0000, 0, 1}, //A相有功功率增益 {HT7032_w_PgainB, 0x0000, 1, 1}, //B相有功功率增益 {HT7032_w_PgainC, 0x0000, 2, 1}, //C相有功功率增益 {HT7032_w_QgainA, 0x0000, 0, 1}, //A相无功功率增益 {HT7032_w_QgainB, 0x0000, 1, 1}, //B相无功功率增益 {HT7032_w_QgainC, 0x0000, 2, 1}, //C相无功功率增益 {HT7032_w_SgainA, 0x0000, 0, 1}, //A相视在功率增益 {HT7032_w_SgainB, 0x0000, 1, 1}, //B相视在功率增益 {HT7032_w_SgainC, 0x0000, 2, 1}, //C相视在功率增益 {HT7032_w_PhSregApq0, 0x0000, 3, 1}, //A相相位校正0 {HT7032_w_PhSregBpq0, 0x0000, 4, 1}, //B相相位校正0 {HT7032_w_PhSregCpq0, 0x0000, 5, 1}, //C相相位校正0 {HT7032_w_PhSregApq1, 0x0000, 6, 1}, //A相相位校正1 {HT7032_w_PhSregBpq1, 0x0000, 7, 1}, //B相相位校正1 {HT7032_w_PhSregCpq1, 0x0000, 8, 1}, //C相相位校正1 {HT7032_w_PoffsetA, 0x0000, 9, 1}, //A相有功功率offset校正 {HT7032_w_PoffsetB, 0x0000, 10, 1}, //B相有功功率offset校正 {HT7032_w_PoffsetC, 0x0000, 11, 1}, //C相有功功率offset校正 {HT7032_w_QPhscal, 0x0000, 0xFF66, 0}, //无功相位校正 {HT7032_w_UgainA, 0x0000, 12, 1}, //A相电压增益 {HT7032_w_UgainB, 0x0000, 13, 1}, //B相电压增益 {HT7032_w_UgainC, 0x0000, 14, 1}, //C相电压增益 {HT7032_w_IgainA, 0x0000, 15, 1}, //A相电流增益 {HT7032_w_IgainB, 0x0000, 16, 1}, //B相电流增益 {HT7032_w_IgainC, 0x0000, 17, 1}, //C相电流增益 {HT7032_w_Istartup, 0x0160, 864u, 0}, //启动电流阈值设置 5A*(1000/144)*0.3%*2^13 {HT7032_w_HFConst, 0x0500, 500u*2, 0}, //高频脉冲输出设置 {HT7032_w_FailVolt, 0x0600, 0x0600, 0}, //失压阈值设置 不用 {HT7032_w_GainADC7, 0x0000, 0x0000, 0}, //第七路ADC输入信号增益 reserved {HT7032_w_QoffsetA, 0x0000, 0x0000, 0}, //A相无功功率offset校正 {HT7032_w_QoffsetB, 0x0000, 0x0000, 0}, //B相无功功率offset校正 {HT7032_w_QoffsetC, 0x0000, 0x0000, 0}, //C相无功功率offset校正 {HT7032_w_URmsoffsetA, 0x0000, 0x0000, 0}, //A相电压有效值offset校正 {HT7032_w_URmsoffsetB, 0x0000, 0x0000, 0}, //B相电压有效值offset校正 {HT7032_w_URmsoffsetC, 0x0000, 0x0000, 0}, //C相电压有效值offset校正 {HT7032_w_IRmsoffsetA, 0x0000, 0x0009, 0}, //A相电流有效值offset校正 {HT7032_w_IRmsoffsetB, 0x0000, 0x0009, 0}, //B相电流有效值offset校正 {HT7032_w_IRmsoffsetC, 0x0000, 0x0009, 0}, //C相电流有效值offset校正 {HT7032_w_UoffsetA, 0x0000, 0x0000, 0}, //A相电压通道ADC offset校正 {HT7032_w_UoffsetB, 0x0000, 0x0000, 0}, //B相电压通道ADC offset校正 {HT7032_w_UoffsetC, 0x0000, 0x0000, 0}, //C相电压通道ADC offset校正 {HT7032_w_IoffsetA, 0x0000, 0x0000, 0}, //A相电流通道ADC offset校正 {HT7032_w_IoffsetB, 0x0000, 0x0000, 0}, //B相电流通道ADC offset校正 {HT7032_w_IoffsetC, 0x0000, 0x0000, 0}, //C相电流通道ADC offset校正 {HT7032_w_EMUIE, 0x0001, 0x0001, 0}, //中断使能 {HT7032_w_ModuleCfg, 0x3527, 0x3437, 0}, //电路模块配置寄存器 开启电压,电流高通,关闭罗氏线圈,开启TPS,BOR,选择PN传感器 {HT7032_w_AllGain, 0x0000, 0x0000, 0}, //全通道增益 {HT7032_w_HFDouble, 0x0000, 0x0000, 0}, //脉冲常数加倍选择 {HT7032_w_LineGain, 0x2C59, 0x2C59, 0}, //基波增益校正 {HT7032_w_PinCtrl, 0x000F, 0x000F, 0}, //数字pin上拉电阻选择控制 内置上拉300K电阻 {HT7032_w_Pstartup, 0x0030, 216u, 0}, //启动功率阈值设置 (Un*Ib*HFConst*imp*0.3%*2^23/(2.592*10^10)) {HT7032_w_Iregion0, 0x7FFF, 3000u, 0}, //相位补偿区域设置寄存器0 5A*(1000/144)*270%*2^5 {HT7032_w_Cyclength, 0x1000, 0x1000, 0}, //SAG数据长度设置寄存器 {HT7032_w_SAGLevel, 0x4500, 0x4500, 0}, //SAG检测阈值设置寄存器 {HT7032_w_Iregion1, 0x0000, 180u, 0}, //相位补偿区域设置寄存器1 5A*(1000/144)*162%*2^5 {HT7032_w_PhSregApq2, 0x0000, 18, 1}, //A相相位校正2 {HT7032_w_PhSregBpq2, 0x0000, 19, 1}, //B相相位校正2 {HT7032_w_PhSregCpq2, 0x0000, 20, 1}, //C相相位校正2 {HT7032_w_PoffsetAL, 0x0000, 21, 1}, //A相有功功率offset校正低字节 //X {HT7032_w_PoffsetBL, 0x0000, 22, 1}, //B相有功功率offset校正低字节 //X {HT7032_w_PoffsetCL, 0x0000, 23, 1}, //C相有功功率offset校正低字节 //X {HT7032_w_QoffsetAL, 0x0000, 0x0000, 0}, //A相无功功率offset校正低字节 {HT7032_w_QoffsetBL, 0x0000, 0x0000, 0}, //B相无功功率offset校正低字节 {HT7032_w_QoffsetCL, 0x0000, 0x0000, 0}, //C相无功功率offset校正低字节 {HT7032_w_IRmsoffsetT, 0x0000, 0x0009, 0}, //电流矢量和offset校正寄存器 {HT7032_w_TPSoffset, 0x0000, 24, 1}, //TPS初值校正寄存器 {HT7032_w_TPSgain, 0x0000, 0x0000, 0}, //TPS斜率校正寄存器 {HT7032_w_TCoffA, 0xFEFF, 0xFF11, 0}, //Vrefgain的二次系数 {HT7032_w_TCoffB, 0xEF7A, 0x2B52, 0}, //Vrefgain的一次系数 {HT7032_w_TCoffC, 0x047C, 0xD483, 0}, //Vrefgain的常数项 {HT7032_w_EMCfg, 0x0000, 0x0022, 0}, //新增算法控制寄存器 3P4W制,使用自动补偿,电流矢量算法1,角度算法1,无功能量全波无功,谐波能量,夹角参考Ua, {HT7032_w_OILevel, 0x0000, 0x0000, 0}, //过流阈值设置寄存器 }; /********************************************************************************************************* * 内部变量定义 *********************************************************************************************************/ uint8_t HT7032_DevOK_flag[HT7032_Device_N] = {0}; uint32_t HT7032_SPI_RX_buff[HT7032_SPI_buff_len] = {0}; uint32_t HT7032_SPI_TX_buff[HT7032_SPI_buff_len] = {0}; /********************************************************************************************************* * 内部函数声明 *********************************************************************************************************/ void HT7032_SPI_config(void); void SPI_Delay(void); uint32_t Read_SPI_IO(uint8_t addr); void Write_SPI_IO(uint8_t addr, uint32_t da); uint32_t HT7032_Wr_Rd_Reg(uint8_t CHx,uint8_t cmd_wr,uint8_t addr,uint32_t da); void init_HT7032_DEV(uint8_t CHx); /********************************************************************************************************* * 内部函数实现 *********************************************************************************************************/ /********************************************************************************************************* * 函数名称:init_HT7032_SPI * 函数功能:初始化与HT7032通信的SPI模块,不采用DMA方式 * 输入参数:void * 输出参数:void * 返 回 值:void * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ void init_HT7032_SPI(void) { HT7032_SPI_config(); } /********************************************************************************************************* * 函数名称:HT7032_SPI_config * 函数功能:配置与HT7032通信的SPI端口 * 输入参数:void * 输出参数:void * 返 回 值:void * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ void HT7032_SPI_config(void) { /* deinitilize SPI and the parameters */ spi_parameter_struct spi_init_struct; /* peripheral clock enable */ rcu_periph_clock_enable(HT7032_SPI_RCU); rcu_periph_clock_enable(HT7032_IRQ_RCU); /*SPI0 GPIO config */ gpio_mode_set(HT7032_SPI_IO, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, HT7032_SPI_SCLK | HT7032_SPI_MOSI); gpio_output_options_set(HT7032_SPI_IO,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,HT7032_SPI_SCLK | HT7032_SPI_MOSI);//设置GPIO输出模式及速度 gpio_mode_set(HT7032_SPI_IO, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, HT7032_SPI_MISO); // gpio_mode_set(HT7032_SPI_IO, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, HT7032_SPI_CS0 | HT7032_SPI_CS1 | HT7032_SPI_CS2); //配置为输出 gpio_output_options_set(HT7032_SPI_IO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, HT7032_SPI_CS0 | HT7032_SPI_CS1 | HT7032_SPI_CS2); //设置GPIO输出模式及速度 gpio_mode_set(HT7032_IRQ_IO, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, HT7032_IRQ0 | HT7032_IRQ1 | HT7032_IRQ2); SPI_CS0_H; SPI_CS1_H; SPI_CS2_H; init_HT7032_DEV(HT7032_CH0); init_HT7032_DEV(HT7032_CH1); init_HT7032_DEV(HT7032_CH2); } /********************************************************************************************************* * 函数名称:HT7032_Wr_Rd_Reg * 函数功能:主机读写HT7032的SPI端口 * 输入参数:CHx片选:CSx;cmd_wr操作命令:1:写,0:读; addr寄存器地址;da数据:写操作时有效。 * 输出参数:uint32_t,相应寄存器地址里的值 * 返 回 值:uint32_t * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ uint32_t HT7032_Wr_Rd_Reg(uint8_t CHx,uint8_t cmd_wr,uint8_t addr,uint32_t da) { bool temp_flag = false; uint16_t i = 0; uint8_t temp_buff = 0; uint32_t temp_d0 = 0; SPI_CS0_H; SPI_CS1_H; SPI_CS2_H; SPI_Delay(); SPI_SCLK_L; SPI_Delay(); switch(CHx) { case HT7032_CH0: { SPI_CS0_L; temp_flag = true; break; } case HT7032_CH1: { SPI_CS1_L; temp_flag = true; break; } case HT7032_CH2: { SPI_CS2_L; temp_flag = true; break; } default: { temp_flag = false; break; } } SPI_Delay(); SPI_Delay(); if(temp_flag) { temp_buff = addr; if(cmd_wr == CMD_write) { temp_buff |= 0x80; Write_SPI_IO(temp_buff,da); } else { temp_d0 = Read_SPI_IO(temp_buff); } } SPI_CS0_H; SPI_CS1_H; SPI_CS2_H; for(i = 0;i< 100;i++) { SPI_Delay(); } return temp_d0; } /********************************************************************************************************* * 函数名称:init_HT7032_DEV * 函数功能:初始化HT7032设备x * 输入参数:CHx:第x个设备 * 输出参数:void * 返 回 值:void * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ void init_HT7032_DEV(uint8_t CHx) { uint32_t temp0 = 0; uint32_t temp1 = 0; uint32_t temp2 = 0; temp2 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_EnRdCali, ~0x0000005A); //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_read,HT7032_r_DeviceID,0); temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_read,HT7032_r_DeviceID,0);//0x7122A0 //temp0 = HT7032_Wr_Rd_Reg(CHx,CMD_read,HT7032_r_ChipID,0); temp0 = HT7032_Wr_Rd_Reg(CHx,CMD_read,HT7032_r_ChipID,0);//0x7022E0 if((temp1 == HT7032_DeviceID) && (temp0 == HT7032_ChipID)) { HT7032_DevOK_flag[CHx] = 1; //开启写校表参数// temp2 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_EnWrCali, 0x0000005A); //校表参数配置,配置都是一样的,HT7032设备// temp2 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_ModeCfg,0x0000b87e); //ADC增益选择,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_PGACtrl,0x00000000); //EMU 单元配置,默认值,ADC滤波选择// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_EMUCfg,0x00000000); //功率增益补偿选择,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_PgainA,0x00000000); //相位校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_PhSregApq0,0x00000000); //功率 offset校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_PoffsetA,0x00000000); //基波无功相位校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_QPhscal,0x00000000); //电压增益校正校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_UgainA,0x00000000); //电流增益校正校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_IgainA,0x00000000); //起动电流设置,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_Istartup,0x00000000); //高频脉冲常数设置,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_HFConst,0x00000000); //失压阈值设置,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_FailVolt,0x00000000); //有效值 offset 校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_URmsoffsetA,0x00000000); //ADC offset 校正,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_UoffsetA,0x00000000); //中断使能寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_EMUIE,0x00000001); //模拟模块使能寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_ModuleCfg,0x00000000); //全通道增益寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_AllGain,0x00000000); //脉冲加倍寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_HFDouble,0x00000000); //基波增益寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_LineGain,0x00000000); //IO 状态配置寄存器,默认值,均为上拉// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_PinCtrl,0x00000000); //起动功率寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_Pstartup,0x00000000); //相位补偿区域设置寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_Iregion1,0x00000000); //SAG 过流检测数据长度设置寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_Cyclength,0x00000000); //SAG 检测阈值设置寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_SAGLevel,0x00000000); //过流检测阈值设置寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_OILevel,0x00000000); //自动温度补偿相关寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_TPSoffset,0x00000000); //Tgain校正寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_TPSgain,0x00000000); //Vrefgain的补偿曲线系数,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_TCoffA,0x00000000); //算法控制寄存器,默认值// //temp1 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_EMCfg,0x00000000); //关闭写校表参数// temp2 = HT7032_Wr_Rd_Reg(CHx,CMD_write,HT7032_w_EnWrCali, ~0x0000005A); } else { HT7032_DevOK_flag[CHx] = 0; } } /********************************************************************************************************* 功能描述:读取计量参数 输入参数:CHx:第x个设备;addr:寄存器地址;*pBuff:缓存 返回参数: 函数说明: *********************************************************************************************************/ uint32_t Get_MeterPara_value(uint8_t CHx,uint8_t addr) { uint32_t pBuff; pBuff = HT7032_Wr_Rd_Reg(CHx,CMD_read,addr, 0x00000000); return pBuff; } /********************************************************************************************************* * 函数名称:Read_SPI_IO * 函数功能:对SPI接口进行读操作 * 输入参数:addr:外设寄存器地址 * 输出参数:uint32_t,实际是24位有效值 * 返 回 值:uint32_t * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ uint32_t Read_SPI_IO(uint8_t addr) { uint8_t i; uint32_t temp = 0; addr &= 0x7F; SPI_Delay(); for(i = 0;i < 8;i++) { SPI_SCLK_H; if (addr & 0x80) { SPI_MOSI_H; } else { SPI_MOSI_L; } addr <<= 1; SPI_Delay(); SPI_SCLK_L; SPI_Delay(); } SPI_Delay(); SPI_Delay(); SPI_Delay(); SPI_Delay(); SPI_Delay(); SPI_Delay(); for(i = 0;i < 24;i++) { temp = temp << 1; SPI_SCLK_H; SPI_Delay(); SPI_SCLK_L; SPI_Delay(); if (SPI_MISO() > 0) { temp |= 0x01; } SPI_Delay(); } SPI_Delay(); return temp; } /********************************************************************************************************* * 函数名称:Write_SPI_IO * 函数功能:对SPI接口进行写操作 * 输入参数:addr:外设寄存器地址;da:写入的数据,实际是24位有效值 * 输出参数: * 返 回 值: * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ void Write_SPI_IO(uint8_t addr, uint32_t da) { uint8_t i; addr |= 0x80; //SPI_Delay(); //SPI_SCLK_L; //SPI_Delay(); for(i = 0;i < 8;i++) { SPI_Delay(); SPI_SCLK_H; if (addr & 0x80) { SPI_MOSI_H; } else { SPI_MOSI_L; } SPI_Delay(); addr <<= 1; SPI_SCLK_L; } for(i = 0;i < 24;i++) { SPI_Delay(); SPI_SCLK_H; if(da & 0x800000) { SPI_MOSI_H; } else { SPI_MOSI_L; } da <<= 1; SPI_Delay(); SPI_SCLK_L; } SPI_Delay(); } /********************************************************************************************************* * 函数名称:SPI_Delay * 函数功能:延时 * 输入参数: * 输出参数: * 返 回 值: * 创建日期:2024年04月20日 * 注 意: *********************************************************************************************************/ void SPI_Delay(void) { static uint16_t i = 750; while(i > 0) { i--; } }