georgezz007 发表于 2008-10-8 15:21:21

交流电参数测量 之 CS5460A程序实例【恢复】

    在OURAVR潜水一年多,学到了很多东西。下面发布一个自己一个作品中部分程序,希望能给有需要的朋友一些帮助。由于水平有限,程序可能写得不是非常漂亮,望众大侠包涵啦。也希望阿莫能给我加分啦。    还要说明的是,为提高编程效率,程序中利用了avrlib函数库。    使用中也发现了一些问题,希望高手们指教:执行完偏置寄存器校准和增益寄存器校准后,将得到的24位AD值按手册上的方法处理后仍得不到实际值。但是该值与实际值有很好的线性关系,因此我就是利用这一线性关系,进行线性拟合,得到最终结果。    下面直接贴一些程序段出来SHOW一下:/*--------------------------------------------------------------------------------------------------------编译平台:winavr2007MCU:ATMEGA32作者:张子佑时间:2008年10月8日功能:运用CS5460A测量交流电压、电流有效值。根据实际需要,还可以测量能量,电压、电流瞬时值。功率因素也可通过计算获得。-----------------------------------------------------------------------------------------------------------*///----------------------------------------------------------------#include<util/delay.h>#include "avrlib/global.h"#include "avrlib/rprintf.h"#include "avrlib/ks0108.h"#include "avrlib/glcd.h"#include "ks0108conf.h"#include "avrlib/timer.h"//--------CS5460 CODE ----------------------------/*CS5460内部寄存器的低六位*/#define CONFIG            0x00  //配置寄存器#define CYCLE_COUNT       0x0A  //周期计数 #define LAST_CURRENT      0x0E  //上一次电流值#define LAST_VOLT         0x10  //上一次电压值#define LAST_POWER        0x12  //上一次的功率值#define LAST_ENERGY       0x14  //上一周期的总能量值#define LAST_CURRENT_RMS  0x16  //上一周期电流有效值#define LAST_VOLT_RMS     0x18  //上一周期电压有效值#define STATUS            0x1E  //状态寄存器#define MASK              0x34  //中断屏蔽寄存器#define VOLT_DC_OFFSET    0X06  //电压通道 直流 偏置寄存器#define CURRENT_DC_OFFSET 0X02  //电流通道 直流 偏置寄存器#define VOLT_AC_OFFSET    0X22  //电压通道 交流 偏置寄存器#define CURRENT_AC_OFFSET 0X20  //电流通道 交流 偏置寄存器/*直流偏置(已校准)*/#define CURRENT_DC      0xCC4ADD //电压偏置   #define VOLT_DC         0X331396 //电流偏置/*寄存器的读写*/#define READ  0x00    //读#define WRITE 0x40    //写/*各寄存器复位后的初始值*/#define CONFIG_INIT      0x000001   //配置寄存器#define STATUS_INIT      0x000001   //状态寄存器#define MASK_INIT        0x000000   //中断屏蔽寄存器#define CYCLE_COUNT_INIT 0x000FA0   //周期计数寄存器/*定义以上寄存器的初始化后的值*/#define  CONFIG_DATA      0x0010E1  //软件复位#define  CALCULATE_DOWN   0x800000  //数据已经就绪,转换结束#define  LOW_POWER        0x000004  //检测到低电源#define  WDT              0X000020  //能量超过5秒未被读取,该位置位 /*定义其他命令*/#define  POWER_OFF_CTRL  0X88  //掉电控制#define  STANDERED_CTRL  0XC0  //标准控制#define  TRANSFORM_START 0Xe8 //开始转换,执行连续计算周期/*定义端口与CS5460的连接*/#define  SDI_H()    PORTB |= _BV(1) #define  SDI_L()    PORTB &= ~BV(1)#define  SDO        ((PINB & _BV(4))==_BV(4))#define  EN_CS()    PORTB &= ~_BV(3)#define  UN_CS()    PORTB |= _BV(3)#define  SCLK_H() PORTB |= _BV(5)#define  SCLK_L() PORTB &= ~_BV(5)//--------全局变量定义-------------------------------------u08 buf;float CurrentRMS,VoltRMS,POWER,ENERGY, COS;//--------------函数声明----------------------------------------void Write_CS5460A(u08 *ptr,u08 n);void Read_CS5460A(u08 reg,u08 *ptr);//---------CS5460端口初始化---------------------void InitPort(void){        DDRB |= _BV(1)+_BV(3)+_BV(5);                PORTB &= ~_BV(4);        DDRB &= ~_BV(4);}//-------------CS5460 SPI读写-------------------------void Write_CS5460A(u08 *ptr,u08 n){  s08 i=0,j=0;  SCLK_L();    EN_CS();  for(j=n;j>=1;j--)  {        for(i=7;i>=0;i--)      {          SCLK_L();          if( ((*ptr)&(1<<i)) != 0 )                SDI_H();          else               SDI_L();      _delay_us(5);      SCLK_H();      _delay_us(5);      }      ptr++;   }//  if(j==0) UN_CS();}void Read_CS5460A(u08 reg,u08 *ptr){    s08 i,j;    EN_CS();    *ptr=reg;      Write_CS5460A(ptr,1);    ptr++;    SDI_H();    for(i=3;i>0;i--)    {        for(j=7;j>=0;j--)        {            SCLK_L();            _delay_us(5);                        if(SDO == 1)                *ptr |= (1<<j);            else                *ptr &= ~(1<<j);                        if(j==0)                SDI_L();            else                 SDI_H();                        _delay_us(5);            SCLK_H();            _delay_us(5);        }        ptr++;    }    UN_CS();}  void Clear_DRDY(void) {     buf=0x5e;     buf=0xff;     buf=0xff;     buf=0xff;     Write_CS5460A(buf,4);      }void Wait_DRDY_High(void) {      while(1)     {          Read_CS5460A(0x1e,buf);           if( (buf&0x80) != 0 ) break;       } } //------------5460初始化-----------------------void Init5460(void){    _delay_ms(5);          buf=0xff;            //SYNC1     buf=0xff;            //SYNC1     buf=0xff;            //SYNC1     buf=0xfe;            //SYNC0     Write_CS5460A(buf,4);   // 3 1 1 0         buf=0x40;             buf=0x00;            //GI=1      buf=0x10;              buf=0x61;            //DCLK=MCLK/1,高通         Write_CS5460A(buf,4);   //写配置寄存器       /**************************************************/    buf=WRITE|0x20;             buf=0x3D;              buf=0xC2;     buf=0x5C;               Write_CS5460A(buf,4);   //电流 交流偏置 校准寄存器      buf=WRITE|0x22;             buf=0x1F;            buf=0xBB;     buf=0x65;                   Write_CS5460A(buf,4);   //电压 交流偏置 校准寄存器   /***************************/    buf=WRITE|0x04;             buf=0x29;              buf=0x71;     buf=0xCA;               Write_CS5460A(buf,4);     //电流增益校准寄存器**    buf=WRITE|0x08;             buf=0x40;                buf=0x96;     buf=0xD3;                   Write_CS5460A(buf,4);     //电压增益校准寄存器**    buf=0x5e;              buf=0xF0;     buf=0x00;     buf=0x00;     Write_CS5460A(buf,4);  //清除状态寄存器     buf=0x74;                     buf=0x80; //DRDY    buf=0x00;     buf=0x00;     Write_CS5460A(buf,4);   //写中断屏蔽寄存器           buf=0x78;    buf=0x00;    buf=0x00;    buf=0x00; //缺省值    Write_CS5460A(buf,4); //写控制寄存器    buf=0x4c;    buf=0x00;    buf=0x34;    buf=0x9C;    Write_CS5460A(buf,4); //写EOUT 脉冲输出寄存器        buf=0x4A;    buf=0x00;    buf=0x01;           //每秒钟计算20 次,N=400     buf=0x90;    Write_CS5460A(buf,4); //写CYCLE COUNT 寄存器            Read_CS5460A(0x1e,buf); //读状态寄存器    buf=0X5E;    Write_CS5460A(buf,4); //写状态寄存器            buf=0xe8;    Write_CS5460A(buf,1); //启动CS5460A}/*-------------------------------------------------------------------------功能:读交流电压寄存器,并对数据进行处理和校准,返回交流电压有效值。需根据实际测量范围调整。---------------------------------------------------------------------------*/double CS5460_GetVoltRMS(void){        float G=1.0/2.0,temp=0.0;    Read_CS5460A(READ|LAST_VOLT_RMS,buf);    for(u08 i=1;i<=3;i++)    {        for(s08 j=7;j>=0;j--)        {            if( (buf&(1<<j)) != 0 )                temp+=G;            G = G/2.0;        }    }        //软件校准    VoltRMS = 20*temp/0.6;         VoltRMS = VoltRMS*1.542*0.9864+0.332;        return VoltRMS;}        /*--------------------------------------------------------------------------------功能:读交流电流寄存器,并对数据进行处理和校准,返回交流电流有效值。需根据实际测量范围调整。-----------------------------------------------------------------------------------*/double CS5460_GetCurrentRMS(void){        float G=1.0/2.0,temp=0.0;                Read_CS5460A(READ|LAST_CURRENT_RMS,buf);    for(u08 i=1;i<=3;i++)    {        for(s08 j=7;j>=0;j--)        {            if( (buf&(1<<j)) != 0 )                temp+=G;            G = G/2.0;        }    }        //软件校准    CurrentRMS =7.8*temp/0.6 ;        CurrentRMS = 5.5203*CurrentRMS+0.0873;        return CurrentRMS;}//-----------软件滤波函数----------------------------------------------#define N 24#define         CS_VRMS  0#define  CS_IRMS  1double filter(u08 CS){   u08 count,i,j;   double value_buf,temp;   double  sum=0;   for  (count=0;count<N;count++)   {                if(CS==CS_VRMS)                        value_buf = CS5460_GetVoltRMS();                else                         value_buf = CS5460_GetCurrentRMS();   }   for (j=0;j<N-1;j++)   {      for (i=0;i<N-j-1;i++)      {         if ( value_buf>value_buf )         {            temp = value_buf;            value_buf = value_buf;             value_buf = temp;         }      }   }   for(count=4;count<N-4;count++)      sum += value_buf;   return (sum/(N-8));}int main (void){        double VRMS=0,VRMSNew=0;        double IRMS=0,IRMSNew=0;        glcdInit();        // send rprintf output to lcd display    rprintfInit(glcdWriteChar);        // perform basic functionality test        glcdSetAddress(4,LINE2);        rprintf("Welcome to george's");        glcdSetAddress(60,LINE4);        rprintf("workspace");        _delay_ms(1000);                glcdClearScreen();        glcdSetAddress(0,LINE1);        rprintf("VRMS=");        glcdSetAddress(0,LINE2);        rprintf("IRMS=");        glcdSetAddress(70,LINE1);        rprintf("(V)");        glcdSetAddress(70,LINE2);        rprintf("(A)");                InitPort();        Init5460();                while(1)        {                                VRMSNew = filter(CS_VRMS);                if( (VRMSNew-VRMS>0.03)||(VRMS-VRMSNew>0.03) )                {                        VRMS = VRMSNew;                }                                IRMSNew = filter(CS_IRMS);                if( (IRMSNew-IRMS>0.003)||(IRMS-IRMSNew>0.003) )                {                        IRMS=IRMSNew;                }                                glcdSetAddress(30,LINE1);                rprintfFloat(4,  VRMS);                glcdSetAddress(30,LINE2);                rprintfFloat(4,  IRMS);                _delay_ms(50);        }}点击此处下载 ourdev_443670.rar(文件大小:243K) (原文件名:CS5460A.rar) 

本贴被 georgezz007 编辑过,最后修改时间:2008-10-08,15:25:12.

dxdq 发表于 2008-10-8 15:40:20

我也在用5460,刚开始用,感觉国产跟进口的片子性能还是有差距,主要是零点偏移比较大,不进行校准不能用,进口的不进行校准零点输出还可以接受,毕竟差两块钱。

georgezz007 发表于 2008-12-26 10:04:25

    自从发了这个帖子后,很多朋友通过QQ与我交流。    惭愧的是,由于本人水平的问题,许多问题也许没能给予较满意的答复。其实当初使用这块芯片时,没有全面的理解它,我只关注了我所需要的部分。    我对于CS5460的理解程度,只是了解到了:            1.其通信方法;            2.初始化及校准过程;            3.读相关寄存器以获取需要的结果。    我发此贴的目的,是在我实际做的时候,感觉芯片的初始化和校准过程比较繁琐,稍不注意可能通信方面就会出问题,所以分享一些我的实际经验,以供参考。    现在,我可能没太大机会再使用该芯片了。希望对于这块芯片使用上有问题的朋友今后加我QQ的时候要慎重,当然我也十分欢迎大家相互学习。但是说实话,我的QQ上人突然暴多起来,还是有些不便,希望体谅。

fanglin0921 发表于 2008-12-11 00:52:18

ligongchen 发表于 2008-12-10 10:05:20

ding十分感谢

xk2yx 发表于 2008-10-10 21:02:33

不错

georgezz007 发表于 2008-10-10 20:57:10

只是做一个高功率因素电源(学生作品),加一个交流电参数测量是增加亮点。因为需要测功率因素,所以选择了这块芯片,顺便将交流电压和交流电流一起显示。希望拿到高分呀。

myworkmail 发表于 2008-10-10 15:40:45

早就用CS5463了,LZ是做什么的?多功能表?配变?

georgezz007 发表于 2008-10-10 15:31:00

我的QQ号是: 569536244

yefengzhoufeng 发表于 2008-10-10 15:23:13

刚刚使用CS5460A,有好些不懂的地方,能不能请教楼主,能给个QQ或者MSN么,谢谢,或者您加我QQ973391979 等待您的消息,谢谢,很着急

georgezz007 发表于 2008-10-9 10:01:57

查看一下它的数据手册就行了。这里有一些我编程时的参考资料。点击此处下载 ourdev_444710.rar(文件大小:913K) (原文件名:cs5460a资料.rar) 

weiweiliou 发表于 2008-10-9 09:17:29

好东西,有应用电路图吗?

lcqqcl 发表于 2008-10-9 08:36:16

记号

dxdq 发表于 2008-10-9 07:17:07

电能分析可以用炬力的片子,好像是7022,带谐波分析,估计够用了,我买的5460国产6元,进口8元,不含税。

lihuyong 发表于 2008-10-9 00:27:16

含6个点的税不到10元,大概是八九元电能分析的不能够,只能够测量单相的大部分电参量

gerbee 发表于 2008-10-9 00:22:50

这东西大概多少钱一片?  电能分析是不是都用得他?

georgezz007 发表于 2008-10-8 21:05:02

知道呀,但是没有试过。好像是要把内部的高通滤波器关掉,再进行直流增益校准过程。但是有一点,采样输入电压有限制,所以若当做24位的AD用恐怕不是很好。

thoro_avr 发表于 2008-10-8 18:05:43

顶一下,楼主知道5460 能测直流电压电流吗?

本贴被 thoro_avr 编辑过,最后修改时间:2008-10-08,18:05:57.

yanrz 发表于 2009-5-26 19:01:53

版主能否将原理图一并发上来看看参考下?

hehe611 发表于 2010-1-22 17:23:15

楼主的程序中好象并没有校准操作啊~~~~~~~

sdmcu51 发表于 2010-2-2 14:45:11

这程序技术含量太高,调试2天未果,很是郁闷

snakeblue 发表于 2010-7-13 11:25:26

请教楼主
数据处理部分
//软件校准
    VoltRMS = 20*temp/0.6;
        VoltRMS = VoltRMS*1.542*0.9864+0.332;
        return VoltRMS;
能解释下吗       感谢

另外   代码写的不错赞一个

georgezz007 发表于 2010-7-14 10:41:21

各位朋友,十分抱歉的告诉大家。小弟我已经不从事单片机方面的工作。平时因为工作繁忙,很多朋友通过qq向我询问有关问题都无法进行答复,希望见谅。

dianqing 发表于 2010-8-20 12:05:44

天啊!看看大家把楼主逼的。。。

gwb721123 发表于 2011-2-24 15:44:32

cs5460A   电流输入端下限能能测到多少mV

haitianshenyun 发表于 2011-2-24 20:07:53

请教楼主
数据处理部分
//软件校准
    VoltRMS = 20*temp/0.6;
VoltRMS = VoltRMS*1.542*0.9864+0.332;
return VoltRMS;
能解释下吗       感谢

另外   代码写的不错赞一个

wdmfhvk 发表于 2011-5-7 22:02:05

taobao上有现成的方案,对于做产品会,节约很多时间与精力.http://shop59944437.taobao.com/

qsm627421059 发表于 2011-8-1 13:28:19

谁帮帮我,cs5460读不出数据

qsm627421059 发表于 2011-8-4 12:04:47

谁能告诉我读的数据怎么转换成实际值

fxk1220 发表于 2012-11-2 12:49:52

qsm627421059 发表于 2011-8-4 12:04 static/image/common/back.gif
谁能告诉我读的数据怎么转换成实际值

你好,你读出数据了吗?我这里还一直读不出数据,不知道为什么,能否请教下
页: [1]
查看完整版本: 交流电参数测量 之 CS5460A程序实例【恢复】