⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ade7758.c

📁 实现对ADE7758电能芯片的读写和校准,8051单片机,通过PC对电参量进行校准
💻 C
📖 第 1 页 / 共 4 页
字号:
union int_char  xdata io_buffer[5][3];//用于电压电流的积分虑波 36

bit b_clean_en = 0;//能量清除标志
extern bit bWorkModel;//工作模式标志位 1:校准模式;0:正常工作模式;启动时检测键盘口状态,确定该位状态
extern bit bit_3s;

uchar sample_cycle = 0;           //电压采样周期,5次取平均
uchar sample_cycle1 = 0;          //电压采样周期,5次取平均

uchar data divider = 1;//电能分频器,默认值为零,视在功率超出一定值时,自动将该值提高

/****************************************************************
从ADE7758中取出三相电压电流功率等电参量
*****************************************************************/

void get_data_from7758()
{
	union long_char temp_data[9];//存放运算过程的中间变量
	uchar i,j;
	long idata temp_v,temp_i;
	
	if( bSendingData )
	return;
	
	if( !bWorkModel )
	{//正常工作模式
		
		if( bit_1s )
		{
			bit_1s = 0;
			//有功
			temp_data[ADD_AWATTHR - 1 ].data32 = read7753a(ADD_AWATTHR,16);
			temp_data[ADD_BWATTHR - 1 ].data32 = read7753a(ADD_BWATTHR,16);
			temp_data[ADD_CWATTHR - 1 ].data32 = read7753a(ADD_CWATTHR,16);
			//无功
			temp_data[ADD_AVARHR - 1 ].data32 = read7753a(ADD_AVARHR,16);
			temp_data[ADD_BVARHR - 1 ].data32 = read7753a(ADD_BVARHR,16);
			temp_data[ADD_CVARHR - 1 ].data32 = read7753a(ADD_CVARHR,16);
			//视在
			temp_data[ADD_AVAHR - 1 ].data32 = read7753a(ADD_AVAHR,16);
			temp_data[ADD_BVAHR - 1 ].data32 = read7753a(ADD_BVAHR,16);
			temp_data[ADD_CVAHR - 1 ].data32 = read7753a(ADD_CVAHR,16);
			
			for( i = 0; i < 9 ; i++)
			{
				if( temp_data[ i ].data32 > 0x7fff )
				temp_data[ i ].data32 = 0xffff - temp_data[ i ].data32 + 1;
			}//end of for( i = 0; i < 9 ; i++)
			
			if( divider > 1)
			{
				for( i = 0; i < 9; i++)
				temp_data[ i ].data32 = temp_data[ i ].data32 * divider;//乘上分频器的值
				
			}//end of if(divider != 0)
			
			 
			/////////////////////////////////////////////////////////////////////////////////
			//能量的计算
			for( i = 0; i < 9; i++)
			energy[i].data32 += temp_data[i].data32;//累加电能值,单位为 WS(瓦秒)
			
			//转换成千瓦时
			for( i = 0; i < 3; i++)
			{
				rwdata.working.watt_hour[i].data32 += (energy[i].data32 / 3600000);//转换成千瓦时
				energy[i].data32 = energy[i].data32 % 3600000;
				
			}//end of for(i)
			rwdata.working.watt_hour[3].data32 = rwdata.working.watt_hour[0].data32 
                                                 + rwdata.working.watt_hour[1].data32
			                                     + rwdata.working.watt_hour[2].data32;//总和
			//
			for(  i = 0; i < 3; i++)
			{
				rwdata.working.var_hour[i].data32 += (energy[ i+3 ].data32 / 3600000);//转换成千瓦时
				energy[ i+3 ].data32 = energy[i+3].data32 % 3600000;
				
			}//end of for(i)
			rwdata.working.var_hour[3].data32 = rwdata.working.var_hour[0].data32 
			                                    + rwdata.working.var_hour[1].data32
			                                    + rwdata.working.var_hour[2].data32;//总和
			
			//转换成千伏安时
			for( i = 0; i < 3; i++)
			{
				rwdata.working.va_hour[i].data32 += (energy[ i+6 ].data32 / 3600000);//转换成千瓦时
				energy[ i+6 ].data32 = energy[i+6].data32 % 3600000;
				
			}//end of for(i)
			rwdata.working.va_hour[3].data32 = rwdata.working.va_hour[0].data32 
			                                   + rwdata.working.va_hour[1].data32
			                                   + rwdata.working.va_hour[2].data32;//总和
			//能量的计算结束
			/////////////////////////////////////////////////////////////////////////////////
			
			
			/////////////////////////////////////////////////////////////////////////////////
			//功率的计算
			
			for( rwdata.working.watt[ 3 ].data16 = 0, i = 0; i < 3; i++ )
			{
				rwdata.working.watt[ i ].data16 = ( temp_data[ i ].data32 )/1000;//千瓦
				rwdata.working.watt[ 3 ].data16 += rwdata.working.watt[ i ].data16;
			}//end of for(i)
			
			for( rwdata.working.var[ 3 ].data16 = 0, i = 0; i < 3; i++ )
			{
				rwdata.working.var[ i ].data16 = ( temp_data[ i +3 ].data32  )/1000;//
				rwdata.working.var[ 3 ].data16 += rwdata.working.var[ i ].data16;
			}//end of for(i)
			
			for( rwdata.working.va[ 3 ].data16 = 0, i = 0; i < 3; i++ )
			{
				rwdata.working.va[ i ].data16 = ( temp_data[ i + 6 ].data32  )/1000;//千伏安
				
				if(rwdata.working.va[ i ].data16 < rwdata.working.watt[ i ].data16)
				{
					rwdata.working.va[ i ].data16 = rwdata.working.watt[ i ].data16;
				}//end of if(rwdata.working.va[ i ].data16 < rwdata.working.watt[ i ].data16)
				
				rwdata.working.va[ 3 ].data16 += rwdata.working.va[ i ].data16;
			}//end of for(i)
			
			//功率的计算结束
			/////////////////////////////////////////////////////////////////////////////////
			
		}//end of if(bit_1s)
		
		
		
		for( j = 0; j < 3; j++)
		{
			vo_buffer[ sample_cycle1 ][j].data16 = read7753a( ADD_AVRMS + j, 24 ) >> 12;//voltage
			io_buffer[ sample_cycle1 ][j].data16 = read7753a( ADD_AIRMS + j, 24 ) >> 13;//current
		}//end of for( j = 0; j < 3; j++)
		
		if( sample_cycle1 == 4)
		{
			for( i = 0; i < 3; i++)
			{
				rwdata.working.voltage[ i ].data16 = 0;
				rwdata.working.current[ i ].data16 = 0;
			}
			for( i = 0; i < 3; i++)
			{
				for( j = 0; j < 5; j++)
				{
					rwdata.working.voltage[ i ].data16 += vo_buffer[j][i].data16;
					rwdata.working.current[ i ].data16 += io_buffer[j][i].data16;
				}
			}
			for( i = 0; i < 3; i++)
			{
				rwdata.working.voltage[ i ].data16 = rwdata.working.voltage[ i ].data16/5;
				rwdata.working.current[ i ].data16 = rwdata.working.current[ i ].data16/5;
			}
			
			//电压电流的三相平均值
			rwdata.working.voltage[ 3 ].data16 = ( rwdata.working.voltage[ 0 ].data16 + rwdata.working.voltage[ 1 ].data16
			                                       + rwdata.working.voltage[ 2 ].data16 ) / 3;
			                                       
			rwdata.working.current[ 3 ].data16 = ( rwdata.working.current[ 0 ].data16 + rwdata.working.current[ 1 ].data16
			                                       + rwdata.working.current[ 2 ].data16 ) / 3;
			
			
			if( bit_3s )
			{
				//自动检测ADE7758是否出现异常
				if( rwdata.working.voltage[ 0 ].data16 > ERR_VOLTAGE ||
				    rwdata.working.voltage[ 1 ].data16 > ERR_VOLTAGE ||
				    rwdata.working.voltage[ 2 ].data16 > ERR_VOLTAGE )//
				check_ade7758();//
				//自动检测ADE7758是否出现异常
			//自动设置分频器的大小
				
				for( i = 0; i < 3 ; i++)
				{
					temp_v = rwdata.working.voltage[ i ].data16;
					temp_i = rwdata.working.current[ i ].data16;
					
					temp_data[i].data32 = ( ( temp_v * temp_i ) / DIVI_VALUE ) & 0x000000ff;
				}//end of for(i)
            	
				temp_data[3].data32 = (   temp_data[0].data32 > temp_data[1].data32 )?
				                      ( ( temp_data[0].data32 > temp_data[2].data32 )?  temp_data[0].data32 : temp_data[2].data32 ) :
				                      ( ( temp_data[1].data32 > temp_data[2].data32 )?  temp_data[1].data32 : temp_data[2].data32 ) ;
            	
				if(  divider != (char)temp_data[3].data32 )
				{//write to ade7758
            	
					divider = (char)temp_data[3].data32 + 1;
            	
					for(i = 0; i < 3; i++)
					{
						write7753a( ADD_WDIV + i, ( (int) divider << 8 ), 8 );
					}//end of for(i)
            	
				}//end of if(  divider != temp_data[3].data32))
			}//end of if(bit_3s)
			
		}//end of if( sample_cycle1 == 4 )
		
		if( sample_cycle1 < 4 )
		sample_cycle1 += 1;
		else
		sample_cycle1 = 0;
		///////////////////////////////////04-8-21 9:02		
		
		//三相线电压
		for( i = 0; i < 4 ; i++)
		rwdata.working.voltageLL[ i ].data16 = 0; 
		
		          
		//三相的电压电流结束
		/////////////////////////////////////////////////////////////////////////////////////
		
		/////////////////////////////////////////////////////////////////////////////////////
		//获取系统频率
		
		rwdata.working.sys_hz.data16 = read7753a( ADD_FREQ, 12 ) & 0x000fff;
		rwdata.working.sys_hz.data16 = rwdata.working.sys_hz.data16 * 100;
		//获取系统频率结束
		/////////////////////////////////////////////////////////////////////////////////////
		
		///////////////////////////////////////////////////
		//获取浪涌个数
		rwdata.working.surge.data32 = rwdata.working.surge.data32 + get_surger();
		//获取浪涌个数
		///////////////////////////////////////////////////
		
	}//end of if(bWorkModel)
	
	else
	{//校准工作模式
		
		if( bit_1s )
		{
			bit_1s = 0;
			//有功
			temp_data[ADD_AWATTHR - 1 ].data32 = read7753a(ADD_AWATTHR,16);
			temp_data[ADD_BWATTHR - 1 ].data32 = read7753a(ADD_BWATTHR,16);
			temp_data[ADD_CWATTHR - 1 ].data32 = read7753a(ADD_CWATTHR,16);
			//无功
			temp_data[ADD_AVARHR - 1 ].data32 = read7753a(ADD_AVARHR,16);
			temp_data[ADD_BVARHR - 1 ].data32 = read7753a(ADD_BVARHR,16);
			temp_data[ADD_CVARHR - 1 ].data32 = read7753a(ADD_CVARHR,16);
			//视在
			temp_data[ADD_AVAHR - 1 ].data32 = read7753a(ADD_AVAHR,16);
			temp_data[ADD_BVAHR - 1 ].data32 = read7753a(ADD_BVAHR,16);
			temp_data[ADD_CVAHR - 1 ].data32 = read7753a(ADD_CVAHR,16);
			
			for( i = 0 ; i < 3; i++)
			{
				rwdata.adjusting.read_data.watt[i].data16 = temp_data[ i + 0 ].data32 & 0x0000ffff;
				rwdata.adjusting.read_data.var[i].data16  = temp_data[ i + 3 ].data32 & 0x0000ffff;//没有校准有功功率
				rwdata.adjusting.read_data.va[i].data16   = temp_data[ i + 6 ].data32 & 0x0000ffff;
			}//end of for(i)
			
		}//end of if( bit_1s )
		///////////////////////////////////////////////////////////////////////////04-8-19 11:36
		for( j = 0; j < 3; j++)
		{
			v_buffer[sample_cycle][j] = read7753a( ADD_AVRMS + j, 24 );
			i_buffer[sample_cycle][j] = read7753a( ADD_AIRMS + j, 24 );
		}//end of for( j = 0; j < 3; j++)
		
		if( sample_cycle == 4)
		{
			for( i = 0; i < 3; i++)
			{
				rwdata.adjusting.read_data.voltage[i].data32 = 0;
				rwdata.adjusting.read_data.current[i].data32 = 0;
			}
			for( i = 0; i < 3; i++)
			{
				for( j = 0; j < 5; j++)
				{
					rwdata.adjusting.read_data.voltage[i].data32 += v_buffer[j][i];
					rwdata.adjusting.read_data.current[i].data32 += i_buffer[j][i];
				}
			}
			for( i = 0; i < 3; i++)
			{
				rwdata.adjusting.read_data.voltage[i].data32 = rwdata.adjusting.read_data.voltage[i].data32/5;
				rwdata.adjusting.read_data.current[i].data32 = rwdata.adjusting.read_data.current[i].data32/5;
			}
		}//end of if( sample_cycle == 4 )
		
		if( sample_cycle < 4 )
		sample_cycle += 1;
		else
		sample_cycle = 0;

	}//end of else
}//end of get_data_from7758()




/**********************************************************************************************
                   将缓冲区中的校准参数写入ADE7758
当确定校准参数的值后,便调用该函数,写数据写入ADE7758特定的寄存器中
***********************************************************************************************/
#define ADD_AVRMSGAIN    0X24
#define ADD_BVRMSGAIN    0X25
#define ADD_CVRMSGAIN    0X26

#define ADD_AIGAIN       0X27
#define ADD_BIGAIN       0X28
#define ADD_CIGAIN       0X29

#define ADD_AWG          0X2A      //12  R/W Phase A Active power Gain register.  
#define ADD_BWG          0X2B      //12  R/W Phase B Active power Gain register.
#define ADD_CWG          0X2C      //12  R/W Phase C Active power Gain register.
                         
#define ADD_AVARG        0X2D      //12  R/W VA Gain register.
#define ADD_BVARG        0X2E      //12  R/W VB Gain register.
#define ADD_CVARG        0X2F      //12  R/W VC Gain register.
                         
#define ADD_AVAG         0X30      //12  R/W VA Gain register.
#define ADD_BVAG         0X31      //12  R/W VB Gain register.
#define ADD_CVAG         0X32      //12  R/W VC Gain register.


void write_to7758()
{
	uchar i;
	uint temp_data;
	
	for(i = 0; i < 3; i++)
	{
		temp_data = rwdata.adjusting.write_data.voltage[i].data16;
		
		if( temp_data < 0x1000 )//4096
		write7753a( ADD_AVRMSGAIN + i, temp_data , 16 );
	}//end of for(i)
	
	for(i = 0; i < 3; i++)
	{
		temp_data = rwdata.adjusting.write_data.current[i].data16;
		
		if( temp_data < 0x1000 )//4096
		write7753a( ADD_AIGAIN + i, temp_data , 16 );
	}//end of for(i)
	
	for(i = 0; i < 3; i++)
	{
		temp_data = rwdata.adjusting.write_data.watt[i].data16;
		
		if( temp_data < 0x1000 )//4096
		write7753a( ADD_AWG + i, temp_data , 16 );
	}//end of for(i)
	
	for(i = 0; i < 3; i++)
	{
		temp_data = rwdata.adjusting.write_data.var[i].data16;
		
		if( temp_data < 0x1000 )//4096
		write7753a( ADD_AVARG + i, temp_data , 16 );
	}//end of for(i)
	
	for(i = 0; i < 3; i++)
	{
		temp_data = rwdata.adjusting.write_data.va[i].data16;
		
		if( temp_data < 0x1000 )//4096
		write7753a( ADD_AVAG + i, temp_data , 16 );
	}//end of for(i)
	
}//end of write_to7758()


/*******************************************************************************************
                  将参数写入E2PROM
在校准模式下才会调用该函数
********************************************************************************************/
#define SET_E2PROM_ADD     0X60    //存放校准参数的起始地址: 96  ;长度: 24 BYTES

void save_set_to_e2prom()
{
	uchar data i,j;
	uchar data temp_data;
	uchar data temp_add = 0;
	
	EA = 0;
	
	byte_write( SAVE_OK, SET_E2PROM_ADD );  //写入标志
	
	for(i = 0; i < 3 ; i++)
	{
		for( j = 0; j < 2; j++)
		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -