Baldwin 发表于 2018-8-22 19:16:34

RN8302计量芯片使用经验分享

本帖最后由 Baldwin 于 2018-8-22 19:16 编辑

最近有款产品需要用到电能计量,选用了FM33A0xx+RN8302主流方案。计量模块开发也是从一知半解到懵懂,再到熟悉,酸甜苦辣因有尽有{:biggrin:} ,下面把相关资料分享给大家,尽量少走弯路;
1---------------------------------------硬件部分-------------------------------------------------------------------------
RN8302外围电路

电压、电流信号采集电路;电压采用常规电阻分压,电流采用电流互感器5(60)A/2mA;


2---------------------------------------RN8302 通信部分-------------------------------------------------------------------------
(1)RN8302采用模拟SPI通信(RN8302与MCU之间采用了光耦隔离,无法直接用硬件SPI,只能用软件SPI)
static void RN8302_GPIO_Init(void)
{
    //cs端口初始化
    OutputIO(RN8302_CS_GPIO, RN8302_CS_GPIO_Pin, 0);
    OutputIO(RN8302_SCK_GPIO, RN8302_SCK_GPIO_Pin, 0);
    InputIO(RN8302_MISO_GPIO, RN8302_MISO_GPIO_Pin, 1);
    OutputIO(RN8302_MOSI_GPIO, RN8302_MOSI_GPIO_Pin, 0);

    //MySPI1_Init();
    //SPIx_SPICR2_SPIEN_Setable(SPI1, ENABLE);//SPI1模块使能

    RN8302_CS_SET();
    RN8302_SCK_CLR();
    RN8302_MOSI_SET();
}

static void RN8302_SPI_WriteByte(uint8_t byte)
{
    uint8_t i=0;

    for(i=0;i<8;i++)        //写字节
    {
      RN8302_SCK_SET();       //在时钟的上升沿写数据
                RN8302_SCK_SET();
      RN8302_DelayUs(RN8302_CLOCKWIDTH);
                if(byte & 0x80 ){
          RN8302_MOSI_SET();
                  RN8302_MOSI_SET();
                }
      else{
          RN8302_MOSI_CLR();
              RN8302_MOSI_CLR();
                }
                RN8302_DelayUs(RN8302_CLOCKWIDTH/2);
      RN8302_SCK_CLR();
                RN8302_SCK_CLR();
      RN8302_DelayUs(RN8302_CLOCKWIDTH);      
      byte <<= 1;
    }
    RN8302_DelayUs(RN8302_CLOCKWIDTH);   
}

static uint8_t RN8302_SPI_ReadByte(void)
{
    uint8_t i=0,byte=0;

    for(i=0;i<8;i++)        //读字节
    {
      byte <<= 1;
      RN8302_SCK_SET();
      RN8302_SCK_SET();
      RN8302_DelayUs(RN8302_CLOCKWIDTH);
      RN8302_SCK_CLR();
      RN8302_SCK_CLR();
      RN8302_DelayUs(RN8302_CLOCKWIDTH);
      if(RN8302_Read_MISO())//在时钟的下降沿读数据
          byte += 0x01;
      //RN8302_DelayUs(RN8302_CLOCKWIDTH/2);
    }

    return byte;
}

(2)RN8302读写寄存器,查看手册,不具体说明
/********************************************************
功能描述:
参数说明:
返回说明: 0表示读取成功,非0表示读取失败
调用方式:
全局变量:
读写时间:
注意事项:
日期    :
********************************************************/
uint8_t RN8302_ReadReg(uint16_t regAddr,uint8_t *regBuf,uint8_t regLen)
{
    uint8_t i = 0,chksum = 0;
    uint8_t buf={0};

    RN8302_CS_CLR();
    RN8302_DelayUs(RN8302_CLOCKWIDTH);
    buf = (uint8_t)(regAddr&0x00FF);
    buf = ((uint8_t)(regAddr>>4))&0xF0|RN8302_Cmd_Read;
    for(i=0;i<2;i++)
    {
      RN8302_SPI_WriteByte(buf);
      chksum += buf;
    }
    RN8302_DelayUs(RN8302_CLOCKWIDTH);
    //最后一个字节是cs校验,所以要多收一个
    for(i=0;i<regLen+1;i++)
    {
      regBuf = RN8302_SPI_ReadByte();
    }
    for(i=0;i<regLen;i++)
    {
      chksum += regBuf;
    }
    RN8302_DelayUs(RN8302_CLOCKWIDTH);
    RN8302_CS_SET();
       
        chksum ^= 0xFF;
       
    if(chksum == regBuf)
      return 0;
    else
      return 1;

}

void RN8302_WriteReg(uint16_t regAddr,uint8_t *regBuf,uint8_t regLen)
{
    uint8_t i = 0;
    uint8_t buf={0};
    uint8_t chksum = 0;

    RN8302_CS_CLR();
        RN8302_DelayUs(RN8302_CLOCKWIDTH);
    buf = (uint8_t)(regAddr&0xFF);
    buf = RN8302_Cmd_Write|((uint8_t)(regAddr>>4))&0xF0;

    for(i=0;i<2;i++){
      RN8302_SPI_WriteByte(buf);
      chksum += buf;
    }
    RN8302_DelayUs(RN8302_CLOCKWIDTH);
    for(i=0;i<regLen;i++){
      chksum += regBuf;
    }
    //最后一个字节是cs校验,所以要多写一个
    for(i=0;i<regLen;i++){
      RN8302_SPI_WriteByte(regBuf);
    }
    RN8302_SPI_WriteByte(~chksum);
    RN8302_DelayUs(RN8302_CLOCKWIDTH);
    RN8302_CS_SET();
}
这是RN8302寄存器地址范围,读取计量参数存储区时,16位寄存器地址前面为0x00xx;读取配置和状态寄存器时,16位寄存器地址前面为0x01xx,这点千万不用忘记了,之前再这边坑了好久{:cry:}

(3)RN8302初始化,将之前校表时换算出的寄存器值填入,这样RN8302采集到的值就是校准好的
uint8_t RN8302_Init(void)
{
    uint8_t regbuf;
    uint8_t status = 1;

    /* 端口初始化 */
    RN8302_GPIO_Init();

    //读取RN8302 DeviceID
    if(RN8302_ReadReg(0x018F,regbuf,3) == 0){
      if((regbuf==0x83)&&(regbuf==0x02)&&(regbuf==0x00)){
            status = 0;
      }
      else{
            status = 1;
      }
    }
    else{
      status = 1;
    }

    //deviceID读取成功
    if(status == 0){
      //写使能
      regbuf = 0xE5;
      RN8302_WriteReg(WREN,regbuf,1);
      //切换到EMM模式
      regbuf = 0xA2;
      RN8302_WriteReg(WMSW,regbuf,1);
      //复位
      regbuf = 0xFA;
      RN8302_WriteReg(SOFTRST,regbuf,1);
      TicksDelayMs(20);
      //写使能
      regbuf = 0xE5;
      RN8302_WriteReg(WREN,regbuf,1);
      //切换到EMM模式
      regbuf = 0xA2;
      RN8302_WriteReg(WMSW,regbuf,1);
      //写HFCONST1
      regbuf = 0x2E;
      regbuf = 0xA1;
      RN8302_WriteReg(HFCONST1,regbuf,2);
      //写电压增益
      regbuf = StDef_RN8302Para_Reg.Cst_GSUx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSUx%256;
      RN8302_WriteReg(GSUA,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GSUx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSUx%256;
      RN8302_WriteReg(GSUB,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GSUx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSUx%256;
      RN8302_WriteReg(GSUC,regbuf,2);
      //写电流增益
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx%256;
      RN8302_WriteReg(GSIA,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx%256;
      RN8302_WriteReg(GSIB,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx%256;
      RN8302_WriteReg(GSIC,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GSIx%256;
      RN8302_WriteReg(GSIN,regbuf,2);
      //采样通道IA分段相位校正
//      RN8302_WriteReg(PHSIA,(uint8_t*)&StDef_RN8302Para_Reg.PHSI,2);
//      RN8302_WriteReg(PHSIB,(uint8_t*)&StDef_RN8302Para_Reg.PHSI,2);
//      RN8302_WriteReg(PHSIC,(uint8_t*)&StDef_RN8302Para_Reg.PHSI,2);
      //通道相位分段校正,电流阈值               
//      RN8302_WriteReg(PRTH1L,(uint8_t*)&Dl645FirmPara.PRth,2);
//      RN8302_WriteReg(PRTH1H,(uint8_t*)&Dl645FirmPara.PRth,2);
//      RN8302_WriteReg(PRTH2L,(uint8_t*)&Dl645FirmPara.PRth,2);
//      RN8302_WriteReg(PRTH2H,(uint8_t*)&Dl645FirmPara.PRth,2);
      //x相有功功率增益
      regbuf = StDef_RN8302Para_Reg.Cst_GPx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GPx%256;
      RN8302_WriteReg(GPA,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GPx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GPx%256;
      RN8302_WriteReg(GPB,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_GPx/256;
      regbuf = StDef_RN8302Para_Reg.Cst_GPx%256;
      RN8302_WriteReg(GPC,regbuf,2);
      //x相有功分段相位校正
      regbuf = StDef_RN8302Para_Reg.Cst_Px_PHSL/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Px_PHSL%256;
      RN8302_WriteReg(PA_PHS,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_Px_PHSL/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Px_PHSL%256;
      RN8302_WriteReg(PB_PHS,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_Px_PHSL/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Px_PHSL%256;
      RN8302_WriteReg(PC_PHS,regbuf,2);
      //x相无功分段相位校正
      regbuf = StDef_RN8302Para_Reg.Cst_Qx_PHSL/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Qx_PHSL%256;
      RN8302_WriteReg(QA_PHS,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_Qx_PHSL/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Qx_PHSL%256;
      RN8302_WriteReg(QB_PHS,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_Qx_PHSL/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Qx_PHSL%256;
      RN8302_WriteReg(QC_PHS,regbuf,2);

      //x相无功功率增益
//      RN8302_WriteReg(GQA,(uint8_t*)&Dl645FirmPara.PGain,2);
//      RN8302_WriteReg(GQB,(uint8_t*)&Dl645FirmPara.PGain,2);
//      RN8302_WriteReg(GQC,(uint8_t*)&Dl645FirmPara.PGain,2);
      //x相视在功率增益
//      RN8302_WriteReg(GSA,(uint8_t*)&Dl645FirmPara.PGain,2);
//      RN8302_WriteReg(GSB,(uint8_t*)&Dl645FirmPara.PGain,2);
//      RN8302_WriteReg(GSC,(uint8_t*)&Dl645FirmPara.PGain,2);
      //x相有功功率offset
//      RN8302_WriteReg(PA_OS,(uint8_t*)&Dl645FirmPara.UI_Offset,2);
//      RN8302_WriteReg(PB_OS,(uint8_t*)&Dl645FirmPara.UI_Offset,2);
//      RN8302_WriteReg(PC_OS,(uint8_t*)&Dl645FirmPara.UI_Offset,2);
                //电流offset
      regbuf = StDef_RN8302Para_Reg.Cst_Ix_OS/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Ix_OS%256;
      RN8302_WriteReg(IA_OS,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_Ix_OS/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Ix_OS%256;
      RN8302_WriteReg(IB_OS,regbuf,2);
      regbuf = StDef_RN8302Para_Reg.Cst_Ix_OS/256;
      regbuf = StDef_RN8302Para_Reg.Cst_Ix_OS%256;
      RN8302_WriteReg(IC_OS,regbuf,2);
               
      //有功视在启动电流阈值
      regbuf = 0x02;
      regbuf = 0x36;
      RN8302_WriteReg(IStart_PS,regbuf,2);
      //无功视在启动电流阈值
      regbuf = 0x02;
      regbuf = 0x36;
      RN8302_WriteReg(IStart_Q,regbuf,2);
      //无功视在启动电流阈值
      regbuf = 0x04;
      regbuf = 0x00;
      RN8302_WriteReg(LostVoltT,regbuf,2);
      //无功视在启动电流阈值
      regbuf = 0x00;
      regbuf = 0x2C;
      RN8302_WriteReg(ZXOT,regbuf,2);

      //CF管脚配置
      regbuf = 0x04;
      regbuf = 0x77;
      regbuf = 0x10;
      RN8302_WriteReg(CFCFG,regbuf,3);
      //计量单元配置寄存器
      regbuf = 0x40;
      regbuf = 0x00;
      regbuf = 0x00;
      RN8302_WriteReg(EMUCFG,regbuf,3);
      //写缓存
      regbuf = 0x10;
      RN8302_WriteReg(WSAVECON,regbuf,1);
      //三相四线
      regbuf = 0x00;
      RN8302_WriteReg(MODESEL,regbuf,1);
      //计量控制位
      regbuf = 0x77;regbuf = 0x77;regbuf = 0x77;
      RN8302_WriteReg(EMUCON,regbuf,3);
      //写保护
      regbuf = 0xDC;
      RN8302_WriteReg(WREN,regbuf,1);
    }

        return status;
}

3---------------------------------------RN8302 校表部分-------------------------------------------------------------------------
(1)校表主要流程,详细流程可以参照用户手册


(2)RN8302校表初始化,这块参照手册,将RN8302的值设置成默认值
/********************************************************
功能描述:   RN8302校表初始化
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期    :
********************************************************/
uint8_t RN8302_CalibrateInit(void)
{
    uint8_t regbuf;
    uint8_t status = 1;

    if(RN8302_ReadReg(0x018F,regbuf,3) == 0){
      if((regbuf==0x83)&&(regbuf==0x02)&&(regbuf==0x00)){
            status = 0;
      }
      else{
            status = 1;
      }
    }
    else{
      status = 1;
    }

    //deviceID读取成功
    if(status == 0){
      //写使能
      regbuf = 0xE5;
      RN8302_WriteReg(WREN,regbuf,1);
      //切换到EMM模式
      regbuf = 0xA2;
      RN8302_WriteReg(WMSW,regbuf,1);
      //复位
      regbuf = 0xFA;
      RN8302_WriteReg(SOFTRST,regbuf,1);
      TicksDelayMs(20);
      //写使能
      regbuf = 0xE5;
      RN8302_WriteReg(WREN,regbuf,1);
      //切换到EMM模式
      regbuf = 0xA2;
      RN8302_WriteReg(WMSW,regbuf,1);
      //写HFCONST1
      regbuf = 0x2E;
      regbuf = 0xA1;
      RN8302_WriteReg(HFCONST1,regbuf,2);
                m_memset(regbuf,0,2);
                RN8302_ReadReg(HFCONST1,regbuf,2);
      //写电压增益
      StDef_RN8302Para_Reg.Cst_GSUx = 0;
      StDef_RN8302Para_Reg.Cst_GSUx = 0;
      StDef_RN8302Para_Reg.Cst_GSUx = 0;
      RN8302_WriteReg(GSUA,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSUx,2);
      RN8302_WriteReg(GSUB,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSUx,2);
      RN8302_WriteReg(GSUC,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSUx,2);
      //写电流增益
      StDef_RN8302Para_Reg.Cst_GSIx = 0;
      StDef_RN8302Para_Reg.Cst_GSIx = 0;
      StDef_RN8302Para_Reg.Cst_GSIx = 0;
      StDef_RN8302Para_Reg.Cst_GSIx = 0;
      RN8302_WriteReg(GSIA,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSIx,2);
      RN8302_WriteReg(GSIB,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSIx,2);
      RN8302_WriteReg(GSIC,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSIx,2);
      RN8302_WriteReg(GSIN,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GSIx,2);
      //x相有功功率增益
      StDef_RN8302Para_Reg.Cst_GPx = 0;
      StDef_RN8302Para_Reg.Cst_GPx = 0;
      StDef_RN8302Para_Reg.Cst_GPx = 0;
      RN8302_WriteReg(GPA,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GPx,2);
      RN8302_WriteReg(GPB,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GPx,2);
      RN8302_WriteReg(GPC,(uint8_t*)&StDef_RN8302Para_Reg.Cst_GPx,2);
      //x相有功分段相位校正
      StDef_RN8302Para_Reg.Cst_Px_PHSL = 0;
      StDef_RN8302Para_Reg.Cst_Px_PHSL = 0;
      StDef_RN8302Para_Reg.Cst_Px_PHSL = 0;
      RN8302_WriteReg(PA_PHS,(uint8_t*)&StDef_RN8302Para_Reg.Cst_Px_PHSL,2);
      RN8302_WriteReg(PB_PHS,(uint8_t*)&StDef_RN8302Para_Reg.Cst_Px_PHSL,2);
      RN8302_WriteReg(PC_PHS,(uint8_t*)&StDef_RN8302Para_Reg.Cst_Px_PHSL,2);
      //x相无功分段相位校正
      StDef_RN8302Para_Reg.Cst_Qx_PHSL = 0;
      StDef_RN8302Para_Reg.Cst_Qx_PHSL = 0;
      StDef_RN8302Para_Reg.Cst_Qx_PHSL = 0;
      RN8302_WriteReg(QA_PHS,(uint8_t*)&StDef_RN8302Para_Reg.Cst_Qx_PHSL,2);
      RN8302_WriteReg(QB_PHS,(uint8_t*)&StDef_RN8302Para_Reg.Cst_Qx_PHSL,2);
      RN8302_WriteReg(QC_PHS,(uint8_t*)&StDef_RN8302Para_Reg.Cst_Qx_PHSL,2);
                //电流offset
      regbuf = 0;
      regbuf = 0;
      RN8302_WriteReg(IA_OS,regbuf,2);
      regbuf = 0;
      regbuf = 0;
      RN8302_WriteReg(IB_OS,regbuf,2);
      regbuf = 0;
      regbuf = 0;
      RN8302_WriteReg(IC_OS,regbuf,2);
      //有功视在启动电流阈值
      regbuf = 0x02;
      regbuf = 0x36;
      RN8302_WriteReg(IStart_PS,regbuf,2);
      //无功视在启动电流阈值
      regbuf = 0x02;
      regbuf = 0x36;
      RN8302_WriteReg(IStart_Q,regbuf,2);
      //无功视在启动电流阈值
      regbuf = 0x04;
      regbuf = 0x00;
      RN8302_WriteReg(LostVoltT,regbuf,2);
      //无功视在启动电流阈值
      regbuf = 0x00;
      regbuf = 0x2C;
      RN8302_WriteReg(ZXOT,regbuf,2);
      //CF管脚配置
      regbuf = 0x04;
      regbuf = 0x32;
      regbuf = 0x10;
      RN8302_WriteReg(CFCFG,regbuf,3);
      //计量单元配置寄存器
      regbuf = 0x40;
      regbuf = 0x00;
      regbuf = 0x00;
      RN8302_WriteReg(EMUCFG,regbuf,3);
                m_memset(regbuf,0,3);
                RN8302_ReadReg(EMUCFG,regbuf,3);
      //计量控制位
      regbuf = 0x00;regbuf = 0x00;regbuf = 0x77;
      RN8302_WriteReg(EMUCON,regbuf,3);
      //校表时不要写保护
      //regbuf = 0xDC;
      //RN8302_WriteReg(WREN,regbuf,1);
    }

    return status;
}

(3)RN8302校表,电压、电流增益校准(校表台设置3相电压设置成220V,3相电流设置成5A)
/********************************************************
功能描述:   功率法校正电压增益
参数说明:   vol:扩大100倍
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期    :
********************************************************/
uint16_t RN8302_CalibrateUGain(uint16_t vol,uint8_t phase)
{
    uint8_t regbuf;
    const uint16_t regURMS[]={0x0007,0x0008,0x0009};
    const uint16_t regGUSx[]={GSUA,GSUB,GSUC};
    float err=0;
    uint16_t uGain;
        int32_t data;

    if(RN8302_ReadReg(regURMS,regbuf,4)==0){
                data = BufToU32(regbuf);
      err = (data-44000000)*1.0/44000000;
      err = -err/(1+err);
      if(err > 0){
            uGain = (uint16_t)(err*32768);
      }
      else{
            uGain = (uint16_t)(err*32768+65536);
      }
                //写使能
      regbuf = 0xE5;
      RN8302_WriteReg(WREN,regbuf,1);
      regbuf = uGain/256;regbuf = uGain%256;
      RN8302_WriteReg(regGUSx,regbuf,2);
                m_memset(regbuf,0x00,2);
                RN8302_ReadReg(regGUSx,regbuf,2);
      StDef_RN8302Para_Reg.Cst_GSUx = uGain;
    }

    return uGain;
}
/********************************************************
功能描述:   功率法校准电流
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期    :
********************************************************/
uint16_t RN8302_CalibrateIGain(uint16_t cur,uint8_t phase)
{
    uint8_t regbuf;
    const uint16_t regIRMS[]={0x000B,0x000C,0x000D};
    const uint16_t regGISx[]={GSIA,GSIB,GSIC};
    float err=0;
    uint16_t iGain;
    int32_t data;

    if(RN8302_ReadReg(regIRMS,regbuf,4)==0){
      data = BufToU32(regbuf);
      err = (data-3500000)*1.0/3500000;
      err = -err/(1+err);
      if(err > 0){
            iGain = (uint16_t)(err*32768);
      }
      else{
            iGain = (uint16_t)(err*32768+65536);
      }
      //写使能
      regbuf = 0xE5;
      RN8302_WriteReg(WREN,regbuf,1);
      regbuf = iGain/256;regbuf = iGain%256;
      RN8302_WriteReg(regGISx,regbuf,2);
      m_memset(regbuf,0x00,2);
      RN8302_ReadReg(regGISx,regbuf,2);
      StDef_RN8302Para_Reg.Cst_GSIx = iGain;
    }

    return iGain;
}
(4)RN8302校表,功率因素在1.0情况下可以不校准,只需通过校表台查看一下误差,误差较大的,再进行校准;正常情况下,电压、电流校准后,1.0无需校准
(5)RN8302校表,0.5L,A相校准,(校表台设置A相电压设置成220V,A相电流设置成5A,功率因素0.5L)
(6)RN8302校表,0.5L,B相校准,(校表台设置B相电压设置成220V,B相电流设置成5A,功率因素0.5L)
(7)RN8302校表,0.5L,C相校准,(校表台设置C相电压设置成220V,C相电流设置成5A,功率因素0.5L)
/********************************************************
功能描述:   功率法校准 Un Ib 0.5增益
参数说明:   err扩大1000倍 xx.xxx
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期    :
********************************************************/
uint16_t RN8302_CalibratePx_PHSL(uint8_t phase)
{
    uint8_t regbuf,i;
    uint32_t regtemp,regtotal=0;
        float err = 0;
    const uint16_t regGPx[]={PA_PHS,PB_PHS,PC_PHS};
    const uint16_t regGQx[]={QA_PHS,QB_PHS,QC_PHS};
    const uint16_t regArry[]={0x0014,0x0015,0x0016};
    uint16_t pGain;
        uint32_t data;

    for(i=0;i<5;i++){
      if(RN8302_ReadReg(regArry,regbuf,4)==0){
            regtemp = BufToU32(regbuf);
            regtotal += regtemp;
      }
      TicksDelayMs(400);
    }
    data = regtotal / 5;
    err = (data-9179115)*1.0/9179115;
    err = -err/(sqrt(3));
    if(err > 0){
      pGain = (uint16_t)(err*32768);
    }
    else{
      pGain = (uint16_t)(err*32768+65536);
    }
    //写使能
    regbuf = 0xE5;
    RN8302_WriteReg(WREN,regbuf,1);
    regbuf = pGain/256;regbuf = pGain%256;
    RN8302_WriteReg(regGPx,regbuf,2);
    RN8302_WriteReg(regGQx,regbuf,2);
    StDef_RN8302Para_Reg.Cst_Px_PHSL = pGain;
    StDef_RN8302Para_Reg.Cst_Qx_PHSL = pGain;

    return pGain;
}
(8)RN8302校表,电流offset校准,(校表台设置三相相电压设置成220V,三相电流设置成0A)
/********************************************************
功能描述:   校准电流偏置
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期    :
********************************************************/
uint8_t RN8302_CalibrateCurrentOffset(uint8_t phase)
{
    uint8_t regbuf;
    uint32_t regtemp,regtotal=0;
    const uint16_t regArry[]={0x000B,0x000C,0x000D};
    const uint16_t regIx_OS[]={IA_OS,IB_OS,IC_OS};
    uint8_t i = 0;
    uint16_t temp;

    for(i=0;i<12;i++)
    {
      if(RN8302_ReadReg(regArry,regbuf,4)==0){
            regtemp = (regbuf<<24)+(regbuf<<16)+\
                  (regbuf<<8)+(regbuf);
      }
      regtotal += regtemp;
      TicksDelayMs(300);
    }
    regtotal /= 12;
    regtotal = regtotal * regtotal;
    //求反码
    regtotal = ~regtotal;
    temp = (regtotal / 0x4000)&0xFFFF;
    //符号位
    if(regtotal & 0x80000000)
      temp |= 0x8000;
    //写使能
    regbuf = 0xE5;
    RN8302_WriteReg(WREN,regbuf,1);
    regbuf = temp/256;regbuf = temp%256;
    RN8302_WriteReg(regIx_OS,regbuf,2);
    StDef_RN8302Para_Reg.Cst_Ix_OS = temp;

    return 0;
}
(9)RN8302校表,电量清零
RN8302累计电量采用的是读后清零方式,所以累计电量是存在eeprom中的,只需要将eeprom中数据清空就可以,不用对RN8302进行操作

Baldwin 发表于 2018-8-24 14:11:17

本帖最后由 Baldwin 于 2018-8-24 14:13 编辑


上图按照手册把HFConst寄存器换算方式列了一下,详细说明参照用户手册64页(注意:校准方式采用功率校准,不是误差校准法)
在上文中提到的RN8302初始化时HFCONST1这个寄存器需要设置成这个值

RN8302用户手册

Baldwin 发表于 2018-8-22 19:17:05

编辑占位

powermeter 发表于 2018-8-22 20:19:59

mark顶你

HJJ2008 发表于 2018-8-22 22:19:16

楼主好人;

lrzxc 发表于 2018-8-22 23:37:08

有相同应用的可以参考了。谢谢分享。

pchf005 发表于 2018-8-23 00:21:53

楼主分享感谢你

LM1876 发表于 2018-8-23 01:04:40

多谢,正好用得上

yangbo18416 发表于 2018-8-23 09:04:35

多谢,楼主介绍的还比较详细,收藏备用

agency 发表于 2018-8-23 09:32:09

{:lol:}楼主好人

RN8302初始化 uint8_t RN8302_Init(void)和 RN8302校表初始化 uint8_t RN8302_CalibrateInit(void)可以合并一下,在RN8302_CalibrateInit中对StDef_RN8302Para_Reg 赋初始化值写eeprom,然后调用 RN8302_Init
StDef_RN8302Para_Reg 校表参数保存到eeprom中时,建议计算CRC校验,并且至少有一个备份;上电从eeprom恢复数据时判断CRC,取正确的那份数据

shaozh_new 发表于 2018-8-23 10:39:26

非常详细的说明!

yanyanyan168 发表于 2018-8-23 20:30:38

多谢分享,收藏备用

Baldwin 发表于 2018-8-24 09:04:39

agency 发表于 2018-8-23 09:32
楼主好人

RN8302初始化 uint8_t RN8302_Init(void)和 RN8302校表初始化 uint8_t RN8302_CalibrateI ...

你好,校表数据是有crc16校验的,是放在非易失性存储那块做的

zhang0352505 发表于 2018-8-24 10:30:27

楼主不错,MARK一下,以防备用

teddeng 发表于 2018-8-24 17:22:06

顶一下,支持。

hongguan 发表于 2018-9-16 16:28:24

谢谢楼主分享!!!

makesoft 发表于 2018-9-16 18:37:28

mark下,备用

juncheng14 发表于 2018-9-16 20:12:30

手上有块rn8209d板,没有datasheet ,不知楼主有吗?有的话能否发个上来。

Baldwin 发表于 2018-9-17 14:08:59

juncheng14 发表于 2018-9-16 20:12
手上有块rn8209d板,没有datasheet ,不知楼主有吗?有的话能否发个上来。


fenglove 发表于 2018-9-17 14:24:58

感谢楼主,这个电流更新频率是多少呀

juncheng14 发表于 2018-9-17 14:30:12

Baldwin 发表于 2018-9-17 14:08


谢楼主,已经在论坛上找到了。

jiaoyi 发表于 2018-10-20 08:38:13

请兄台推荐个校表台,有型号和厂家最好,谢谢

Baldwin 发表于 2018-10-20 09:35:49

fenglove 发表于 2018-9-17 14:24
感谢楼主,这个电流更新频率是多少呀

3.495Hz或13.982Hz

Baldwin 发表于 2018-10-20 09:37:58

jiaoyi 发表于 2018-10-20 08:38
请兄台推荐个校表台,有型号和厂家最好,谢谢

你好,校表台一台是相对来说比较贵,大概需要20~30万,你是做什么产品的,如果量不是很大,可以找相应厂家来帮你弄

晚枫 发表于 2018-11-1 17:22:45

不错,学习一下。

yaya001 发表于 2018-11-1 21:51:16

请问 为什么
“光耦隔离,无法直接用硬件SPI,只能用软件SPI”

谢谢

Baldwin 发表于 2018-11-2 10:49:11

yaya001 发表于 2018-11-1 21:51
请问 为什么
“光耦隔离,无法直接用硬件SPI,只能用软件SPI”



我用的普通的光耦,通信速度比较慢,硬件SPI的速度都比较快,所以只用了软件spi

yaya001 发表于 2018-11-2 11:21:16

Baldwin 发表于 2018-11-2 10:49
我用的普通的光耦,通信速度比较慢,硬件SPI的速度都比较快,所以只用了软件spi ...

速度原因,了解了多谢

twjccmx 发表于 2019-1-5 22:52:38

搞得不错,好好学习

liangshanguang 发表于 2019-1-18 10:22:16

marker 一下,过后再看 RN8302

zhenke 发表于 2019-1-18 10:29:27

好资料,谢谢分享!

shiruquaan23 发表于 2019-2-19 13:53:55

好资料感谢楼主的

qq915412051 发表于 2019-2-19 16:15:41

感谢分享!

开始 发表于 2019-2-20 09:01:48

谢谢 收藏的 以后用

windrarara 发表于 2019-2-23 00:14:31

为毛要用光耦隔离呢, 直接通信不行吗……

zhangxiaojin 发表于 2019-2-23 14:34:24

必须点赞

Baldwin 发表于 2019-2-23 19:43:47

windrarara 发表于 2019-2-23 00:14
为毛要用光耦隔离呢, 直接通信不行吗……

电压是直连的,不隔离设备就是带电的

windrarara 发表于 2019-2-25 09:26:46

Baldwin 发表于 2019-2-23 19:43
电压是直连的,不隔离设备就是带电的

哦, 我用PT了....

zhangguanqun 发表于 2019-3-20 14:09:10

原理图能否传一份上来啊

panda1985 发表于 2019-3-20 16:38:21

我想问一下   使用RN8209D必须要先校表吗?我就想检测电压 电流 功率需不需要校表?

diego2003 发表于 2019-3-20 17:28:19

楼主不错,MARK一下,以防备用

mon51 发表于 2019-3-20 21:13:32

正在做RN7302,看看。

mon51 发表于 2019-3-20 21:39:43

请问楼主:1、可以把H文件贴出来吗?2、BufToU32()这个函数可以看看吗? 3、有读取电压,电流有效值的代码吗?主要想看看如何转换成实际值。

蛋定 发表于 2019-3-20 23:01:56

将要用到电量计量芯片,做个记号

bigharpoon 发表于 2019-3-20 23:47:42

标记标记{:victory:}

magiczero 发表于 2019-3-20 23:53:29

谢谢分享{:smile:}

Baldwin 发表于 2019-3-21 12:42:11

zhangguanqun 发表于 2019-3-20 14:09
原理图能否传一份上来啊

原理图已上传

Baldwin 发表于 2019-3-21 12:43:37

mon51 发表于 2019-3-20 21:39
请问楼主:1、可以把H文件贴出来吗?2、BufToU32()这个函数可以看看吗? 3、有读取电压,电流有效值的代码吗 ...

uint8_t RN8302_ReadCurrentReg(uint8_t phase,uint8_t *regdata)
{
    uint8_t regbuf;
    if(phase == 0){
      if(RN8302_ReadReg(0x000B,regbuf,4)==0){
            m_memcpy((uint8_t*)regdata,regbuf,4);
      }
    }
    else if(phase == 1){
      if(RN8302_ReadReg(0x000C,regbuf,4)==0){
            m_memcpy((uint8_t*)regdata,regbuf,4);
      }
    }
    else if(phase == 2){
      if(RN8302_ReadReg(0x000D,regbuf,4)==0){
            m_memcpy((uint8_t*)regdata,regbuf,4);
      }
    }
       
        return 0;
}

uint8_t RN8302_ReadVoltage(uint8_t phase)
{
    uint8_t regbuf;
        uint32_t regtemp = 0;
        const uint16_t regArry[]={0x0007,0x0008,0x0009};
       
        if(RN8302_ReadReg(regArry,regbuf,4)==0)
        {            
                regtemp = (regbuf<<24)+(regbuf<<16)+\
                                       (regbuf<<8)+(regbuf);
      #ifdef RN8302_USING_PowerCorrection
      Voltage = (uint16_t)(regtemp*10.0/ (44000000/220)); //扩大10
      #endif

      #ifdef RN8302_USING_ErrCorrection
      Voltage = (uint16_t)(regtemp*10.0*Kv); //扩大10
      #endif

        }
       
        return 0;
}
这是电压、电流的换算,使用这个宏定义RN8302_USING_PowerCorrection
BUF2int这个函数就是将数组中的4个字节换算成uint32_t

Baldwin 发表于 2019-3-21 12:46:30

panda1985 发表于 2019-3-20 16:38
我想问一下   使用RN8209D必须要先校表吗?我就想检测电压 电流 功率需不需要校表? ...

你好,RN8209计量芯片需要先校表的;如果对要求不高,你可以串一个电表来进行校表,通过电表测量出的电压、电流来换算你自己的值

mon51 发表于 2019-3-22 18:40:29

本帖最后由 mon51 于 2019-3-22 18:44 编辑

Baldwin 发表于 2019-3-21 12:43
这是电压、电流的换算,使用这个宏定义RN8302_USING_PowerCorrection
BUF2int这个函数就是将数组中的4个 ...

请问:      Voltage = (uint16_t)(regtemp*10.0/ (44000000/220)); //扩大10   44000000/220这个系数是如何确定的?
               Voltage = (uint16_t)(regtemp*10.0*Kv); //扩大10         Kv 这个参数是如何确定的?

zhangguanqun 发表于 2019-3-29 22:04:45

Baldwin 发表于 2019-3-21 12:42
原理图已上传

源代码也上传下把,这样就完整了

Baldwin 发表于 2019-3-30 10:19:23

mon51 发表于 2019-3-22 18:40
请问:      Voltage = (uint16_t)(regtemp*10.0/ (44000000/220)); //扩大10   44000000/220这个系 ...

用户手册里功率校表法那章有讲的,手册讲的比较详细

pengtaoABC 发表于 2019-3-31 16:28:32

推荐 CS5463 电表计量芯片

pengtaoABC 发表于 2019-3-31 16:29:21


推荐 CS5463 电表计量芯片







CS5463

CS5464

zhongsandaoren 发表于 2019-3-31 16:36:42

谢谢分享

梨花 发表于 2019-3-31 17:57:25

谢谢分享~~~

whitekang82 发表于 2019-4-22 14:12:31

这个校准的话是不是需要校表台才能准确校准?

Baldwin 发表于 2019-4-22 17:28:21

whitekang82 发表于 2019-4-22 14:12
这个校准的话是不是需要校表台才能准确校准?

要看精度要求的,有表位数量少的,便宜的校表台,2~3万左右

rogerllg 发表于 2019-4-24 08:39:49

楼主的资料比较详细,点赞~

zhangyg0123456 发表于 2019-5-13 16:02:51

多谢楼主分享,点赞~

retention 发表于 2019-6-2 11:48:02

LZ有空解释一下什么是变比参数吗

Baldwin 发表于 2019-6-3 10:23:50

retention 发表于 2019-6-2 11:48
LZ有空解释一下什么是变比参数吗

变比是互感器的主要参数,比如1000:1,假设输入电压220V,通过互感器后220/1000=0.22V,互感器输出就是0.22V

liangshanguang 发表于 2019-6-14 17:23:10

Baldwin 发表于 2019-6-3 10:23
变比是互感器的主要参数,比如1000:1,假设输入电压220V,通过互感器后220/1000=0.22V,互感器输出就是0.2 ...

这里面这个读操作没有看懂是什么意思啊,

Baldwin 发表于 2019-6-15 13:44:26

liangshanguang 发表于 2019-6-14 17:23
这里面这个读操作没有看懂是什么意思啊,

这是当时会为了做验证的,回读一下,没特殊含义,可以去掉

edaworld 发表于 2019-6-16 20:06:59

mark,计量

frankvos 发表于 2019-8-20 22:29:22

感谢楼主,正用到这个芯片

shizt 发表于 2019-8-21 16:37:04

感谢楼主分享经验!

fzkqi 发表于 2019-8-31 16:42:30

楼主能推荐一个价格便宜的校表仪器吗?用在非计量行业产品。

yanyanyan168 发表于 2019-8-31 17:17:50

多谢分享,RN8302计量芯片

Berger 发表于 2019-10-24 12:53:31

多谢分享

zjk 发表于 2019-10-24 13:24:35

谢谢分享

mpxkali 发表于 2019-12-18 10:17:46

谢谢分享,顶一下!!!

tangpeng 发表于 2019-12-21 21:26:58

留着备用

粤H广宁 发表于 2020-4-15 08:58:08

SPI接口一定要隔离吗?电压等级不一样吗?

felix_tao 发表于 2020-7-6 16:35:10

挺全的资料,正在研究当中。。。

felix_tao 发表于 2020-7-9 07:58:30

楼主你好,用功率法校准电压,电流增益后,计算出来电圧,电流,那么有功功率,功率因数应该怎么计算?

heqibin 发表于 2020-7-22 10:50:37

有个问题请教lz,你电压寄存器标准值取44000000,理论/标准=0.698,不符合手册说的0.8< <1.2啊,这里怎么考虑的?

mypear 发表于 2020-7-23 09:06:45

有数字隔离芯片,同光耦价格长不多或者更便宜。

hdxet 发表于 2020-7-23 10:48:22

好资料,谢谢分享

2nd 发表于 2020-7-27 11:09:36

楼主请教,RN8302B电流空载噪声有多少?你启用OFFSET校正了吗?

deity2020 发表于 2020-8-28 10:58:27

刚好研究这个片子,多谢楼主分享~~~

MyOS 发表于 2020-8-28 14:17:38

这是个非常好的东西

Baldwin 发表于 2020-8-31 17:12:28

2nd 发表于 2020-7-27 11:09
楼主请教,RN8302B电流空载噪声有多少?你启用OFFSET校正了吗?

启用offset了,空载噪声和板子有关系

lihaimeng@163 发表于 2020-9-12 16:12:22

切换到三相三线,UCA 是通过UAB UBC计算出来的吗???

livelei 发表于 2020-11-13 14:47:13

万分感谢楼主!另外有没有PCB分享一下啊?

chw_caan 发表于 2021-11-11 15:50:53

请问楼主,电压偏置UA_OS不需要设置了吗?

江风VS山月 发表于 2022-5-11 16:12:14

这个帖值得收藏!

deven_zheng 发表于 2023-5-30 11:40:50

楼主,RN8302读取电量值2.2kwh和三相标准源(220V/5A)值3.3kwh,有差别是什么问题?

hz_luping 发表于 2023-5-30 14:25:50

记录一下,最近可能要用类似芯片

AWEN2000 发表于 2023-5-30 18:07:18

deven_zheng 发表于 2023-5-30 11:40
楼主,RN8302读取电量值2.2kwh和三相标准源(220V/5A)值3.3kwh,有差别是什么问题? ...
(引用自88楼)

功率标准值算的有问题吧。
根据手册上的方法算就行了
页: [1]
查看完整版本: RN8302计量芯片使用经验分享