|
在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[5];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[0]=0x5e; buf[1]=0xff; buf[2]=0xff; buf[3]=0xff; Write_CS5460A(buf,4); }void Wait_DRDY_High(void) { while(1) { Read_CS5460A(0x1e,buf); if( (buf[1]&0x80) != 0 ) break; } } //------------5460初始化-----------------------void Init5460(void){ _delay_ms(5); buf[0]=0xff; //SYNC1 buf[1]=0xff; //SYNC1 buf[2]=0xff; //SYNC1 buf[3]=0xfe; //SYNC0 Write_CS5460A(buf,4); // 3 1 1 0 buf[0]=0x40; buf[1]=0x00; //GI=1 buf[2]=0x10; buf[3]=0x61; //DCLK=MCLK/1,高通 Write_CS5460A(buf,4); //写配置寄存器 /**************************************************/ buf[0]=WRITE|0x20; buf[1]=0x3D; buf[2]=0xC2; buf[3]=0x5C; Write_CS5460A(buf,4); //电流 交流偏置 校准寄存器 buf[0]=WRITE|0x22; buf[1]=0x1F; buf[2]=0xBB; buf[3]=0x65; Write_CS5460A(buf,4); //电压 交流偏置 校准寄存器 /***************************/ buf[0]=WRITE|0x04; buf[1]=0x29; buf[2]=0x71; buf[3]=0xCA; Write_CS5460A(buf,4); //电流增益校准寄存器** buf[0]=WRITE|0x08; buf[1]=0x40; buf[2]=0x96; buf[3]=0xD3; Write_CS5460A(buf,4); //电压增益校准寄存器** buf[0]=0x5e; buf[1]=0xF0; buf[2]=0x00; buf[3]=0x00; Write_CS5460A(buf,4); //清除状态寄存器 buf[0]=0x74; buf[1]=0x80; //DRDY buf[2]=0x00; buf[3]=0x00; Write_CS5460A(buf,4); //写中断屏蔽寄存器 buf[0]=0x78; buf[1]=0x00; buf[2]=0x00; buf[3]=0x00; //缺省值 Write_CS5460A(buf,4); //写控制寄存器 buf[0]=0x4c; buf[1]=0x00; buf[2]=0x34; buf[3]=0x9C; Write_CS5460A(buf,4); //写EOUT 脉冲输出寄存器 buf[0]=0x4A; buf[1]=0x00; buf[2]=0x01; //每秒钟计算20 次,N=400 buf[3]=0x90; Write_CS5460A(buf,4); //写CYCLE COUNT 寄存器 Read_CS5460A(0x1e,buf); //读状态寄存器 buf[0]=0X5E; Write_CS5460A(buf,4); //写状态寄存器 buf[0]=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[N],temp; double sum=0; for (count=0;count<N;count++) { if(CS==CS_VRMS) value_buf[count] = CS5460_GetVoltRMS(); else value_buf[count] = CS5460_GetCurrentRMS(); } for (j=0;j<N-1;j++) { for (i=0;i<N-j-1;i++) { if ( value_buf>value_buf[i+1] ) { temp = value_buf; value_buf = value_buf[i+1]; value_buf[i+1] = temp; } } } for(count=4;count<N-4;count++) sum += value_buf[count]; 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. |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|