#include "user.h" #include //求根号 #define USING_SOFT_SPI #define RN8209D_CS_SET() HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_SET) #define RN8209D_CS_CLR() HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_RESET) #define RNDelay delay_us #define RN_CLOCKWIDTH 30 StDef_RN8209DPara StDef_RN8209DPara_Reg; void RN8209D_GetCheckSum(void); void RN8209D_ReadRegNoCheck(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen) { uint8_t ucI,ucK; RN8209D_CS_CLR(); delay_us(10); addr |= 0x00; HAL_SPI_Transmit(&hspi1,&addr,1,10);//发送读数据命令(bit.7=0) delay_us(50); HAL_SPI_Transmit(&hspi1,regbuf,regbuflen,10); //发送数据 delay_us(10); RN8209D_CS_SET(); } uint8_t RN8209D_ReadReg(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen) { uint8_t buf[4]; RN8209D_ReadRegNoCheck(addr,regbuf,regbuflen); m_memset(buf,0x01,4); RN8209D_ReadRegNoCheck(Reg_RData,buf,4); if(regbuflen == 3){ if(m_memcmp(regbuf,buf+1,regbuflen) == 0) return 0; else return 1; } else if(regbuflen == 4){ if(m_memcmp(regbuf,buf,regbuflen) == 0) return 0; else return 1; } else if(regbuflen == 2){ if(m_memcmp(regbuf,buf+2,regbuflen) == 0) return 0; else return 1; } else{ return 1; } } void RN8209D_WriteRegNoCheck(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen) { uint8_t ucI,ucK; RN8209D_CS_CLR(); delay_us(100); addr |= 0x80; //发送写数据命令(bit.7=1) for(ucI=0;ucI<8;ucI++) { if( addr & 0x80 ) RN8209D_MOSI_SET(); else RN8209D_MOSI_CLR(); ; RN8209D_SCK_SET(); delay_us(RN_CLOCKWIDTH); RN8209D_SCK_CLR(); //在时钟的下降沿写数据 addr<<=1; delay_us(RN_CLOCKWIDTH); } RN8209D_MOSI_CLR(); RN8209D_SCK_CLR(); delay_us(500); for(ucK=0;ucK 0){ GPQx = (uint16_t)(k*32768); //写使能 regbuf[0] = 0xE5; RN8209D_WriteReg(WREN,regbuf,1); regbuf[0] = GPQx/256; regbuf[1] = GPQx%256; RN8209D_WriteReg(regGPx[phase],regbuf,2); } else{ GPQx = (uint16_t)(k*32768+65536); //写使能 regbuf[0] = 0xE5; RN8209D_WriteReg(WREN,regbuf,1); //写寄存器 regbuf[0] = GPQx/256; regbuf[1] = GPQx%256; RN8209D_WriteReg(regGPx[phase],regbuf,2); m_memset(regbuf,0x00,2); RN8209D_ReadReg(regGPx[phase],regbuf,2); } if(phase == phase_A){ StDef_RN8209DPara_Reg.Cst_GPQA = GPQx; if(RN8209D_ReadReg(regArry[phase],regbuf,2)==0){ tempValue = regbuf[0]*256+regbuf[1]; //StDef_RN8209DPara_Reg.Cst_Kpa = tempValue / 1100; } } else if(phase == phase_B){ StDef_RN8209DPara_Reg.Cst_GPQB = GPQx; if(RN8209D_ReadReg(regArry[phase],regbuf,2)==0){ tempValue = regbuf[0]*256+regbuf[1]; //StDef_RN8209DPara_Reg.Cst_Kpb = tempValue / 1100; } } } /******************************************************** 功能描述: 误差法校准相位 参数说明: 返回说明: 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ void RN8209D_CalibratePhsXErr(uint8_t phase,int16_t err) { double k = 0; uint8_t phsValue = 0; const uint16_t regGPx[]={Reg_PhsA,Reg_PhsB}; uint8_t regbuf[5]; k = asin(-err/10000.0/1.732)*180/3.142; if(k > 0){ phsValue = (uint8_t)(k/0.02); } else{ phsValue = (uint8_t)(k/0.02+512); } //写使能 regbuf[0] = 0xE5; RN8209D_WriteReg(WREN,regbuf,1); //写寄存器 regbuf[0] = phsValue; RN8209D_WriteReg(regGPx[phase],regbuf,1); if(phase == phase_A){ StDef_RN8209DPara_Reg.Cst_PhsA = phsValue; } else if(phase == phase_B){ StDef_RN8209DPara_Reg.Cst_PhsB = phsValue; } } /******************************************************** 功能描述: 计算有功功率offset 参数说明: 返回说明: 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ //void RN8209D_CalibrateAPOSx(uint8_t phase) //{ // uint8_t regbuf[5]; // uint32_t regtemp[12],regtotal=0; // const uint16_t regArry[]={Reg_PowerPA,Reg_PowerPB}; // const uint16_t reg_APOSArry[]={Reg_APOSA,Reg_APOSB}; // uint8_t i = 0; // uint16_t temp; // for(i=0;i<12;i++){ // if(RN8209D_ReadReg(regArry[phase],regbuf,4)==0){ // regtemp[i] = (regbuf[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]); // //求补码 // if(regtemp[i]&0x80000000){ // regtemp[i] = ~regtemp[i]; // regtemp[i] += 1; // } // } // delay_ms(350); // } // //第一个数据不要 // for(i=1;i<12;i++){ // regtotal += regtemp[i]; // } // regtotal /= 11; // temp = (regtotal&0x0000FFFF); // //写使能 // regbuf[0] = 0xE5; // RN8209D_WriteReg(WREN,regbuf,1); // //写寄存器 // regbuf[0] = temp/256;regbuf[1] = temp%256; // RN8209D_WriteReg(reg_APOSArry[phase],regbuf,2); //} void RN8209D_CalibrateAPOSx(uint8_t phase) { uint8_t regbuf[5]; uint32_t regtemp[12],regtotal=0; const uint16_t regArry[]={Reg_PowerPA,Reg_PowerPB}; const uint16_t reg_APOSArry[]={Reg_APOSA,Reg_APOSB}; const uint16_t reg_GPQxArry[]={Reg_GPQA,Reg_GPQB}; uint8_t i = 0; uint16_t temp; float gGPQx = 0; double k = 0; for(i=0;i<12;i++){ if(RN8209D_ReadReg(regArry[phase],regbuf,4)==0){ regtemp[i] = (regbuf[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]); //求补码 if(regtemp[i]&0x80000000){ regtemp[i] = ~regtemp[i]; regtemp[i] += 1; } } delay_ms(350); } //第一个数据不要 for(i=1;i<12;i++){ regtotal += regtemp[i]; } regtotal /= 11; RN8209D_ReadReg(reg_GPQxArry[phase],regbuf,2); temp = regbuf[0]*256+regbuf[1]; if(temp&0x8000) { gGPQx = (temp-65536)/32768.0; } else{ gGPQx = temp/32768.0; } k = (602299-regtotal)/(1+gGPQx); if(k > 0){ temp = (uint16_t)k; } else{ temp = (uint16_t)(k+65536); } //写使能 regbuf[0] = 0xE5; RN8209D_WriteReg(WREN,regbuf,1); //写寄存器 regbuf[0] = temp/256;regbuf[1] = temp%256; RN8209D_WriteReg(reg_APOSArry[phase],regbuf,2); if(phase == phase_A){ StDef_RN8209DPara_Reg.Cst_APOSA = temp; } else if(phase == phase_B){ StDef_RN8209DPara_Reg.Cst_APOSB = temp; } } /******************************************************** 功能描述: 计算电流通道offset 参数说明: 返回说明: 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ void RN8209D_CalibrateCurrentOffset(uint8_t phase) { uint8_t regbuf[5]; uint32_t regtemp[12],regtotal=0; const uint16_t regArry[]={Reg_IARMS,Reg_IBRMS}; const uint16_t regIx_OS[]={Reg_IARMSOS,Reg_IBRMSOS}; uint8_t i = 0; uint16_t temp; for(i=0;i<12;i++) { if(RN8209D_ReadReg(regArry[phase],regbuf,3)==0){ regtemp[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); } delay_ms(350); } //第一个数据不要 for(i=1;i<12;i++){ regtotal += regtemp[i]; } regtotal /= 11; regtotal = regtotal * regtotal; //求反码 regtotal = ~regtotal; temp = (regtotal>>8); //符号位 if(regtotal & 0x80000000) temp |= 0x8000; //写使能 regbuf[0] = 0xE5; RN8209D_WriteReg(WREN,regbuf,1); //写寄存器 regbuf[0] = temp/256;regbuf[1] = temp%256; RN8209D_WriteReg(regIx_OS[phase],regbuf,2); if(phase == phase_A){ StDef_RN8209DPara_Reg.Cst_IARMSOS = temp; } else if(phase == phase_B){ StDef_RN8209DPara_Reg.Cst_IBRMSOS = temp; } } /******************************************************** 功能描述: 计算电压、电流显示转换系数 参数说明: 返回说明: 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ void RN8209D_CalibrateKx(uint8_t phase) { uint8_t regbuf[3]; //uint32_t tempValue; uint32_t regtemp[12],regtotal=0; uint8_t i = 0; if(phase == phase_A){ for(i=0;i<12;i++) { if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){ regtemp[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); } delay_ms(350); } //第一个数据不要 for(i=1;i<12;i++){ regtotal += regtemp[i]; } regtotal /= 11; StDef_RN8209DPara_Reg.Cst_Ku = regtotal / 220; regtotal = 0; for(i=0;i<12;i++) { if(RN8209D_ReadReg(Reg_IARMS,regbuf,3)==0){ regtemp[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); } delay_ms(350); } //第一个数据不要 for(i=1;i<12;i++){ regtotal += regtemp[i]; } regtotal /= 11; StDef_RN8209DPara_Reg.Cst_Kia = regtotal / 5; } else if(phase == phase_B){ for(i=0;i<12;i++) { if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){ regtemp[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); } delay_ms(350); } //第一个数据不要 for(i=1;i<12;i++){ regtotal += regtemp[i]; } regtotal /= 11; StDef_RN8209DPara_Reg.Cst_Ku = regtotal / 220; regtotal = 0; for(i=0;i<12;i++) { if(RN8209D_ReadReg(Reg_IBRMS,regbuf,3)==0){ regtemp[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); } delay_ms(350); } //第一个数据不要 for(i=1;i<12;i++){ regtotal += regtemp[i]; } regtotal /= 11; StDef_RN8209DPara_Reg.Cst_Kib = regtotal / 5; } } /******************************************************** 功能描述: 参数说明: 返回说明: 扩大10倍 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ uint8_t RN8209D_ReadVoltage(uint16_t *vol) { uint8_t regbuf[3]; uint32_t tempValue; if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){ tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); if(tempValue & 0x800000){ tempValue = 0; } else{ *vol = (uint16_t)(tempValue*10.0/StDef_RN8209DPara_Reg.Cst_Ku); } return 0; } return 1; } /******************************************************** 功能描述: 参数说明: 返回说明: 扩大1000倍 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ uint8_t RN8209D_ReadCurrent(uint8_t phase,uint16_t *current) { uint8_t regbuf[3]; uint32_t tempValue; if(phase == phase_A){ if(RN8209D_ReadReg(Reg_IARMS,regbuf,3)==0){ tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); if(tempValue & 0x800000){ tempValue = 0; } else{ *current = (uint16_t)(tempValue*1000.0/StDef_RN8209DPara_Reg.Cst_Kia); } return 0; } } else if(phase == phase_B){ if(RN8209D_ReadReg(Reg_IBRMS,regbuf,3)==0){ tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); if(tempValue & 0x800000){ tempValue = 0; } else{ *current = (uint16_t)(tempValue*1000.0/StDef_RN8209DPara_Reg.Cst_Kib); } return 0; } } return 1; } /******************************************************** 功能描述: 读取有功功率 参数说明: 返回说明: 扩大1000倍 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ uint8_t RN8209D_ReadPower(uint8_t phase,uint32_t *p) { uint8_t regbuf[4]; uint32_t tempValue; if(phase == phase_A){ if(RN8209D_ReadReg(Reg_PowerPA,regbuf,4)==0){ tempValue = (regbuf[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]); if(tempValue&0x80000000){ tempValue = ~tempValue; tempValue += 1; } // if(tempValue>=21903393){ // *p = (uint32_t)(tempValue*0.0000457); // } // else if(tempValue<21903393 && tempValue>=2190339){ // *p = (uint32_t)(tempValue*10*0.0000457); // } // else if(tempValue<2190339 && tempValue>=219033){ // *p = (uint32_t)(tempValue*100*0.0000457); // } // else if(tempValue<219033){ // *p = (uint32_t)(tempValue*1000*0.0000457); // } *p = (uint32_t)(tempValue*0.000457); return 0; } } else if(phase == phase_B){ if(RN8209D_ReadReg(Reg_PowerPB,regbuf,4)==0){ tempValue = (regbuf[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]); if(tempValue&0x80000000){ tempValue = ~tempValue; tempValue += 1; } *p = (uint32_t)(tempValue*0.0000457); return 0; } } return 1; } /******************************************************** 功能描述: 读取累计电量 参数说明: 返回说明: 扩大100倍 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ uint8_t RN8209D_ReadTotalE(uint8_t phase,uint32_t *p) { uint8_t regbuf[3]; uint32_t tempValue; if(phase == phase_A){ if(RN8209D_ReadReg(Reg_EnergyP,regbuf,3)==0){ tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); //*p = (uint32_t)(tempValue*100.0/3200); *p = tempValue; return 0; } } else if(phase == phase_B){ if(RN8209D_ReadReg(Reg_EnergyD,regbuf,3)==0){ tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); //*p = (uint32_t)(tempValue*100.0/3200); *p = tempValue; return 0; } } return 1; } /******************************************************** 功能描述: 读取校验寄存器 参数说明: 返回说明: 调用方式: 全局变量: 读写时间: 注意事项: 日期 : ********************************************************/ uint8_t RN8209D_ReadCheckSum(uint32_t *p) { uint8_t regbuf[3]; uint32_t tempValue; if(RN8209D_ReadReg(Reg_EMUStatus,regbuf,3)==0){ tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]); *p = tempValue; return 0; } return 1; }