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

📄 ade7753.c

📁 电能计量芯片ADE7753的c51程序
💻 C
字号:

/********************************************************/
/* 硬件操作程序						*/
/* MCU 型号: upsd32xx					*/
/* MCU时钟频率:  22.1184MHz				*/
/* ADE7753时钟频率: 3.579545 MHz			*/
/* 开发环境: Keil C51 V7.09				*/
/* 开发日期: 2004.03.9-					*/
/* 程序编写: jl_mx					*/
/********************************************************/

/*define library */
#include "common.h"
#ifndef _UPSD_H_
	#include <at89x52.h>
#endif
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include <intrins.h>
#include <string.h>

//ade7753、63中的寄存器名称及地址
//		寄存器		地址
#define WAVEFORM	0x01 
#define AENERGY		0x02 
#define RAENERGY	0x03 
#define LAENERGY	0x04 
#define VAENERGY	0x05 
#define RVAENERGY	0x06 
#define LVAENERGY	0x07 
#define RESERVED	0x08 
#define MODE		0x09 
#define IRQEN		0x0A 
#define STATUS		0x0B 
#define RSTSTATUS	0x0C 
#define CH1OS		0x0D 
#define CH2OS		0x0E 
#define GAIN		0x0F 
#define PHCAL		0x10 
#define APOS		0x11 
#define WGAIN		0x12 
#define WDIV		0x13 
#define CFNUM		0x14 
#define CFDEN		0x15 
#define IRMS		0x16 
#define VRMS		0x17 
#define IRMSOS		0x18 
#define VRMSOS		0x19 
#define VAGAIN		0x1A 
#define VADIV		0x1B 
#define LINECYC		0x1C 
#define ZXTOUT		0x1D 
#define SAGCYC		0x1E 
#define SAGLVL		0x1F 
#define IPKLVL		0x20 
#define VPKLVL		0x21 
#define IPEAK		0x22 
#define RSTIPEAK	0x23 
#define VPEAK		0x24 
#define RSTVPEAK	0x25 
#define TEMP		0x26 
#define PERIOD		0x27 
#define TMODE		0x3D 
#define CHKSUM		0x3E 
#define DIEREV		0x3F 

//定义对应地址中寄存器的字节数
char	code reg_len[]={
//			0 1 2 3 4 5 6 7 8 9 A B	C D	E F
/*0x0	*/  0,3,3,3,3,3,3,3,3,2,2,2,2,1,1,1,
/*0x10	*/	1,2,2,1,2,2,3,3,2,2,2,1,2,2,1,1,
/*0x20	*/	1,1,3,3,3,3,1,2,0,0,0,0,0,0,0,0,
/*0x30	*/	0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,
};

//定义可读写的寄存器,标定时需要保存的寄存器可定义再此处,顺序不限。
char	code wr_rd_reg[]={
MODE,
IRQEN,
CH1OS,	
CH2OS,	
GAIN,	
PHCAL,	
APOS,	
WGAIN,	
WDIV,	
CFNUM,	
CFDEN,	
IRMSOS,	
VRMSOS,	
VAGAIN,	
VADIV,	
LINECYC,	
ZXTOUT,	
SAGCYC,	
SAGLVL,	
IPKLVL,	
VPKLVL,	
TMODE,	
};

//用于读取寄存器列表
char code rd_reg[]={
 WAVEFORM,
 AENERGY,	
 RAENERGY,
 LAENERGY,
 VAENERGY,
 RVAENERGY,
 LVAENERGY,
 RESERVED,
 MODE,	
 IRQEN,	
 STATUS,	
 RSTSTATUS,
 CH1OS,	
 CH2OS,	
 GAIN,	
 PHCAL,	
 APOS,	
 WGAIN,	
 WDIV,	
 CFNUM,	
 CFDEN,	
 IRMS,	
 VRMS,	
 IRMSOS,	
 VRMSOS,	
 VAGAIN,	
 VADIV,	
 LINECYC,	
 ZXTOUT,	
 SAGCYC,	
 SAGLVL,	
 IPKLVL,	
 VPKLVL,	
 IPEAK,	
 RSTIPEAK,
 VPEAK,	
 RSTVPEAK,
 TEMP,	
 PERIOD,	
 TMODE,	
 CHKSUM,	
 DIEREV,	
};


typedef	struct{
	long	waveform;		//波形寄存器电压电流
	long	anergy;			//有功功率
	long	ranergy;		//有功功率,读取后自动清零
	long	laenergy;		//线累计有功功率,N个lincyc半周期上的累计值
	ulong	vaenergy;		//视在功率
	ulong	rvaenergy;		//视在功率,读取后自动清零
	ulong	lvaenergy;		//线视在功率,N个lincyc半周期上的累计值
	long	lvarenergy;		//
	uint	mode;			//模式寄存器,配置采样速率、校准模式、滤波使能等,任何时间都能读取。
	uint	irqen;			//中断使能寄存器
	uint	status;			//中断状态寄存器
	uint	rststatus;		//中断状态寄存器,读取后自动清零
	char	ch1os;			//通道1的偏移调节寄存器
	char	ch2os;			//通道2的偏移调节寄存器
	uchar	gain;			//增益调节寄存器,控制CH1和CH2的通道增益
	char	phcal;			//相位校准寄存器,通道1和通道2之间的相位差,0x1d~0x21之间有效
	int		apos;			//有效功率偏移校准寄存器,可以移去较小的有效功率偏移量
	int		wgain;			//有功功率校准寄存器,偏移量+-50%
	uchar	wdiv;			//有功功率除数寄存器,有功功率=内部有功功率/wdiv
	uint	cfnum;			//CF频率除数分子寄存器,写入值可调节CF引脚输出频率
	uint	cfden;			//CF频率除数分母寄存器,写入值可调节CF引脚输出频率
	ulong	irms;			//CH1电流有效值
	ulong	vrms;			//CH2电压有效值
	int		irmsos;			//CH1电流有效值偏移量调节寄存器
	int		vrmsos;			//CH2电压有效值偏移量调节寄存器
	int		vgain;			//视在功率增益调节寄存器,+-50%范围
	uchar	vadiv;			//视在功率除数寄存器,视在功率=内部视在功率/vadiv
	uint	linecyc;		//线周期能力累计模式累计周期寄存器,能量累计半周期个数。
	uint	zxtout;			//过零超时寄存器,一段时间内在ch2上没有检测的过零信号,可产生中断
	uchar	sagcyc;			//线电压跌落周期寄存器,SAG信号输出前通道2的线电压跌落到saglvl的连续周期数
	uchar	saglvl;			//线电压跌落电平寄存器。
	uchar	ipklvl;			//通道1最大电流脉冲值
	uchar	vpklvl;			//通道2最大电压脉冲值
	ulong	ipeak;			//CH1电流最大值
	ulong	rstipeak;		//CH1电流最大值,读取后自动清零
	ulong	vpeak;			//CH2电压最大值
	ulong	rstvpeak;		//CH2电压最大值,读取后自动清零
	char	temp;			//温度寄存器,有最新的温度转换值
	uint	period;			//CH2的周期,由过零评估得来。最高位总为0
	uchar	tmode;			//测试模式寄存器
	uchar	chksum;			//校验和以上字节的和
	uchar	dierev;			//芯片硬件版本

}energy_registers;

typedef		union{
	long	long_val;
	int		int_val;
	char	char_val;
	char	rddata[4];			//最高字节
}valchange;

//#define CS7753		XBYTE[0X0302]			//ADE7753的片选
//#define CS25040		XBYTE[0X0303]			//FM25040的片选
sbit	SCLK	=P4^7;
sbit	DIN		=P3^5;
sbit	DOUT	=P4^5;

energy_registers xdata energy_reg;

//搜索reg_name在结构中的偏移量
uchar	wr_rdreg_os(uchar reg_name)
{uchar i=0,offset=0;
	while(i!=reg_name){
		if(reg_len[i]==3){
			offset+=4;
		}else{
			offset+=reg_len[i];
		}
		i++;
	}
	return offset;
}

void delay_us(uchar ts)
{
	while(ts)ts--;
}

char	ade7753_fm25040_cs;		//ade7753 fm25040芯片片选寄存器 0-19

//向ade7753中写入一个字节,命令或数据。
void	write_byte(uchar val)
{uchar i;
	for(i=0;i<8;i++){
		SCLK=1;
		DIN=0x80 & val;	
		SCLK=0;
		val=_crol_(val,1);
	}
}

//从ade7753中读取一个字节,状态或数据。
uchar 	read_byte(void)
{uchar i,j,val=0;
	for(i=0;i<8;i++){
		val=_crol_(val,1);
		SCLK=1;
		j=DOUT;
		SCLK=0;
		val=val|j;
	}
	return val;
}

//从ade7753中读取数据,可以是1~3个字节,由读取的寄存器决定。
//chipsel :指定读取ade7753的片选
//reg_name 要读取的寄存器名称既地址
long	read_operation(uchar chipsel,uchar reg_name)		//读取1~3个字节
{valchange data vc;
 char i;
 	i=reg_len[reg_name];	//取得需要读取的字节数
	CS7753=chipsel;			//片选使能
	write_byte(reg_name);	//将地址写入通讯寄存器
	switch(i){
		case 3:
			vc.rddata[1]=read_byte();		//最高字节
			vc.rddata[2]=read_byte();
			vc.rddata[3]=read_byte();
			break;
		case 2:								//低字节
			vc.rddata[0]=read_byte();
			vc.rddata[1]=read_byte();
			break;
		case 1:
			vc.rddata[0]=read_byte();
			break;
	}
	CS7753=0xff;			//片选失效
	SCLK=1; DIN=1;			//数据线置已知状态,为下一次的写命令准备。
	switch(i){
		case 3:
			if(vc.rddata[1]&0x80){		//处理符号位
				vc.rddata[0]=0xff;
			}else{
			 	vc.rddata[0]=0x00;
			}
			return vc.long_val;
		case 2:
			return vc.int_val;
		case 1:
			return vc.char_val;
			break;
	}
	return 0;
}

//向ade7753中写入数据,可以是1~2个字节,由写入的寄存器决定。
//chipsel :指定写入的ade7753片选
//reg_name 要写入的寄存器名称既地址
//dd :写入的数据
void	write_operation(uchar chipsel,uchar reg_name,int dd)		//读取1~2个字节
{valchange data vc;
 char i;
 	i=reg_len[reg_name];	//取得需要读取的字节数
	vc.int_val=dd;
	CS7753=chipsel;			//片选使能
	write_byte(0x80|reg_name);	//将地址写入通讯寄存器
	switch(i){
		case 2:
			write_byte(vc.rddata[0]);
			write_byte(vc.rddata[1]);
			break;
		case 1:
			write_byte(vc.rddata[0]);
			break;
	}
	CS7753=0xff;			//片选失效
	SCLK=1; DIN=1;			//数据线置已知状态,为下一次的写命令准备。
}

//将结构中的数据写入到ade7753可读写寄存器中,用于从FM25040中恢复标定参数
void	write_allreg(uchar chipsel )
{uchar i;
 int xdata *reg_ptr;
	for(i=0;i<sizeof(wr_rd_reg);i++){
		switch(reg_len[wr_rd_reg[i]]){
			case 1:
				reg_ptr=(char *)((char *)&energy_reg+wr_rdreg_os(wr_rd_reg[i]));
				break;
			case 2:
				reg_ptr=(int *)((char *)&energy_reg+wr_rdreg_os(wr_rd_reg[i]));
				break;
		}
		write_operation(chipsel,wr_rd_reg[i],*reg_ptr);
	}
}

//读出ade7753中的所有寄存器值,数据放入结构中。
void	read_allreg(uchar chipsel)
{uchar i;
 char xdata *char_ptr;
 int xdata *int_ptr;
 long xdata *long_ptr;
	for(i=0;i<sizeof(rd_reg);i++){
		switch(reg_len[rd_reg[i]]){
			case 1:	//字节
				char_ptr=(char *)((char *)&energy_reg+wr_rdreg_os(rd_reg[i]));
				*char_ptr=read_operation(chipsel,rd_reg[i]);
				break;
			case 2:
				int_ptr=(int *)((char *)&energy_reg+wr_rdreg_os(rd_reg[i]));
				*int_ptr=read_operation(chipsel,rd_reg[i]);
				break;
			case 3:
				long_ptr=(long *)((char *)&energy_reg+wr_rdreg_os(rd_reg[i]));
				*long_ptr=read_operation(chipsel,rd_reg[i]);
				break;
		}
	}
}

//测试程序
#if(1)
void	test_main()
{ long lval;
  ulong ulval;
  int   intval;
  uint  uintval=0;
  char  charval=0x55;
  uchar ucharval,ch=0,j=0;
  char	buff[10];

	while(1){
/*		for(j=1;j<0x40;j++){
			lval=read_operation(ch,j);
	//		lval=read_operation(ch,AENERGY);
	//		ulval=read_operation(ch,VAENERGY);
	//		intval=read_operation(ch,IRQEN);
	//		uintval=read_operation(ch,MODE);
	//		charval=read_operation(ch,CH1OS);
	//		ucharval=read_operation(ch,GAIN);
		}
*/
		ch=19;
		read_allreg(ch);
//		write_allreg(ch);
 		sequ_write(ch,&charval,uintval,1);
 		sequ_read(ch,buff,uintval,1);
		cursor(3,0);
		dprintf("chip=%bu addr=%u wr=%bu rd=%bu",ch,uintval,charval,buff[0]);
		if(++uintval>=512)uintval=0;
		if(++ch>19)ch=0;
	}
}
#endif

⌨️ 快捷键说明

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