|
发表于 2007-11-26 19:34:32
|
显示全部楼层
贴一程序,测两路交流,两路直流,只是交流是半波的改成全波的也行应该,频率就是根据采样的数据大概估算出来,取平均能做到一伏.
// Target : M8
// Crystal: 8.0000Mhz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <math.h>
#include <avr/wdt.h>
volatile unsigned long a=0,b=0;
volatile unsigned int times=0;
volatile int e=0,f=0;
unsigned char led_buffu1[3]={0};
unsigned char led_buffu2[3]={0};
unsigned int Adc_d[4][41]={{0}};
volatile unsigned char Adc_i=0,Adc_j=0;
volatile unsigned char Meature_Over=0,Meature_F;
volatile unsigned char numt11,numt12,numt2;
volatile unsigned int U[12],I[12],U_select,I_select,display_u,display_i;
volatile unsigned int p,time,numt1;
volatile unsigned long T;
volatile double p1=16;
volatile unsigned char p2[12];
const unsigned char led[10]={0xDD,0x05,0xD6,0x57,0x0F,0x5B,0xDB,0x15,0xDF,0x5F};//共阴LED
#define SET_BIT(x,y) (x|=(1<<y))
#define CLR_BIT(x,y) (x&=~(1<<y))
#define GET_BIT(x,y) (x&=(1<<y))
#define Vref 463
void delayus(unsigned int us) //延时函数(us级别)
{
unsigned int i;
for(i=0;i<us;i++)
{};
}
void delayms(unsigned int ms) //延时函数 (ms级别)
{
unsigned int i;
for(i=0;i<ms;i++)
{
delayus(1000);
}
}
void display_u2(unsigned int c) //显示第二块数据
{
unsigned char j;
for(j=0;j<3;j++)
{
led_buffu2[j]=led[c%10];
c=c/10;
}
}
void display_u1(unsigned int c) //显示第一块数据
{
unsigned char j;
for(j=0;j<3;j++)
{
led_buffu1[j]=led[c%10];
c=c/10;
}
}
void Init_io(void) //IO口的初始化
{
DDRB=0x3f;
DDRD=0xff;
SET_BIT(DDRC,PC5);
}
void Init_timer1(void) //定时器1的初始化
{
TCCR1A=0x00;
TCCR1B=0x0a;
OCR1AH = 0x02;
OCR1AL = 0x70;
TIMSK = 0x10;
}
SIGNAL(SIG_OUTPUT_COMPARE1A) //定时器1输出比较匹配中断
{
if(Meature_Over==0) //定时启动ad中断
{
//PORTC^=_BV(PC5);
Adc_i++;
if(Adc_i==41) {Adc_i=0;Meature_Over=1;}
Adc_j=0;
SET_BIT(ADCSRA,ADSC);
}
numt2++;if(numt2==7) numt2=0;
PORTB&=0xc0;
if((numt2<=3)&&(numt2>0)) //刷新电流数据
{
PORTD=led_buffu2[numt2-1];
PORTB|=(8<<(2-(numt2-1)));
}
if((numt2>3)&&(numt2<7)) //刷新电压数据
{
PORTD=led_buffu1[numt2-4];
PORTB|=(1<<(2-(numt2-4)));
}
}
void Init_ad(void) //ad的初始化
{
ADCSRA|=(1<<ADEN)|(1<<ADIE)|(1<<ADPS0)|(1<<ADPS2);
}
SIGNAL(SIG_ADC) //adc的中断函数
{
PORTC^=_BV(PC5);
Adc_d[Adc_j][Adc_i]=ADCL;
Adc_d[Adc_j][Adc_i]|=(unsigned int)(ADCH<<8);
Adc_j++;
if(Adc_j<4)
{
ADMUX=ADMUX+1;
SET_BIT(ADCSRA,ADSC);
}
if(Adc_j==4)
{ADMUX=0;Adc_j=0;}
}
unsigned int Meature(unsigned char mux,unsigned int fun,unsigned char point) //测量数据
{
double valuedouble=0;
unsigned int value=0;
unsigned char i;
if(mux<2)
{
for(i=1;i<point+1;i++)
{
valuedouble=valuedouble+(((double)Adc_d[mux]*Vref)/1024)*(((double)Adc_d[mux]*Vref)/1024);
}
valuedouble=sqrt(valuedouble/point);
if(mux==0) //电压档位设计
{
if((fun<135)&&(fun>65))
{valuedouble=valuedouble*1.252;}
else if((fun>165)&&(fun<235))
{valuedouble=valuedouble*2.505;}
else if((fun>265)&&(fun<335))
{valuedouble=valuedouble*5.01;}
else
{valuedouble=valuedouble*2.505;}
//else if((fun>=300)&&(fun<400))
// {valuedouble=valuedouble*1.54;}
//else if((fun>=400)&&(fun<460))
// {valuedouble=valuedouble*1.54;}
}
else if(mux==1) //电流档位设计
{
if((fun<95)&&(fun>45))
{valuedouble=valuedouble*1;}
else if((fun>115)&&(fun<165))
{valuedouble=valuedouble*1.5;}
else if((fun>185)&&(fun<235))
{valuedouble=valuedouble*2;}
else if((fun>255)&&(fun<305))
{valuedouble=valuedouble*3;}
else if((fun>325)&&(fun<375))
{valuedouble=valuedouble*5;}
else if((fun>395)&&(fun<445))
{valuedouble=valuedouble*10;}
else
{valuedouble=valuedouble*2;}
}
}
else
{
for(i=1;i<point+1;i++)
{
valuedouble=valuedouble+Adc_d[mux];
}
valuedouble=(double)valuedouble/32*Vref/1024;
}
value=valuedouble;
return value;
}
unsigned char Meature_p(void) //计算频率用到
{
unsigned char i=0,number1=0,number2=0;
unsigned char f;
for(i=2;i<39;i++)
{
if((Adc_d[0][i-2]<Adc_d[0][i-1])&&(Adc_d[0][i-1]<Adc_d[0])&&(Adc_d[0]>Adc_d[0][i+1])&&(Adc_d[0][i+1]>Adc_d[0][i+2]))
{
number1=i;
break;
}
}
for(i=number1+2;i<40;i++)
{
if((Adc_d[0][i-2]<Adc_d[0][i-1])&&(Adc_d[0][i-1]<Adc_d[0])&&(Adc_d[0]>Adc_d[0][i+1])&&(Adc_d[0][i+1]>Adc_d[0][i+2]))
{
number2=i;
break;
}
}
if(number1>=number2)
{f=number1-number2;}
else {f=number2-number1;}
if((f>10)&&(f<22))
return f;
else {f=16;return f;}
}
void filter(void) //频率滤波函数
{
unsigned char i,j;
unsigned char temp_f1;
for(i=0;i<12;i++) //做排列从小到大取中间有用的
{
for(j=i;j<12;j++)
{
if(p2[j]<p2)
{
temp_f1=p2[j];p2[j]=p2;p2=temp_f1;
}
}
}
}
int main(void) //主函数
{
unsigned int num=0;
unsigned char i=0;
cli(); //初始化工作
Init_io();
Init_timer1();
Init_ad();
wdt_enable(WDTO_2S);
sei();
while(1) //主循环
{
if(Meature_Over) //等待测量完毕开始计算
{
p2=Meature_p();
if(i==11)
{
filter();p1=(p2[3]+p2[4]+p2[5]+p2[6]+p2[7]+p2[8])/6;
time=(OCR1AH<<8)+(OCR1AL)+1;
T=p1*100*time*2;
OCR1AH =(unsigned char)(((T>>5)/100)>>8);
OCR1AL =(unsigned char)(((T>>5)/100)-1);
}
U_select=Meature(2,0,32); //计算电压档位
I_select=Meature(3,0,32); //计算电流档位
U=Meature(0,U_select,32); //计算电压
I=Meature(1,I_select,32); //计算电流
i++;
if(i>=12){i=0;}
Meature_Over=0;
}
num++;
if(num==500) //刷新led时间设置
{
display_u=(U[0]+U[1]+U[2]+U[3]+U[4]+U[5]+U[6]+U[7]+U[8]+U[9]+U[10]+U[11])/12; //取平均电压
display_i=(I[0]+I[1]+I[2]+I[3]+I[4]+I[5]+I[6]+I[7]+I[8]+I[9]+I[10]+I[11])/12; //取平均电流
num=0;
}
display_u1(display_i); //显示电流函数
display_u2(display_u); //显示电压函数
wdt_reset();
}
} |
|