HDL语言及源代码
ADE7758 是一款高准确度的三相电能计量芯片,带有两路脉冲输出功能和一个串行接口。ADE7758 集成了二阶∑-D 模数转换器, 数字积分器,基准电路,温度传感器,以及所有进行有功,无功和视在电能计量以及有效值计量所需的信号处理元件。
ADE7758 适用于计量各种三相配置条件下的有功,无功和视在电能,如WYE 和DELTA 系统,包括三线和四线制。
ADE7758 为各相提供系统校准功能,包括有效值偏移校准、相位校准、功率校准。APCF 逻辑输出提供有功功率信息,VARCF 逻辑输出提供瞬时无功率或视在功率信息。
ADE7758 中具有波形采样寄存器,它可以对模数转换器的输出进行访问。该器件集成了一个用于短时低电平和高电平变化的检测电路,变化的阈值电压和持续时间(即半周期数)由用户编程决定。三相中的任一相的线电压过零检测与电压过零点是同步的,过零检测的结果可用于测量三个电压输入中任意一个的周期。也可用于内部芯片的线循环(LINE CYCLE)电能累加模式。该模式使电能累加与半周期的整数倍同步,以此实现更快更准确的校准。
数据通过ADE7758 的SPI 串行接口读取。中断请求输出(IRQ)为开漏极,低电平有效。在ADE7758 中出现一个或多个中断事件时,IRQ 输出变为低电平。通过状态寄存器显示中断事件的性质。ADE7758 采用24 引脚小外形封装(SOIC)。
特点高准确度:支持IEC60687,IEC61036,, IEC 61268, IEC 62053-21, IEC 62053-22, 和IEC 62053-23
/*
* ade7758.c
*
* Created on: 2014-9-12
* Author: lzy
*/
#include
#include “debug.h”
#include “ade7758.h”
#include “SpiDev.h”
unsigned char bWorkModel=0;//工作模式标志位 1:校准模式;0:正常工作模式;
unsigned char bit_1s=0; //1s钟标志,在时钟中断函数中置位
static unsigned char divider = 1;//电能分频器,默认值为零,视在功率超出一定值时,自动将该值提高
static unsigned int energy[9];//用于累加电能值 36
struct all_data working;//正常工作模式下存放的电参量 95
struct adjust_data adjusting;//校准模式下存放的数据 65
static unsigned int vo_buffer[5][3];//用于电压的积分虑波 36
static unsigned int io_buffer[5][3];//用于电流的积分虑波 36
static unsigned char b_adjust = 0;//ADE7758已经校准标志
static unsigned char sample_cycle = 0; //电压采样周期,5次取平均
static unsigned char ADE_AdjustDataBuf[2+sizeof(struct adjust_dataw)]={0}; /*校准数据暂存缓冲区*/
void ADE_Check7758(void);
/**
* 功能:延时函数 50us
*/
void ADE_udelay(void)
{
// usleep(50);
}
/**
* 功能:片选使能
*/
void ADE_CS(unsigned char cs)
{
// CSADE7758_A = cs; //=====
}
/**
* 功能:通过SPI写入数据至芯片
* 入口参数:
* buf -》 数据缓冲区
* len -》 数据长度
*/
void ADE_SPIWrite(unsigned char *buf, unsigned char len)
{
SPI_Write(buf,len);
}
/**
* 功能:通过SPI读芯片数据
* 入口参数:len -》 数据长度
* 出口参数: buf -》 数据缓冲区
*
*/
void ADE_SPIRead(unsigned char *buf, unsigned char len)
{
SPI_Read(buf,len);
}
/**
* 功能:7758写数据函数
* 入口参数:
* type:目标寄存器的地址
* wdata:写进寄存器的内容
* databit:目标寄存器的宽度
* 出口参数:NULL
* 返回值:NULL
*/
void ADE_Write(unsigned char type,unsigned int wdata,unsigned char databit)
{
unsigned char data[3];
ADE_CS(0);
type = type | 0x80;
data[0] = type;
ADE_SPIWrite(data, 1);
ADE_udelay();
if(databit == 8)
{
data[0] = wdata;
ADE_SPIWrite(data, 1);
}
else if(databit == 16)
{
data[0] = (wdata&0xff00) 》》 8; /*高8位*/
data[1] = (wdata&0x00ff); /*底8位*/
ADE_SPIWrite(data, 2);
}
else
pr_err(“ADE write databit Error:%d\n”, databit);
ADE_CS(1);
}
/**
* 功能:7758读寄存器函数
* 入口参数:
* type:目标寄存器的地址
* databit:目标寄存器的宽度
* 出口参数:指定寄存器的内容
* 返回值:指定寄存器的内容
*/
unsigned int ADE_Read(unsigned char type,unsigned char databit)
{
unsigned char data[4]={0,0,0,0};
unsigned int rtdata = 0;
ADE_CS(0);
type = type & 0x7F;
data[0] = type;
ADE_SPIWrite(data, 1);
ADE_udelay();
if(databit == 8)
{
ADE_SPIRead(data,1);
rtdata = data[0];
}
else if(databit == 12)
{
ADE_SPIRead(data,2);
rtdata = (data[0]&0x0f) 《《 8;
rtdata += data[1];
}
else if(databit == 16)
{
ADE_SPIRead(data,2);
rtdata = data[0] 《《 8;
rtdata += data[1];
}else if(databit == 24)
{
ADE_SPIRead(data,3);
rtdata = data[0] 《《 16;
rtdata += (data[1] 《《 8);
rtdata += data[2];
}
else
pr_err(“ADE Read databit Error:%d\n”, databit);
ADE_CS(1);
return(rtdata);
}
/**
* 功能:检测异常
*/
void ADE_AuCheck(void)
{
unsigned char i;
unsigned int temp_data[5];//存放运算过程的中间变量
unsigned int temp_v,temp_i;
//自动检测ADE7758是否出现异常
if( working.voltage[ 0 ] 》 ERR_VOLTAGE ||
working.voltage[ 1 ] 》 ERR_VOLTAGE ||
working.voltage[ 2 ] 》 ERR_VOLTAGE )
{
ADE_Check7758();
}
//自动设置分频器的大小
for( i = 0; i 《 3 ; i++)
{
temp_v = working.voltage[ i ];
temp_i = working.current[ i ];
temp_data[i] = ( ( temp_v * temp_i ) / DIVI_VALUE ) & 0x000000ff;
}
temp_data[3] = ( temp_data[0] 》 temp_data[1] )?
( ( temp_data[0] 》 temp_data[2] )? temp_data[0] : temp_data[2] ) :
( ( temp_data[1] 》 temp_data[2] )? temp_data[1] : temp_data[2] ) ;
if( divider != (char)temp_data[3] )
{
//write to ade7758
divider = (char)temp_data[3] + 1;
for(i = 0; i 《 3; i++)
ADE_Write( ADD_WDIV + i, ( (int) divider 《《 8 ), 8 );
}
}
/**
* 功能:每秒读取功率
*/
void ADE_ReadHR(void)
{
unsigned char i;
unsigned int temp_data[9];//存放运算过程的中间变量
//有功
temp_data[ADD_AWATTHR - 1 ] = ADE_Read(ADD_AWATTHR,16);
temp_data[ADD_BWATTHR - 1 ] = ADE_Read(ADD_BWATTHR,16);
temp_data[ADD_CWATTHR - 1 ] = ADE_Read(ADD_CWATTHR,16);
//无功
temp_data[ADD_AVARHR - 1 ] = ADE_Read(ADD_AVARHR,16);
temp_data[ADD_BVARHR - 1 ] = ADE_Read(ADD_BVARHR,16);
temp_data[ADD_CVARHR - 1 ] = ADE_Read(ADD_CVARHR,16);
//视在
temp_data[ADD_AVAHR - 1 ] = ADE_Read(ADD_AVAHR,16);
temp_data[ADD_BVAHR - 1 ] = ADE_Read(ADD_BVAHR,16);
temp_data[ADD_CVAHR - 1 ] = ADE_Read(ADD_CVAHR,16);
for( i = 0; i 《 9 ; i++)
{
if( temp_data[ i ] 》 0x7fff )
temp_data[ i ] = 0xffff - temp_data[ i ] + 1;
}
if( divider 》 1)
{
for( i = 0; i 《 9; i++)
temp_data[ i ] = temp_data[ i ] * divider;//乘上分频器的值
}
//能量的计算
for( i = 0; i 《 9; i++)
energy[i] += temp_data[i];//累加电能值,单位为 WS(瓦秒)
//转换成千瓦时
for( i = 0; i 《 3; i++)
{
working.watt_hour[i] += (energy[i] / 3600000);//转换成千瓦时
energy[i] = energy[i] % 3600000;
}
working.watt_hour[3] = working.watt_hour[0] + working.watt_hour[1] + working.watt_hour[2];//总和
//转换成千伏安时
for( i = 0; i 《 3; i++)
{
working.va_hour[i] += (energy[ i+6 ] / 3600000);//转换成千瓦时
energy[ i+6 ] = energy[i+6] % 3600000;
}
working.va_hour[3] = working.va_hour[0] + working.va_hour[1] + working.va_hour[2];//总和
for( working.watt[ 3 ] = 0, i = 0; i 《 3; i++ )
{
working.watt[ i ] = temp_data[ i ]/1000;//千瓦
working.watt[ 3 ] += working.watt[ i ];
}
for( working.var[ 3 ] = 0, i = 0; i 《 3; i++ )
{
working.var[ i ] = temp_data[ i +3 ]/1000;
working.var[ 3 ] += working.var[ i ];
}
for( working.va[ 3 ] = 0, i = 0; i 《 3; i++ )
{
working.va[ i ] = temp_data[ i + 6 ] /1000;//千伏安
if(working.va[ i ] 《 working.watt[ i ])
working.va[ i ] = working.watt[ i ];
working.va[ 3 ] += working.va[ i ];
}
}
/**
* 功能:实时读取电流电压值
*/
void ADE_ReadVC(void)
{
unsigned char i, j;
for( i = 0; i 《 3; i++)
{
working.voltage[ i ] = 0;
working.current[ i ] = 0;
}
for( i = 0; i 《 3; i++)
{
for( j = 0; j 《 5; j++)
{
working.voltage[ i ] += vo_buffer[j][i];
working.current[ i ] += io_buffer[j][i];
}
}
for( i = 0; i 《 3; i++)
{
working.voltage[ i ] = working.voltage[ i ]/5;
working.current[ i ] = working.current[ i ]/5;
}
//电压电流的三相平均值
working.voltage[ 3 ] = (working.voltage[ 0 ] + working.voltage[ 1 ] + working.voltage[ 2 ] ) / 3;
working.current[ 3 ] = ( working.current[ 0 ] + working.current[ 1 ] + working.current[ 2 ] ) / 3;
printf(“ voltage=%d current=%d\n”,working.voltage[ 3 ], working.current[ 3 ]);
}
/**
* 校准模式下 每秒读取功率
*/
void ADE_AdjustHR(void)
{
unsigned char i;
unsigned int temp_data[9];//存放运算过程的中间变量
//有功
temp_data[ADD_AWATTHR - 1 ] = ADE_Read(ADD_AWATTHR,16);
temp_data[ADD_BWATTHR - 1 ] = ADE_Read(ADD_BWATTHR,16);
temp_data[ADD_CWATTHR - 1 ] = ADE_Read(ADD_CWATTHR,16);
//无功
temp_data[ADD_AVARHR - 1 ] = ADE_Read(ADD_AVARHR,16);
temp_data[ADD_BVARHR - 1 ] = ADE_Read(ADD_BVARHR,16);
temp_data[ADD_CVARHR - 1 ] = ADE_Read(ADD_CVARHR,16);
//视在
temp_data[ADD_AVAHR - 1 ] = ADE_Read(ADD_AVAHR,16);
temp_data[ADD_BVAHR - 1 ] = ADE_Read(ADD_BVAHR,16);
temp_data[ADD_CVAHR - 1 ] = ADE_Read(ADD_CVAHR,16);
for( i = 0 ; i 《 3; i++)
{
adjusting.read_data.watt[i] = temp_data[ i + 0 ] & 0x0000ffff;
adjusting.read_data.var[i] = temp_data[ i + 3 ] & 0x0000ffff;//没有校准有功功率
adjusting.read_data.va[i] = temp_data[ i + 6 ] & 0x0000ffff;
}
}
/**
* 校准模式下实时读取电流电压值
*/
void ADE_AdjustVC(void)
{
unsigned char i, j;
for( i = 0; i 《 3; i++)
{
adjusting.read_data.voltage[i] = 0;
adjusting.read_data.current[i] = 0;
}
for( i = 0; i 《 3; i++)
{
for( j = 0; j 《 5; j++)
{
adjusting.read_data.voltage[i] += vo_buffer[j][i];
adjusting.read_data.current[i] += io_buffer[j][i];
}
}
for( i = 0; i 《 3; i++)
{
adjusting.read_data.voltage[i] = adjusting.read_data.voltage[i]/5;
adjusting.read_data.current[i] = adjusting.read_data.current[i]/5;
}
}
/**
* 功能:从ADE7758中取出三相电压电流功率等电参量
*/
void ADE_GetData(void)
{
static unsigned char bit_3s=0;
unsigned char j;
if( !bWorkModel ) //正常工作模式
{
if( bit_1s )
{
bit_1s = 0;
ADE_ReadHR();
if( (bit_3s++) 》= 3 ) /*三秒检测一次异常*/
{
ADE_AuCheck();
bit_3s=0;
}
}
for( j = 0; j 《 3; j++)
{
vo_buffer[ sample_cycle ][j] = ADE_Read( ADD_AVRMS + j, 24 ) 》》 12;//voltage
io_buffer[ sample_cycle ][j] = ADE_Read( ADD_AIRMS + j, 24 ) 》》 13;//current
}
if( sample_cycle == 4) /*读取5次取平均值*/
ADE_ReadVC();
}
else
{
if( bit_1s )
{
bit_1s = 0;
ADE_AdjustHR();
}
for( j = 0; j 《 3; j++)
{
vo_buffer[sample_cycle][j] = ADE_Read( ADD_AVRMS + j, 24 );
io_buffer[sample_cycle][j] = ADE_Read( ADD_AIRMS + j, 24 );
}
if( sample_cycle == 4)
ADE_AdjustVC();
// save_set_to_e2prom(); //===
}
if( sample_cycle 《 4 )
sample_cycle += 1;
else
sample_cycle = 0;
}
/**
* 校准数据保存至缓冲区
*/
void ADE_WriteByte(unsigned short data, unsigned short addr)
{
memcpy(ADE_AdjustDataBuf+addr, &data, sizeof(unsigned short));
}
/**
* 读取校准数据缓冲区中数据
*/
unsigned short ADE_ReadByte(unsigned short addr)
{
unsigned short data;
memcpy(&data, ADE_AdjustDataBuf+addr, sizeof(unsigned short));
return data;
}
/**
* 功能:保存校准数据
*/
void ADE_AdjustSaveData(void)
{
unsigned char i;
unsigned short temp_data;
unsigned short temp_add = 0;
ADE_WriteByte( SAVE_OK, ADE_SET_ADDR ); //写入标志
temp_add +=2;
for(i = 0; i 《 3 ; i++)
{
temp_data = adjusting.write_data.voltage[i];
ADE_WriteByte(temp_data , ADE_SET_ADDR + temp_add );
temp_add += 2;
}
for(i = 0; i 《 3 ; i++)
{
temp_data = adjusting.write_data.current[i];
ADE_WriteByte(temp_data , ADE_SET_ADDR + temp_add );
temp_add += 2;
}
for(i = 0; i 《 3 ; i++)
{
temp_data = adjusting.write_data.watt[i];
ADE_WriteByte(temp_data , ADE_SET_ADDR + temp_add );
temp_add += 2;
}
for(i = 0; i 《 3 ; i++)
{
temp_data = adjusting.write_data.var[i];
ADE_WriteByte(temp_data , ADE_SET_ADDR + temp_add );
temp_add += 2;
}
for(i = 0; i 《 3 ; i++)
{
temp_data = adjusting.write_data.va[i];
ADE_WriteByte(temp_data , ADE_SET_ADDR + temp_add );
temp_add += 2;
}
}
/**
* 功能: 将缓冲区中的校准参数写入ADE7758
* 当确定校准参数的值后,便调用该函数,写数据写入ADE7758特定的寄存器中
*/
void ADE_AdjustWriteValue(void)
{
unsigned char i;
unsigned short temp_data;
for(i = 0; i 《 3; i++)
{
temp_data = adjusting.write_data.voltage[i];
if( temp_data 《 0x1000 )//4096
ADE_Write( ADD_AVRMSGAIN + i, temp_data , 16 );
}
for(i = 0; i 《 3; i++)
{
temp_data = adjusting.write_data.current[i];
if( temp_data 《 0x1000 )//4096
ADE_Write( ADD_AIGAIN + i, temp_data , 16 );
}
for(i = 0; i 《 3; i++)
{
temp_data = adjusting.write_data.watt[i];
if( temp_data 《 0x1000 )//4096
ADE_Write( ADD_AWG + i, temp_data , 16 );
}
for(i = 0; i 《 3; i++)
{
temp_data = adjusting.write_data.var[i];
if( temp_data 《 0x1000 )//4096
ADE_Write( ADD_AVARG + i, temp_data , 16 );
}
for(i = 0; i 《 3; i++)
{
temp_data = adjusting.write_data.va[i];
if( temp_data 《 0x1000 )//4096
ADE_Write( ADD_AVAG + i, temp_data , 16 );
}
}
/**
* 功能:读出已保存的校准参数
*/
void ADE_AdjustReadData(void)
{
unsigned char i;
unsigned short temp_data;
unsigned short temp_add = 0;
if( ADE_ReadByte(ADE_SET_ADDR) == SAVE_OK)
{
b_adjust = 1;//ADE7758已经校准标志
temp_add += 2;
for( i = 0; i 《 3 ; i++)
{
temp_data = ADE_ReadByte( ADE_SET_ADDR + temp_add );
adjusting.write_data.voltage[i]= temp_data;
temp_add += 2;
}
for( i = 0; i 《 3 ; i++)
{
temp_data = ADE_ReadByte( ADE_SET_ADDR + temp_add );
adjusting.write_data.current[i]= temp_data;
temp_add += 2;
}
for( i = 0; i 《 3 ; i++)
{
temp_data = ADE_ReadByte( ADE_SET_ADDR + temp_add );
adjusting.write_data.watt[i]= temp_data;
temp_add += 2;
}
for( i = 0; i 《 3 ; i++)
{
temp_data = ADE_ReadByte( ADE_SET_ADDR + temp_add );
adjusting.write_data.var[i]= temp_data;
temp_add += 2;
}
for( i = 0; i 《 3 ; i++)
{
temp_data = ADE_ReadByte( ADE_SET_ADDR + temp_add );
adjusting.write_data.va[i]= temp_data;
temp_add += 2;
}
ADE_AdjustWriteValue();
}
}
/**
* 功能:检测7758是否异常,有则修复
*/
void ADE_Check7758(void)
{
unsigned short temp,temp1;
if( !b_adjust )//ADE7758已经校准标志
return;
temp = ADE_ReadByte( ADE_SET_ADDR + 2 );
temp1 = ADE_Read( ADD_AVRMSGAIN ,12 ) & 0x0fff;
if( temp != temp1 )//检测A相校准参数是否正确
ADE_AdjustReadData();
}
/**
* 功能:将标志写入中断寄存器中,允许能量寄存器容量超出一半时产生中断
*/
void ADE_WriteMask(void)
{
unsigned char data[3];
unsigned char type;
unsigned int wdata = 0x00000700;//AEHF=1,VAEHF=1,低8位无用
ADE_CS(0);
type = ADD_MASK & 0x7F;
type = type | 0x80;
data[0] = type;
ADE_SPIWrite(data, 1);
ADE_udelay();
data[0] = (wdata 》》 16)&0xFF;
data[1] = (wdata 》》 8)&0xFF;
data[2] = wdata&0xFF;
ADE_SPIWrite(data, 3);
ADE_CS(1);
}
/**
* 功能:清除校准数据
*/
void ADE_Clean(void)
{
unsigned char i;
for( i = 0; i 《 3 ; i++)
adjusting.write_data.voltage[i] = 0;
for( i = 0; i 《 3 ; i++)
adjusting.write_data.current[i] = 0;
for( i = 0; i 《 3 ; i++)
adjusting.write_data.watt[i] = 0;
for( i = 0; i 《 3 ; i++)
adjusting.write_data.var[i] = 0;
for( i = 0; i 《 3 ; i++)
adjusting.write_data.va[i] = 0;
ADE_AdjustWriteValue();
memset(ADE_AdjustDataBuf,0,sizeof(ADE_AdjustDataBuf)); /*校验数据缓冲区清0*/
}
/**
* 功能:7758初始化函数
*/
void ADE_Init(void)
{
unsigned char TempData, i;
ADE_WriteMask();//write interrupt mask to ade7758
TempData = (0xff & ADE_Read(ADD_COMPMODE,8) ) | 0x80;
ADE_Write(ADD_COMPMODE,((int)TempData《《8),8);//seting activate the no-load threshold
if( bWorkModel )
{
ADE_Clean();
for(i = 0; i 《 3; i++)
ADE_Write( ADD_WDIV + i, 0X00 , 8 );
}
else //正常工作模式
ADE_AdjustReadData();
}
int main(void)
{
int ret = 0;
ret = SPI_Open();
if(ret)
return ret;
ADE_AdjustSaveData();
ADE_Init();
while(1)
{
sleep(1);
bit_1s = 1;
ADE_GetData();
}
SPI_Close();
return 0;
}
全部0条评论
快来发表一下你的评论吧 !