#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <math.h>
bit udre; //usart data register empty 串口数据寄存器空
bit adcsc; //ADC开始转换
bit usart_r_flag=0; //串口输出标志
bit adc_permm; //adc permmite ADC允许
unsigned char adc_flag=1; // adc complete flag ADC完成标志
unsigned char adch,adcl,channel_compl; //ADC高电平,ADC低电平,通道
unsigned long int adc_temp; //ADC数据暂存
unsigned long int irms; //电流有效值
unsigned long int urms; //电压有效值
unsigned long int adc_av=0; //ADC平均值
signed long int adc_s; //
signed long int p_av; //功率平均
unsigned long int p_factor; //功率因数
unsigned long int p_sum,p_sum_temp,e_sum; //总和
unsigned char p_sum_count; //总和计数
unsigned char usart_count=0; //串口计数
unsigned char usart_r[5]; //串口数组
signed int Volt[100]; //电压数组
signed int Curr[100]; //电流数组
unsigned char Volth[100]={0x00}; //
unsigned char Voltl[100]={0x00}; //
void usart_trans(unsigned char s_data) //串口发射
{
UDR=s_data;
do
{
udre=UCSRA.5;
}
while(!udre);
UCSRA.6=1;
}
void usart_trans_addr(unsigned char *s_addr) //串口发射地址
{
UDR=*s_addr;
do
{
udre=UCSRA.5;
}
while(!udre);
UCSRA.6=1;
}
void _delay(unsigned int time_delay) //延时
{
unsigned int d_t;
while(time_delay--)
for(d_t=0;d_t<1;d_t++);
}
void l_delay(unsigned int time_delay) //长延时
{
unsigned int d_t;
while(time_delay--)
for(d_t=0;d_t<200;d_t++);
}
interrupt [USART_RXC] void usart_rx_isr(void) //串口接收中断
{
if(usart_count>=0&&usart_count<=4)
usart_r[usart_count]=UDR;
usart_count++;
if(usart_r[0]==0x20)
{
usart_r_flag=0;
UCSRB=0x00;
usart_count=0;
#asm("cli");
GICR&=0xdf;
#asm("sei");
}
//PORTD.7^=1;
}
interrupt [ADC_INT] void adc_isr(void) //ADC中断
{
adcl=ADCL;
adch=ADCH;
adc_flag=1;
}
interrupt [EXT_INT0] void ext_int0_isr(void) //外部中断0
{
adc_permm=1;
}
interrupt [EXT_INT2] void ext_int2_isr(void) //外部中断2,50HZ方波
{
adc_permm=1;
#asm("cli");
GICR&=0xdf;
#asm("sei");
//PORTD.7^=1;
}
void start_adc() //开始ADC
{
GICR=0x00; //close INT0,avoid INT0 happening during ADC-converting
adc_flag=0;
ADCSRA=0x89 | 0xC0;
do
{
adcsc=ADCSRA.6;
}
while(adcsc);
}
void start_adc_n_c() //ADC_Noise_Canceler Mode AD,噪声滤波
{
#asm("cli");
MCUCR|= 0x50;
GICR=0x00;//close EXT_INT
#asm("sei");
#asm("sleep")
}
void adc_mux_alter(unsigned char mux_) //ADC通道转换
{
ADMUX=0x20;
ADMUX|=mux_;
l_delay(10);
}
void usart_int(unsigned int x) //发送整型数据
{
unsigned char int_x,int_y;
int_x=x/256;
int_y=x%256;
usart_trans(int_x);
usart_trans(int_y);
}
void usart_l_int(signed long int x) //发送32位整型数据
{
unsigned char int_x,int_y,int_z,int_w;
int_x=x/(256*65536);
x=x%(256*65536);
int_y=x/65536;
x=x%65536;
int_z=x/256;
int_w=x%256;
usart_trans(int_x);
l_delay(5);
usart_trans(int_y);
l_delay(5);
usart_trans(int_z);
l_delay(5);
usart_trans(int_w);
l_delay(10);
}
void trans_100byte(unsigned char *addr) //发送100字节,检测
{
unsigned char addr_;
for(addr_=0;addr_<100;addr_++)
{
usart_trans_addr(addr++);
l_delay(20);
}
l_delay(10);
}
void adc_calcu(signed int *addr,unsigned u_i) //ADC计算
{
unsigned char k;
adc_av=0;
for(k=0;k<100;k++)
{
*(addr+k)=(Volth[k]*4+Voltl[k]/64)*5;
}
for(k=0;k<92;k++)
{
adc_av+=*(addr+k);
}
adc_av/=92;
for(k=0;k<100;k++)
*(addr+k)-=adc_av;
adc_temp=0;
for(k=0;k<92;k++)
{
adc_temp+=(long int) pow(*(addr+k),2);
}
adc_temp/=92;
adc_s=0;
switch(u_i)
{
case 0:
{
urms=0;
urms=(int )sqrt(adc_temp);
break;
}
case 1:
{
irms=0;
irms=(int )sqrt(adc_temp);
break;
}
}
if(urms<=0x0200)
urms=0;
if(irms<=0x06)
{
irms=0;
adc_s=0;
}
else
irms-=0x04;
}
void power_calcu() //功率计算
{
unsigned char k;
signed long int calcu1,calcu2;
//signed long int calcu3,calcu4;
p_av=0;
adc_s=0;
p_factor=0;
for(k=0;k<92;k++)
{
calcu1=Volt[k+3];
calcu2=Curr[k];
p_av+=calcu1 * calcu2;
}
p_av/=92;
if(irms==0)
p_av=0;
// else
// p_av+=0x10;
//把有功功率、视在功率转化为扩大一百倍的十进制表示
p_av/=1024;
p_av*=26;
// adc_s=urms*irms;
// adc_s/=1024;
// adc_s*=26;
// p_factor=p_av*1000;
// p_factor/=adc_s;
p_sum_temp+=p_av;
p_sum_count++;
if(p_sum_count>=100)
{
p_sum=p_sum+p_sum_temp/10000*49; //每次转换完成需要1.780s,178/36=4.9
e_sum=e_sum+p_sum/10000;
p_sum_temp=0;
p_sum_count=1;
}
}
void usart_send(unsigned char channel,unsigned char comm) //通过发送模块无线
{
usart_trans(0x45);
_delay(4);
usart_trans(0x53);
_delay(4);
usart_trans(0x02);
_delay(4);
usart_trans(channel);
_delay(4);
usart_trans(comm);
_delay(4);
}
void main(void)
{
unsigned int k;
char i=0;
//char adc_addr=0;
DDRB.2=0;
PORTB.2=0;
PORTC=0xff;
PORTD=0x80;
DDRD=0xfd;
MCUCR|=0X02;
MCUCSR|=0X40;
GIFR|=0X60;
GICR|=0X20;
UCSRA=0x02;
UCSRB=0x98;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0c;
// ADC initialization
// ADC Clock frequency: 500.000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: ADC Stopped
ADMUX=0x20;
ADCSRA=0x8c;
PORTC=0X00;
ACSR|=0x80;
p_sum=0;
p_sum_temp=0;
p_sum_count=0;
channel_compl=0;
#asm("sei")
start_adc();
usart_r_flag=0x01;
while(1)
{
if(!usart_r_flag)
{
UCSRB=0x08;
usart_send(0x01,0x00);
usart_count=0;
UCSRB=0x98;
while(!usart_r_flag)
{
while(usart_count<5)
UCSRB=0x98;
if(usart_r[0]==0x45 && usart_r[1]==0x53 && usart_r[2]==0x02 && usart_r[3]==0x01)
{
switch(usart_r[4])
{
case 0:
{
//usart_trans(usart_r[2]);
usart_trans(0x45);
usart_trans(0x53);
usart_trans(0x0d);
usart_trans(0x01);
usart_l_int(e_sum);
usart_int(urms*26);
usart_int(irms);
usart_l_int(p_av);
usart_r_flag=1;
GIFR|=0xe0;
GICR=0x20;
UCSRB=0x00;
// usart_l_int(adc_s);
//usart_int(p_factor);
//usart_trans('*');
//usart_trans('*');
}
break;
case 1:
  ORTD.7=1;
usart_trans(0x45);
usart_trans(0x53);
usart_trans(0x02);
usart_trans(0x01);
usart_trans(0x01);
usart_r_flag=1;
GIFR|=0xe0;
GICR=0x20;
UCSRB=0x00;
break;
case 2:
  ORTD.7=0;
usart_trans(0x45);
usart_trans(0x53);
usart_trans(0x02);
usart_trans(0x01);
usart_trans(0x02);
usart_r_flag=1;
GIFR|=0xe0;
GICR=0x20;
UCSRB=0x00;
break;
case 3:
usart_r_flag=1;
usart_trans(0x45);
usart_trans(0x53);
usart_trans(0x02);
usart_trans(0x01);
usart_trans(0x03);
GIFR|=0xe0;
GICR=0x20;
UCSRB=0x00;
}
}
usart_count=0;
}
}
adc_permm=0;//in INT2 service runtime,turns to 1
l_delay(10);
GIFR|=0xe0;
GICR=0x20;
UCSRB=0x00;
while(!adc_permm);
while (usart_r_flag)
{
if(adc_permm)
start_adc_n_c();
_delay(2);
if(adc_flag)
{
if(i<100 )
{
Volth=adch;
Voltl=adcl;
i++;
adc_flag=0;
}
else
{
k=0;
adc_temp=0;
if(channel_compl%2)
{
UCSRB=0x98;
//usart_trans('/');
}
switch(channel_compl%2)
{
case 0:
adc_calcu(&Volt[0],0);break;
case 1:
adc_calcu(&Curr[0],1);break;
}
//trans_100byte(&Volth[0]);
//usart_l_int(adc_av);
if(channel_compl%2)
{
power_calcu();
}
// if(channel_compl%2)
// {
// UCSRB=0x98;
// usart_trans('*');
// }
i=0;
k=0;
channel_compl++;
adc_mux_alter(channel_compl%2);
l_delay(2);
adc_permm=0;//in INT2 service runtime,turns to 1
GIFR|=0xe0;
GICR=0x20;
UCSRB=0x00;
while(!adc_permm);
//UCSRB=0x00;
}
}
}
}
自己标注了一点程序,具体的不懂。无线模块给AVR发45 53 02 01 00,返回45 53 0D 01 00 00 00 00 5A 98 00 00 00 00 00 00 (什么都没插);45 53 0D 01 00 00 00 00 5A 16 00 11 00 00 00 EA 插充电器;45 53 0D 01 00 00 00 00 59 94 00 3B 00 00 01 86 插充电灯。不知道哪个是电压,哪个是电流,同学说U,I还要乘系数哦,但是不记得是多少了,有人能帮我看一下么???!!
|