交流电参数测量 之 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. 我也在用5460,刚开始用,感觉国产跟进口的片子性能还是有差距,主要是零点偏移比较大,不进行校准不能用,进口的不进行校准零点输出还可以接受,毕竟差两块钱。 自从发了这个帖子后,很多朋友通过QQ与我交流。 惭愧的是,由于本人水平的问题,许多问题也许没能给予较满意的答复。其实当初使用这块芯片时,没有全面的理解它,我只关注了我所需要的部分。 我对于CS5460的理解程度,只是了解到了: 1.其通信方法; 2.初始化及校准过程; 3.读相关寄存器以获取需要的结果。 我发此贴的目的,是在我实际做的时候,感觉芯片的初始化和校准过程比较繁琐,稍不注意可能通信方面就会出问题,所以分享一些我的实际经验,以供参考。 现在,我可能没太大机会再使用该芯片了。希望对于这块芯片使用上有问题的朋友今后加我QQ的时候要慎重,当然我也十分欢迎大家相互学习。但是说实话,我的QQ上人突然暴多起来,还是有些不便,希望体谅。 强 ding十分感谢 不错 只是做一个高功率因素电源(学生作品),加一个交流电参数测量是增加亮点。因为需要测功率因素,所以选择了这块芯片,顺便将交流电压和交流电流一起显示。希望拿到高分呀。 早就用CS5463了,LZ是做什么的?多功能表?配变? 我的QQ号是: 569536244 刚刚使用CS5460A,有好些不懂的地方,能不能请教楼主,能给个QQ或者MSN么,谢谢,或者您加我QQ973391979 等待您的消息,谢谢,很着急 查看一下它的数据手册就行了。这里有一些我编程时的参考资料。点击此处下载 ourdev_444710.rar(文件大小:913K) (原文件名:cs5460a资料.rar) 好东西,有应用电路图吗? 记号 电能分析可以用炬力的片子,好像是7022,带谐波分析,估计够用了,我买的5460国产6元,进口8元,不含税。 含6个点的税不到10元,大概是八九元电能分析的不能够,只能够测量单相的大部分电参量 这东西大概多少钱一片? 电能分析是不是都用得他? 知道呀,但是没有试过。好像是要把内部的高通滤波器关掉,再进行直流增益校准过程。但是有一点,采样输入电压有限制,所以若当做24位的AD用恐怕不是很好。 顶一下,楼主知道5460 能测直流电压电流吗?
本贴被 thoro_avr 编辑过,最后修改时间:2008-10-08,18:05:57. 版主能否将原理图一并发上来看看参考下? 楼主的程序中好象并没有校准操作啊~~~~~~~ 这程序技术含量太高,调试2天未果,很是郁闷 请教楼主
数据处理部分
//软件校准
VoltRMS = 20*temp/0.6;
VoltRMS = VoltRMS*1.542*0.9864+0.332;
return VoltRMS;
能解释下吗 感谢
另外 代码写的不错赞一个 各位朋友,十分抱歉的告诉大家。小弟我已经不从事单片机方面的工作。平时因为工作繁忙,很多朋友通过qq向我询问有关问题都无法进行答复,希望见谅。 天啊!看看大家把楼主逼的。。。 cs5460A 电流输入端下限能能测到多少mV 请教楼主
数据处理部分
//软件校准
VoltRMS = 20*temp/0.6;
VoltRMS = VoltRMS*1.542*0.9864+0.332;
return VoltRMS;
能解释下吗 感谢
另外 代码写的不错赞一个 taobao上有现成的方案,对于做产品会,节约很多时间与精力.http://shop59944437.taobao.com/ 谁帮帮我,cs5460读不出数据 谁能告诉我读的数据怎么转换成实际值 qsm627421059 发表于 2011-8-4 12:04 static/image/common/back.gif
谁能告诉我读的数据怎么转换成实际值
你好,你读出数据了吗?我这里还一直读不出数据,不知道为什么,能否请教下
页:
[1]