📄 ade7753.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 + -