ADE7758 是一款高準(zhǔn)確度的三相電能計量芯片,帶有兩路脈沖輸出功能和一個串行接口。ADE7758 集成了二階∑-D 模數(shù)轉(zhuǎn)換器, 數(shù)字積分器,基準(zhǔn)電路,溫度傳感器,以及所有進行有功,無功和視在電能計量以及有效值計量所需的信號處理元件。
ADE7758 適用于計量各種三相配置條件下的有功,無功和視在電能,如WYE 和DELTA 系統(tǒng),包括三線和四線制。
ADE7758 為各相提供系統(tǒng)校準(zhǔn)功能,包括有效值偏移校準(zhǔn)、相位校準(zhǔn)、功率校準(zhǔn)。APCF 邏輯輸出提供有功功率信息,VARCF 邏輯輸出提供瞬時無功率或視在功率信息。
ADE7758 中具有波形采樣寄存器,它可以對模數(shù)轉(zhuǎn)換器的輸出進行訪問。該器件集成了一個用于短時低電平和高電平變化的檢測電路,變化的閾值電壓和持續(xù)時間(即半周期數(shù))由用戶編程決定。三相中的任一相的線電壓過零檢測與電壓過零點是同步的,過零檢測的結(jié)果可用于測量三個電壓輸入中任意一個的周期。也可用于內(nèi)部芯片的線循環(huán)(LINE CYCLE)電能累加模式。該模式使電能累加與半周期的整數(shù)倍同步,以此實現(xiàn)更快更準(zhǔn)確的校準(zhǔn)。
數(shù)據(jù)通過ADE7758 的SPI 串行接口讀取。中斷請求輸出(IRQ)為開漏極,低電平有效。在ADE7758 中出現(xiàn)一個或多個中斷事件時,IRQ 輸出變?yōu)榈碗娖健Mㄟ^狀態(tài)寄存器顯示中斷事件的性質(zhì)。ADE7758 采用24 引腳小外形封裝(SOIC)。
特點高準(zhǔn)確度:支持IEC60687,IEC61036,, IEC 61268, IEC 62053-21, IEC 62053-22, 和IEC 62053-23
ade7758程序
/*
* ade7758.c
*
* Created on: 2014-9-12
* Author: lzy
*/
#include
#include “debug.h”
#include “ade7758.h”
#include “SpiDev.h”
unsigned char bWorkModel=0;//工作模式標(biāo)志位 1:校準(zhǔn)模式;0:正常工作模式;
unsigned char bit_1s=0; //1s鐘標(biāo)志,在時鐘中斷函數(shù)中置位
static unsigned char divider = 1;//電能分頻器,默認值為零,視在功率超出一定值時,自動將該值提高
static unsigned int energy[9];//用于累加電能值 36
struct all_data working;//正常工作模式下存放的電參量 95
struct adjust_data adjusting;//校準(zhǔn)模式下存放的數(shù)據(jù) 65
static unsigned int vo_buffer[5][3];//用于電壓的積分慮波 36
static unsigned int io_buffer[5][3];//用于電流的積分慮波 36
static unsigned char b_adjust = 0;//ADE7758已經(jīng)校準(zhǔn)標(biāo)志
static unsigned char sample_cycle = 0; //電壓采樣周期,5次取平均
static unsigned char ADE_AdjustDataBuf[2+sizeof(struct adjust_dataw)]={0}; /*校準(zhǔn)數(shù)據(jù)暫存緩沖區(qū)*/
void ADE_Check7758(void);
/**
* 功能:延時函數(shù) 50us
*/
void ADE_udelay(void)
{
// usleep(50);
}
/**
* 功能:片選使能
*/
void ADE_CS(unsigned char cs)
{
// CSADE7758_A = cs; //=====
}
/**
* 功能:通過SPI寫入數(shù)據(jù)至芯片
* 入口參數(shù):
* buf -》 數(shù)據(jù)緩沖區(qū)
* len -》 數(shù)據(jù)長度
*/
void ADE_SPIWrite(unsigned char *buf, unsigned char len)
{
SPI_Write(buf,len);
}
/**
* 功能:通過SPI讀芯片數(shù)據(jù)
* 入口參數(shù):len -》 數(shù)據(jù)長度
* 出口參數(shù): buf -》 數(shù)據(jù)緩沖區(qū)
*
*/
void ADE_SPIRead(unsigned char *buf, unsigned char len)
{
SPI_Read(buf,len);
}
/**
* 功能:7758寫數(shù)據(jù)函數(shù)
* 入口參數(shù):
* type:目標(biāo)寄存器的地址
* wdata:寫進寄存器的內(nèi)容
* databit:目標(biāo)寄存器的寬度
* 出口參數(shù):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讀寄存器函數(shù)
* 入口參數(shù):
* type:目標(biāo)寄存器的地址
* databit:目標(biāo)寄存器的寬度
* 出口參數(shù):指定寄存器的內(nèi)容
* 返回值:指定寄存器的內(nèi)容
*/
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是否出現(xiàn)異常
if( working.voltage[ 0 ] 》 ERR_VOLTAGE ||
working.voltage[ 1 ] 》 ERR_VOLTAGE ||
working.voltage[ 2 ] 》 ERR_VOLTAGE )
{
ADE_Check7758();
}
//自動設(shè)置分頻器的大小
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(瓦秒)
//轉(zhuǎn)換成千瓦時
for( i = 0; i 《 3; i++)
{
working.watt_hour[i] += (energy[i] / 3600000);//轉(zhuǎn)換成千瓦時
energy[i] = energy[i] % 3600000;
}
working.watt_hour[3] = working.watt_hour[0] + working.watt_hour[1] + working.watt_hour[2];//總和
//轉(zhuǎn)換成千伏安時
for( i = 0; i 《 3; i++)
{
working.va_hour[i] += (energy[ i+6 ] / 3600000);//轉(zhuǎn)換成千瓦時
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 ]);
}
/**
* 校準(zhǔn)模式下 每秒讀取功率
*/
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;//沒有校準(zhǔn)有功功率
adjusting.read_data.va[i] = temp_data[ i + 6 ] & 0x0000ffff;
}
}
/**
* 校準(zhǔn)模式下實時讀取電流電壓值
*/
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;
}
/**
* 校準(zhǔn)數(shù)據(jù)保存至緩沖區(qū)
*/
void ADE_WriteByte(unsigned short data, unsigned short addr)
{
memcpy(ADE_AdjustDataBuf+addr, &data, sizeof(unsigned short));
}
/**
* 讀取校準(zhǔn)數(shù)據(jù)緩沖區(qū)中數(shù)據(jù)
*/
unsigned short ADE_ReadByte(unsigned short addr)
{
unsigned short data;
memcpy(&data, ADE_AdjustDataBuf+addr, sizeof(unsigned short));
return data;
}
/**
* 功能:保存校準(zhǔn)數(shù)據(jù)
*/
void ADE_AdjustSaveData(void)
{
unsigned char i;
unsigned short temp_data;
unsigned short temp_add = 0;
ADE_WriteByte( SAVE_OK, ADE_SET_ADDR ); //寫入標(biāo)志
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;
}
}
/**
* 功能: 將緩沖區(qū)中的校準(zhǔn)參數(shù)寫入ADE7758
* 當(dāng)確定校準(zhǔn)參數(shù)的值后,便調(diào)用該函數(shù),寫數(shù)據(jù)寫入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 );
}
}
/**
* 功能:讀出已保存的校準(zhǔn)參數(shù)
*/
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已經(jīng)校準(zhǔn)標(biāo)志
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是否異常,有則修復(fù)
*/
void ADE_Check7758(void)
{
unsigned short temp,temp1;
if( !b_adjust )//ADE7758已經(jīng)校準(zhǔn)標(biāo)志
return;
temp = ADE_ReadByte( ADE_SET_ADDR + 2 );
temp1 = ADE_Read( ADD_AVRMSGAIN ,12 ) & 0x0fff;
if( temp != temp1 )//檢測A相校準(zhǔn)參數(shù)是否正確
ADE_AdjustReadData();
}
/**
* 功能:將標(biāo)志寫入中斷寄存器中,允許能量寄存器容量超出一半時產(chǎn)生中斷
*/
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);
}
/**
* 功能:清除校準(zhǔn)數(shù)據(jù)
*/
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)); /*校驗數(shù)據(jù)緩沖區(qū)清0*/
}
/**
* 功能:7758初始化函數(shù)
*/
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;
}
評論
查看更多