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

📄 ade7758.c

📁 实现对ADE7758电能芯片的读写和校准,8051单片机,通过PC对电参量进行校准
💻 C
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************************************************
                                文件和函数说明
本文件包含对ADE7758芯片进行操作的所有函数,利用单片机的I/O口模拟标准的SPI对ADE7758进行操作。
使用单片机型号:p89v51rd2,护展1K处部RAM
晶振频率:11.0592MHz
功能模块:
         1、ADE7758底层操作函数:
         write7753(unsigned char type,unsigned int wdata,unsigned char databit) 向ADE758写数据
         read7753(unsigned char type,unsigned char databit)                     从ADE758读出一个寄存器的数据
         2、ADE7758应用层操作函数:
         write7753a(unsigned char type,unsigned int wdata,unsigned char databit)
         read7753a(unsigned char type,unsigned char databit)
         get_data_from7758()      从ADE7758中读出所需的电参量
硬件要求
BIT     0022H.2   0000H.2   UNIT         ?BI?ADE7758
DATA    005DH     0007H     UNIT         ?DT?ADE7758
XDATA   0000H     01AEH     UNIT         ?XD?ADE7758
******************************************************************************************************************/

#include  "reg52.h"	
#include  "intrins.h"
#include  "surge.h"
#include "rs232.h"
#include "25045.h"
#include "r_wIAP.h"

#define PARAMETER 17 //将电能寄存器中的值转换成实际电能值的计参数

#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long
//key value table
#define KeyUp		0xfd
#define KeyDown		0xfb
#define KeyEnter	0xf7
#define KeyCancel	0xef
//eerom address define
#define EEROM_ADD_TAE 10        //5bytes  first:flag,second to five:data
#define EEROM_ADD_TVAE 16       // 5bytes  first:flag,second to five:data
#define EEROM_ADD_DATE 22       //存放开始计电能 的日期时间地址,连续6个字节
//eerom address of saveing parameter
#define EEROM_ADD_FLA  29
#define EEROM_ADD_PAR  30       //存放参数的起始地址,第间二个字节存放一个12BIT参数
#define EEROM_ADD_CRC  90				//存放参数的校验和
//save ok define
#define SAVE_OK 0XAA            //接下来四个字节的数据有效标志



//register  name     address    length

//read only register
#define ADD_AWATTHR   0X01      //16  Phase A Watt-Hour accumulation
#define ADD_BWATTHR   0X02      //16  Phase B Watt-Hour accumulation
#define ADD_CWATTHR   0X03      //16  Phase C Watt-Hour accumulation

#define ADD_AVARHR    0X04      //16  Var-Hour accumulation register for phase A
#define ADD_BVARHR    0X05      //16  Var-Hour accumulation register for phase b
#define ADD_CVARHR    0X06      //16  Var-Hour accumulation register for phase c

#define ADD_AVAHR     0X07      //16
#define ADD_BVAHR     0X08      //16
#define ADD_CVAHR     0X09      //16


#define ADD_AIRMS     0X0A      //24  Current register
#define ADD_BIRMS     0X0B      //24
#define ADD_CIRMS     0X0C      //24

#define ADD_AVRMS     0X0D      //24  Voltage register
#define ADD_BVRMS     0X0E      //24
#define ADD_CVRMS     0X0F      //24
//end of read only register
#define ADD_COMPMODE  0x16      //8   R/W DEFAULT VALUE 0x1C

#define ADD_MASK      0X18      //24	R/W IRQ Mask register,determines if an interrup event will generate an active-low output at IRQ pin

#define ADD_RSTATUS   0X1A      //24  READ ONLY,CLEANED ZERO after a read operation


#define ADD_GAIN      0X23      //8		R/W 0~1bit used to select the Gain of the current channels inputs

#define ADD_WDIV      0X42      //8   R/W Active Energy register divider
#define ADD_VARDIV    0X43      //8   R/W Apparent Energy register divider
#define ADD_VADIV     0X44      //8   R/W Apparent Energy register divider

#define ADD_FREQ      0X10      //12  Read only,frequency of the line input estimated by zero-crossing processing


#define ADD_LCYCMODE  0X17      //8   R/W bit7
#define ADD_MMODE     0X14      //8   R/W bit01
///////////////////////////////////////////////////////////////////////////////////////////
#define BaseAdd       41

extern bit bit_1s; //1s钟标志,在时钟中断函数中置位

void clean_energy(void);
void check_ade7758(void);
///////////////////////////////////////////////////////////////////////////////////////////
//                        MCU与ADE7758的接口函数                                         //
///////////////////////////////////////////////////////////////////////////////////////////

//接口信号线
sbit CSADE7753_A = P1^5;//ADE7758的片选信号
sbit SSDO        = P1^7;
sbit SSCK        = P1^3;
sbit SSDI        = P1^4;
//接口信号线

/*****************************************************************************************
                          延时函数
时间:40uS                         
******************************************************************************************/
void delay10us()
{
	uchar loop;
	for(loop = 0;loop < 10;loop ++)
	{
		_nop_();
	}
}

/******************************************************************************************
                         7758写数据函数
入口参数:type:目标寄存器的地址
          wdata:写进寄存器的内容
          databit:目标寄存器的宽度
出口参数:NULL
返回值:NULL
******************************************************************************************/
void write7753(unsigned char type,unsigned int wdata,unsigned char databit)
{
	unsigned char loop = 0;

	type = type & 0x7F;
	type = type | 0x80;
	for(loop = 0; loop < 8; loop++)
	{
		SSCK = 1;
		_nop_();
		SSDI = type & 0X80;
		_nop_();
		SSCK = 0;
		_nop_();
		type = (type << 1);
	}//end of for()
	
	delay10us();
	
	for(loop = 0; loop < databit; loop++)
	{
		SSCK = 1;
		_nop_();
		SSDI = wdata & 0X8000;
		_nop_();
		SSCK = 0;
		_nop_();
		wdata = (wdata << 1);
	}//end of for()
	
}//end of write7753()

/*******************************************************************************************
                          7758写寄存器函数
入口参数:type:目标寄存器的地址
          databit:目标寄存器的宽度
出口参数:指定寄存器的内容
返回值:指定寄存器的内容
********************************************************************************************/
unsigned long read7753(unsigned char type,unsigned char databit)
{
	unsigned char loop = 0;
	unsigned long  rtdata = 0;
	//ade7758 7 bits address
	//ade7754 6 bits address
	type = type & 0x7F;
	type = type | 0x00;
	for(loop = 0;loop < 8;loop ++)
	{
	 	SSCK = 1;
   	_nop_();
  	SSDI = type & 0X80;
  	_nop_();
		SSCK = 0;
  	_nop_();
  	type = (type << 1);
	}
	delay10us();
	for(loop = 0;loop < databit;loop ++)
	{
	 	SSCK = 1;
  	_nop_();
		rtdata = (rtdata << 1);
  	if(SSDO) rtdata += 1;
   	_nop_();
   	SSCK = 0;
  	_nop_();
	}
	return(rtdata);
}//end of read7753()

/*****************************************************************
             7758写数据函数
入口参数:type:目标寄存器的地址
          wdata:写进寄存器的内容
          databit:目标寄存器的宽度
出口参数:NULL
返回值:NULL

注意写入数据的数据类型对写入数据的影响,参数:wdata
wdata数据类型为整型,2个字节当形参的实参为字符型,1个字节时要先将
它强制转换为整型再左移8位,databit为8。当wdata字长为12位时,必须先
将它扩展为16位,并且第一字节的高半字节无任何意义.
******************************************************************/
void write7753a(unsigned char type,unsigned int wdata,unsigned char databit)
{
	//EA = 0;//disable interrupt
	CSADE7753_A = 1;        
	SSCK = 0;
	SSDI = 0;
	SSDO = 0;
	CSADE7753_A = 0;
	write7753(type,wdata,databit);
	CSADE7753_A = 1;
	//EA = 1;//enable interrupt
}//end of write7753a()

/*******************************************************************************************
                          7758写寄存器函数
入口参数:type:目标寄存器的地址
          databit:目标寄存器的宽度
出口参数:指定寄存器的内容
返回值:指定寄存器的内容

该函数与 read7753(unsigned char type,unsigned char databit)的区别在于操作ADE7758之前先确定一下
SPI接口的各个状态,所以当需要从ADE7758中读出一个数据时不要直接调用
read7753a(unsigned char type,unsigned char databit)而是直接调用本函数。
********************************************************************************************/
unsigned long read7753a(unsigned char type,unsigned char databit)
{
	unsigned long  rtdata = 0;
	//EA = 0;//disable interrupt
	CSADE7753_A = 1;         
	SSCK = 0;
	SSDI = 0;
	SSDO = 0;
	CSADE7753_A = 0;
	rtdata = read7753(type,databit);
	CSADE7753_A = 1;
	//EA = 1;//enable interrupt
	return(rtdata);
}//end of read7753a()



/***************************************************************************************************************
                     从ADE7758中读出所有的电参量,并做相应的处理
因为本模块起始是用P89C51RC2HBP芯片,由于没有扩展数据存储器,资源有限,为了充分利用有限的资源,设计了以下的共用体
数据结构。
功能:
1、在校准模式下:从ADE7758中读取电压电流和功率值,并发给上位机,上位机运算后再校准参数发回来(通讯方面请参考RS232模块)
2、在正常工作模式下:读取电压电流电能值等电参量,并等待上位机发指令读取。电参量就存放于以下共用体中。

注:在MCS51单片机中,共用体数据的存放与386机器有点区别,MCS51的一个共用体中高位地址存放高位数据,低位地址存放低位数据
386机器刚好相反。所以在使用共用体与上位机通讯时要注意这个问题。
****************************************************************************************************************/
#define DIVI_VALUE 30000 //30千瓦以上时,将分频器重新设值
#define ERR_VOLTAGE  250 //当ADE7758受干扰导校准参数混乱而检测不准

//整型数和字符型数的共用体
union int_char
{
	uint data16;
	uchar data8[2];
};

//长整型数和字符型数的共用体
union long_char
{
	ulong data32;
	uchar data8[4];
};

//通讯时的信息头结构(MODBUS协议头)
struct com
{
	uchar local_add;//本机地址
	
	uchar funtion_code;//功能码
	
	uchar reg_num;//寄存器个数
};

//保存所有处理过的从7758中来的电参量,也是一个在正常模式下的通讯发送缓冲区
struct all_data
{
	struct com          com_head;//通讯时的响应帧的开头   3bytes
	
	union int_char      voltage[4];//三相电压值 + 平均值                8bytes
	
	union int_char      voltageLL[4];//三相线电压压值 + 平均值          8bytes
	
	union int_char      current[4];//三相电流值 + 平均值                8bytes
	
	union int_char      watt[4];//三相有功功率,最后一个是三相总和        8bytes
	
	union int_char      var[4];//三相无功功率,最后一个是三相总和         8bytes
	
	union int_char      va[4];//三相视在功率,最后一个是三相总和          8bytes
	
	union long_char     watt_hour[4];//三相有功电能值,最后一个是三相总和,初始化时应该将E2PROM中的数据读出来。16bytes
	
	union long_char     var_hour[4];//三相无功电能值,最后一个是三相总和  16bytes
	
	union long_char     va_hour[4];//三相视在电能值,最后一个是三相总和   16bytes
	
	union int_char      sys_hz;//系统频率                                 2bytes
	
	union long_char     surge;//浪涌个数                                  4bytes
	
	union int_char      com_crc;//通讯时存放校验和                        2bytes
	
	//整个结构体的长度为95字节        //+12bytes
};

//在校准模式下的只读寄存器内容,与上面的结构体内存共用
struct adjust_datar
{
	struct com           com_head;//通讯时的响应帧的开头
	
	union long_char     voltage[3];
	
	union long_char     current[3];
	
	union int_char      watt[3];
	
	union int_char      var[3];
	
	union int_char      va[3];
	
	union int_char       com_crc;//通讯时存放校验和
	//以上部分不只作为只读数据缓冲,还作为校准模式下的通讯缓冲,总长度为:3+36+2+6
};

//在校准模式下的只写寄存器内容,与上面的结构体内存共用
struct adjust_dataw
{
	union int_char     voltage[3];
	
	union int_char     current[3];
	
	union int_char      watt[3];
	
	union int_char      var[3];
	
	union int_char      va[3];
	
	//总长度为:30字节
};


//在校准模式下存放电参量的原始数据
struct adjust_data
{
	struct adjust_dataw  write_data;//存放修正参数,最后将写入E2PROM     30
	
	struct adjust_datar  read_data;//存放原始数据
	
};

//存放正常模块和校准模式下的数据,采用共用体以节省存储空间
union all
{
	struct all_data       working;//正常工作模式下存放的电参量  95
	
	struct adjust_data    adjusting;//校准模式下存放的数据      65
	
	uint serie_data16[47];           //连续的数据16位           94
	
	uchar serie_data8[107];           //连续的数据8位            95
	
	uchar serie1_data8[41];           //连续的数据8位,communication   41
	
}xdata rwdata;
//整个结构体的长度为107字节

uchar data counter[3] = {0,0,0};//滤波计数器
union long_char xdata energy[9];//用于累加电能值 36

unsigned long xdata i_buffer[5][3];        //用于原始电压电流的积分虑波
unsigned long xdata v_buffer[5][3];

union int_char  xdata vo_buffer[5][3];//用于电压电流的积分虑波 36

⌨️ 快捷键说明

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