ade7758程序

HDL语言及源代码

6人已加入

描述

  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程序

  /*

  * 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;

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分