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:13 编辑
上图按照手册把HFConst寄存器换算方式列了一下,详细说明参照用户手册64页(注意:校准方式采用功率校准,不是误差校准法)
在上文中提到的RN8302初始化时HFCONST1这个寄存器需要设置成这个值
RN8302用户手册
编辑占位 mark顶你 楼主好人; 有相同应用的可以参考了。谢谢分享。 楼主分享感谢你 多谢,正好用得上 多谢,楼主介绍的还比较详细,收藏备用 {: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,取正确的那份数据 非常详细的说明! 多谢分享,收藏备用 agency 发表于 2018-8-23 09:32
楼主好人
RN8302初始化 uint8_t RN8302_Init(void)和 RN8302校表初始化 uint8_t RN8302_CalibrateI ...
你好,校表数据是有crc16校验的,是放在非易失性存储那块做的
楼主不错,MARK一下,以防备用 顶一下,支持。 谢谢楼主分享!!! mark下,备用 手上有块rn8209d板,没有datasheet ,不知楼主有吗?有的话能否发个上来。 juncheng14 发表于 2018-9-16 20:12
手上有块rn8209d板,没有datasheet ,不知楼主有吗?有的话能否发个上来。
感谢楼主,这个电流更新频率是多少呀
Baldwin 发表于 2018-9-17 14:08
谢楼主,已经在论坛上找到了。 请兄台推荐个校表台,有型号和厂家最好,谢谢 fenglove 发表于 2018-9-17 14:24
感谢楼主,这个电流更新频率是多少呀
3.495Hz或13.982Hz jiaoyi 发表于 2018-10-20 08:38
请兄台推荐个校表台,有型号和厂家最好,谢谢
你好,校表台一台是相对来说比较贵,大概需要20~30万,你是做什么产品的,如果量不是很大,可以找相应厂家来帮你弄 不错,学习一下。 请问 为什么
“光耦隔离,无法直接用硬件SPI,只能用软件SPI”
谢谢 yaya001 发表于 2018-11-1 21:51
请问 为什么
“光耦隔离,无法直接用硬件SPI,只能用软件SPI”
我用的普通的光耦,通信速度比较慢,硬件SPI的速度都比较快,所以只用了软件spi Baldwin 发表于 2018-11-2 10:49
我用的普通的光耦,通信速度比较慢,硬件SPI的速度都比较快,所以只用了软件spi ...
速度原因,了解了多谢 搞得不错,好好学习 marker 一下,过后再看 RN8302
好资料,谢谢分享! 好资料感谢楼主的 感谢分享! 谢谢 收藏的 以后用 为毛要用光耦隔离呢, 直接通信不行吗…… 必须点赞 windrarara 发表于 2019-2-23 00:14
为毛要用光耦隔离呢, 直接通信不行吗……
电压是直连的,不隔离设备就是带电的 Baldwin 发表于 2019-2-23 19:43
电压是直连的,不隔离设备就是带电的
哦, 我用PT了.... 原理图能否传一份上来啊 我想问一下 使用RN8209D必须要先校表吗?我就想检测电压 电流 功率需不需要校表? 楼主不错,MARK一下,以防备用 正在做RN7302,看看。 请问楼主:1、可以把H文件贴出来吗?2、BufToU32()这个函数可以看看吗? 3、有读取电压,电流有效值的代码吗?主要想看看如何转换成实际值。 将要用到电量计量芯片,做个记号 标记标记{:victory:} 谢谢分享{:smile:} zhangguanqun 发表于 2019-3-20 14:09
原理图能否传一份上来啊
原理图已上传 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 panda1985 发表于 2019-3-20 16:38
我想问一下 使用RN8209D必须要先校表吗?我就想检测电压 电流 功率需不需要校表? ...
你好,RN8209计量芯片需要先校表的;如果对要求不高,你可以串一个电表来进行校表,通过电表测量出的电压、电流来换算你自己的值 本帖最后由 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 这个参数是如何确定的? Baldwin 发表于 2019-3-21 12:42
原理图已上传
源代码也上传下把,这样就完整了 mon51 发表于 2019-3-22 18:40
请问: Voltage = (uint16_t)(regtemp*10.0/ (44000000/220)); //扩大10 44000000/220这个系 ...
用户手册里功率校表法那章有讲的,手册讲的比较详细 推荐 CS5463 电表计量芯片
推荐 CS5463 电表计量芯片
CS5463
CS5464 谢谢分享 谢谢分享~~~ 这个校准的话是不是需要校表台才能准确校准? whitekang82 发表于 2019-4-22 14:12
这个校准的话是不是需要校表台才能准确校准?
要看精度要求的,有表位数量少的,便宜的校表台,2~3万左右 楼主的资料比较详细,点赞~ 多谢楼主分享,点赞~ LZ有空解释一下什么是变比参数吗 retention 发表于 2019-6-2 11:48
LZ有空解释一下什么是变比参数吗
变比是互感器的主要参数,比如1000:1,假设输入电压220V,通过互感器后220/1000=0.22V,互感器输出就是0.22V Baldwin 发表于 2019-6-3 10:23
变比是互感器的主要参数,比如1000:1,假设输入电压220V,通过互感器后220/1000=0.22V,互感器输出就是0.2 ...
这里面这个读操作没有看懂是什么意思啊, liangshanguang 发表于 2019-6-14 17:23
这里面这个读操作没有看懂是什么意思啊,
这是当时会为了做验证的,回读一下,没特殊含义,可以去掉 mark,计量 感谢楼主,正用到这个芯片 感谢楼主分享经验! 楼主能推荐一个价格便宜的校表仪器吗?用在非计量行业产品。 多谢分享,RN8302计量芯片 多谢分享 谢谢分享 谢谢分享,顶一下!!! 留着备用 SPI接口一定要隔离吗?电压等级不一样吗? 挺全的资料,正在研究当中。。。 楼主你好,用功率法校准电压,电流增益后,计算出来电圧,电流,那么有功功率,功率因数应该怎么计算? 有个问题请教lz,你电压寄存器标准值取44000000,理论/标准=0.698,不符合手册说的0.8< <1.2啊,这里怎么考虑的? 有数字隔离芯片,同光耦价格长不多或者更便宜。 好资料,谢谢分享 楼主请教,RN8302B电流空载噪声有多少?你启用OFFSET校正了吗? 刚好研究这个片子,多谢楼主分享~~~ 这是个非常好的东西 2nd 发表于 2020-7-27 11:09
楼主请教,RN8302B电流空载噪声有多少?你启用OFFSET校正了吗?
启用offset了,空载噪声和板子有关系 切换到三相三线,UCA 是通过UAB UBC计算出来的吗??? 万分感谢楼主!另外有没有PCB分享一下啊? 请问楼主,电压偏置UA_OS不需要设置了吗? 这个帖值得收藏! 楼主,RN8302读取电量值2.2kwh和三相标准源(220V/5A)值3.3kwh,有差别是什么问题? 记录一下,最近可能要用类似芯片 deven_zheng 发表于 2023-5-30 11:40
楼主,RN8302读取电量值2.2kwh和三相标准源(220V/5A)值3.3kwh,有差别是什么问题? ...
(引用自88楼)
功率标准值算的有问题吧。
根据手册上的方法算就行了
页:
[1]