CS5463校验方法
Posted zhuguangming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CS5463校验方法相关的知识,希望对你有一定的参考价值。
1:校验电压,电流偏移(交流,直流)
//偏移校正
void cs5463AcDcOffsetwrite(void)
{
uint8_t readBuffer[4];
uint32_t vulue=0;
emberAfCorePrintln("cs5463AcDcOffset satrt.......");
halcs5463Init();
Clear_DRDY();
sendCS5463CalCmd(CS5463_CMD_POWERUP_HALT);
Clear_DRDY();
sendCS5463CalCmd(CS5463_CMD_CALIBRATION_CURRENT_DC_OFFSET);
Wait_DRDY_High();
memset(readBuffer,0,4);
readCs5463Register(0,CS5463_CURRENTDCOFFSET_REG,readBuffer);
emberAfCorePrintln("CS5463_CURRENTDCOFFSET_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
vulue = INT8U_TO_INT32U(0, readBuffer[1], readBuffer[2], readBuffer[3]);
SetCs5463CalDataToFlash(vulue,CS5463_IDCOFF);
Clear_DRDY();
sendCS5463CalCmd(CS5463_CMD_CALIBRATION_VOLTAGE_DC_OFFSET);
Wait_DRDY_High();
memset(readBuffer,0,4);
readCs5463Register(0,CS5463_VOLTAGEDCOFFSET_REG,readBuffer);
emberAfCorePrintln("CS5463_VOLTAGEDCOFFSET_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
vulue = INT8U_TO_INT32U(0, readBuffer[1], readBuffer[2], readBuffer[3]);
SetCs5463CalDataToFlash(vulue,CS5463_VDCOFF);
Clear_DRDY();
sendCS5463CalCmd(CS5463_CMD_CALIBRATION_CURRENT_AC_OFFSET);
Wait_DRDY_High();
memset(readBuffer,0,4);
readCs5463Register(0,CS5463_IACOFF_REG,readBuffer);
emberAfCorePrintln("CS5463_IACOFF_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
vulue = INT8U_TO_INT32U(0, readBuffer[1], readBuffer[2], readBuffer[3]);
SetCs5463CalDataToFlash(vulue,CS5463_IACOFF);
Clear_DRDY();
sendCS5463CalCmd(CS5463_CMD_CALIBRATION_VOLTAGE_AC_OFFSET);
Wait_DRDY_High();
memset(readBuffer,0,4);
readCs5463Register(0,CS5463_VACOFF_REG,readBuffer);
emberAfCorePrintln("CS5463_VACOFF_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
vulue = INT8U_TO_INT32U(0, readBuffer[1], readBuffer[2], readBuffer[3]);
SetCs5463CalDataToFlash(vulue,CS5463_VACOFF);
sendCS5463CalCmd(CS5463_CMD_START_CONV_CONTINUOUS);
emberAfCorePrintln("cs5463AcDcOffset end.......");
}
//偏移读取
void cs5463AcDcOffsetread(void)
{
uint32_t Value=0;
#if 1
uint8_t readBuffer[4];
emberAfCorePrintln("cs5463AcDcOffsetread start*************");
readCs5463Register(0,CS5463_CURRENTDCOFFSET_REG,readBuffer);
emberAfCorePrintln("CS5463_CURRENTDCOFFSET_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
readCs5463Register(0,CS5463_VOLTAGEDCOFFSET_REG,readBuffer);
emberAfCorePrintln("CS5463_CURRENTDCOFFSET_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
readCs5463Register(0,CS5463_IACOFF_REG,readBuffer);
emberAfCorePrintln("CS5463_CURRENTDCOFFSET_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
readCs5463Register(0,CS5463_VACOFF_REG,readBuffer);
emberAfCorePrintln("CS5463_CURRENTDCOFFSET_REG: 0x%x,%x,%x,%x",readBuffer[0],readBuffer[1],readBuffer[2],readBuffer[3]);
#endif
Value= GetCs5463CalDataFromFlash(CS5463_IDCOFF);
emberAfCorePrintln("GetCs5463Vdcoffset: 0x%02x",Value>>16);
}
/********************************************
32位浮点数字转成二进制,
小数点后面的位数,由intNum来决定
************************************************/
uint32_t FloatToBinary(float value)
{
// (-1) s表示符号位,当s = 0,V为正数;当s = 1,V为负数。
// (2)M表示有效数字,大于等于1,小于2。
// (3)2^E表示指数位。
// 对于单精度 符号位 1 指数为8 有效数字 23
uint32_t P_value=0;
uint8_t num=0;
uint32_t reval=0,temp=0;
uint8_t sign =(value>=0)?0:1; //获取符号位
emberAfCorePrintln("sign:%d",sign);
value= fabs(value); //求绝对值
int Interger = floor(value); //获取整数部分
float frac = value - (float)Interger; //获取小数部分
/************************************************************
正数部分42.75;-42.75
sign:0
Interger:42
frac_h:0x1560
frac_l:0x0000
sign:1
Interger:42
frac_h:0x9560
frac_l:0x0000
********************************************************/
while (Interger)
{
if(Interger % 2)
{
temp |= (1<<num);
}
num++;
Interger /= 2;
}
temp <<=23;
reval=temp;
/************************************************************
分解小数部分----由于小部分,可能会出现分解不完全的情况,
并且float中仅有23位,所以仅仅循环23次
------但是对于仅有小数的部分,还要截断一部分,所以需要补充
********************************************************/
temp=0;
for(num=0;num<23;num++)
{
frac *=2;
if(frac>=1)
{
frac -=1;
temp |=(1<<(22-num));
}
if(frac==0)
{
break;
}
}
reval |=temp;
//符号位的处理
if(sign)
{
reval |=(1<<31); //负数
}
emberAfCorePrintln("frac_h:0x%02x",reval>>16);
emberAfCorePrintln("frac_l:0x%02x",reval&(0xffff));
return reval;
}
//清除数据就绪位
void Clear_DRDY()
{
uint8_t buf[4];
cs5463ReadReg(PAGE_0, CS5463_STATUS_REG, buf);
cs5463WriteReg(PAGE_0, CS5463_STATUS_REG, buf);
}
//等待数据就绪,转换好
void Wait_DRDY_High()
{
uint8_t readBuffer[4];
while(1)
{
halResetWatchdog();
cs5463ReadReg(PAGE_0, CS5463_STATUS_REG, readBuffer);
if(readBuffer[1] & 0x80) break; //??DRDY=1
}
}
2:校验电压,电流增益
2.1:电压增益:要带负载,输入电压电流
void cs5463GainVwrite(void)
{
uint8_t value = (uint8_t)emberUnsignedCommandArgument(0);
emberAfCorePrintln("Voltage:%d",value);
InitCalVlltage(1); //电压增益初始化
Wait_DRDY_High();
CalVoltageGain(value); //把表上读到的值,输入进去。(0-255V)1个字节
}
//电压,电流增益初始化函数
void InitCalVlltage(uint8_t VorI)
{
uint32_t config;
uint32_t Value;
// Dessert PWR_SEN_RESET pin and delay 10ms
GPIO_PinModeSet(PWR_SEN_RESET_PORT, PWR_SEN_RESET_PIN, gpioModePushPull, 1);
GPIO_PinOutClear(PWR_SEN_RESET_PORT, PWR_SEN_RESET_PIN);
halCommonDelayMilliseconds(10);
GPIO_PinOutSet(PWR_SEN_RESET_PORT, PWR_SEN_RESET_PIN); //复位5463
Value= GetCs5463CalDataFromFlash(CS5463_VACOFF);
cs5463WriteValue(PAGE_0, CS5463_VACOFF_REG, Value); //输入电压交流偏移
Value= GetCs5463CalDataFromFlash(CS5463_IACOFF);
cs5463WriteValue(PAGE_0, CS5463_IACOFF_REG, Value); //输入电流交流偏移
Value= GetCs5463CalDataFromFlash(CS5463_IDCOFF);
cs5463WriteValue(PAGE_0,
CS5463_CURRENTDCOFFSET_REG, //输入电流直流偏移
Value);
Value= GetCs5463CalDataFromFlash(CS5463_VDCOFF); //输入电压直流偏移
cs5463WriteValue(PAGE_0,
CS5463_VOLTAGEDCOFFSET_REG,
Value);
cs5463WriteValue(PAGE_0, CS5463_CYCLECOUNT_REG, 4000); //zgm 写入N周期数
if(VorI==0) //校准电流
{
cs5463WriteValue(PAGE_0, CS5463_CURRENTGAIN_REG, 0x00400000); //电流增益初始化为1,这个要校准的参数
Value= GetCs5463CalDataFromFlash(CS5463_VACGAIN);
cs5463WriteValue(PAGE_0, CS5463_VOLTAGEGAIN_REG, Value); //把校准过的电压增益写入
}
else //校准电压
{
cs5463WriteValue(PAGE_0, CS5463_VOLTAGEGAIN_REG, 0x00400000); //把电压增益初始化为1,这个要校准的参数
Value= GetCs5463CalDataFromFlash(CS5463_IACGAIN);
cs5463WriteValue(PAGE_0, CS5463_CURRENTGAIN_REG, Value);
}
cs5463WriteValue(PAGE_0, CS5463_MODE_REG, 0x00000030); //dakai hpf zgm 打开高频滤波
cs5463WriteValue(PAGE_1, CS5463_TEMP_OFFSET, TEMPERATURE_OFFSET_DEFAULT); //写入温度偏移
config = ((PC) | (IGAIN) | (EWA) | (IMODE) | (IINV) | (ICPU) | (CDIV)); //设置电流10X (176.8MV)
isCalibrating = false;
cs5463WriteValue(PAGE_0, CS5463_CONFIG_REG, config); //写入配置字
halCommonDelayMilliseconds(20);
cs5463WriteCommand(CS5463_CMD_START_CONV_CONTINUOUS); // start conversion 开启转换
Clear_DRDY(); //清除DRDY
}
//===========校准电压增益==========================Vgain=Vin/(MAX_VOLTAGE*VRMS)。========
//Vgain=Vin/(MAX_VOLTAGE*读取CS5463的有效电压值)
//Vgain =输入的电压220V,除以读出的电压值230V ,
//vgain=220/230=0.956
void CalVoltageGain(uint8_t value)
{
float vgain=0;
uint32_t vrms;
uint8_t readBuffer[WRITE_BUFFER_SIZE];
cs5463ReadReg(PAGE_0, CS5463_RMSVOLTAGE_REG, readBuffer);
vrms = INT8U_TO_INT32U(0, readBuffer[1], readBuffer[2], readBuffer[3]);
vrms = vrms >> 5;
vrms = vrms * MAX_VOLTAGE;
vrms = vrms >> 19;
emberAfCorePrintln("cs5463ReadReg: %d",vrms);
vgain=(float)value/vrms;
if(vgain>=4)
{
emberAfCorePrintln("Vgain>4, Fail");
return ;
}
vrms = FloatToBinary(vgain);
vrms >>=1;//因为增益只有22位小数,没23为小数 范围【0,4)
vrms &=0x00ffffff;
cs5463WriteValue(PAGE_0, CS5463_VOLTAGEGAIN_REG, vrms);
SetCs5463CalDataToFlash(vrms,CS5463_VACGAIN);
emberAfCorePrintln("CalVoltageGain, ok");
}
2.2:电流增益:要带负载,输入电压电流
void cs5463GainIwrite(void)
{
uint8_t value = (uint8_t)emberUnsignedCommandArgument(0);
emberAfCorePrintln("Current:%d",value);
InitCalVlltage(0);
Wait_DRDY_High();
CalCurrentGain(value);
}
//===========校准电流增益==================================
void CalCurrentGain(uint8_t value)
{
float cgain=0;
double fgain=0;
uint32_t crms;
uint8_t readBuffer[WRITE_BUFFER_SIZE];
cs5463ReadReg(PAGE_0, CS5463_RMSCURRENT_REG, readBuffer);
crms = INT8U_TO_INT32U(0, readBuffer[1], readBuffer[2], readBuffer[3]);
crms = crms >> 8;
crms = crms * 315; //3.157
crms = crms >> 16;
fgain =(double)crms /100.0;
cgain=(float)value/crms;
if(cgain>=4)
{
emberAfCorePrintln("cgain>4, cgain");
return ;
}
crms = FloatToBinary(cgain);
crms >>=1;//因为增益只有22位小数,没23为小数 范围【0,4)
crms &=0x00ffffff;
cs5463WriteValue(PAGE_0, CS5463_CURRENTGAIN_REG, crms);
SetCs5463CalDataToFlash(crms,CS5463_IACGAIN);
emberAfCorePrintln("CalCurrentGain, ok");
}
/***************************************
从FLSAH中读取数据
item: 表示读的是哪个数据
CS5463_VDCOFF 电压直流偏移
CS5463_IDCOFF 电流直流偏移
CS5463_VACOFF 电压交流偏移
CS5463_IACOFF 电流交流偏移
CS5463_IACGAIN 电流增益
CS5463_VACGAIN 电压增益
uint32_t 返回值
***************************************/
uint32_t GetCs5463CalDataFromFlash(uint32_t item)
{
uint32_t Value=0;
switch(item)
{
case CS5463_VDCOFF:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_VDCOFF);
break;
case CS5463_IDCOFF:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_IDCOFF);
break;
case CS5463_VACOFF:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_VACOFF);
break;
case CS5463_IACOFF:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_IACOFF);
break;
case CS5463_IACGAIN:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_IACGAIN);
break;
case CS5463_VACGAIN:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_VACGAIN);
break;
case CS5463_POWEROFF:
halCommonGetToken((uint32_t *)&Value, TOKEN_CS5463_POWEROFF);
break;
}
return Value;
}
/***************************************
从FLSAH中读取数据
item: 表示读的是哪个数据
CS5463_VDCOFF 电压直流偏移
CS5463_IDCOFF 电流直流偏移
CS5463_VACOFF 电压交流偏移
CS5463_IACOFF 电流交流偏移
CS5463_IACGAIN 电流增益
CS5463_VACGAIN 电压增益
uint32_t Value :
对应的条款的值
***************************************/
void SetCs5463CalDataToFlash(uint32_t Value,uint32_t item)
{
switch(item)
{
case CS5463_VDCOFF:
halCommonSetToken(TOKEN_CS5463_VDCOFF,(uint32_t *)&Value);
break;
case CS5463_IDCOFF:
halCommonSetToken(TOKEN_CS5463_IDCOFF,(uint32_t *)&Value);
break;
case CS5463_VACOFF:
halCommonSetToken(TOKEN_CS5463_VACOFF,(uint32_t *)&Value);
break;
case CS5463_IACOFF:
halCommonSetToken(TOKEN_CS5463_IACOFF,(uint32_t *)&Value);
break;
case CS5463_IACGAIN:
halCommonSetToken(TOKEN_CS5463_IACGAIN,(uint32_t *)&Value);
break;
case CS5463_VACGAIN:
halCommonSetToken(TOKEN_CS5463_VACGAIN,(uint32_t *)&Value);
break;
case CS5463_POWEROFF:
halCommonSetToken(TOKEN_CS5463_POWEROFF,(uint32_t *)&Value );
break;
}
}
以上是关于CS5463校验方法的主要内容,如果未能解决你的问题,请参考以下文章