原创 C8051F学习日记(转载)

2008-3-16 21:24 2992 6 6 分类: MCU/ 嵌入式
AD采集交流电的程序50HZ的交流电经过精密整流以后每个周期单通道采集800个点分两个通道采集电压和电流并计算S,P,Q,相位角g ;   感觉玩C8051F的AD好爽啊   还有DA    功能强啊   就是爽           

/*******************************************************************


                C8051F020 AD采集         2006.09.26


*******************************************************************/


/************************预定义************************************/
#i nclude <C8051F020.h>
#i nclude <intrins.h>
#i nclude <stdio.h>
#i nclude <math.h>
/*******************************************************************


                           定义IO口和变量


*******************************************************************/
sbit LCDBUSY = P3^0; //LCD忙信号位
sbit REQ = P3^1;     //LCD请求信号位
sbit RES = P3^2;     //LCD复位信号位
sfr16 ADC0 = 0xbe;
unsigned int xdata ADC0_data1[800]; //AD通道一采集数据存放数组
unsigned int xdata ADC0_data2[800]; //AD通道二采集数据存放数组
unsigned int data ADC0_data_n;      //AD采集次数
unsigned int data ADC0_data_n1;     //通道一采集次数
unsigned int data ADC0_data_n2;     //通道二采集次数
bit m;//AD采集完标志
/*******************************************************************


                            函数声明


*******************************************************************/


void Sjcl(void);//AD采集完100次数据处理函数


void ADC0_ISR(void);//ADC0中断函数声明


void write_data(unsigned char writedata);//写数据到LCD


void send_ascii8(unsigned char x,unsigned char y,unsigned char ascii);//显示8*8ASCII


/********************************************************************


                        子函数定义


********************************************************************/


void delay_us(int timer)//us沿时

  timer*=20;//时钟周期调整
  for(;timer>0;timer--)
  _nop_();
}


void delay_ms(int i)//ms沿时
{
  for(;i>0;i--)
  delay_us(1000);
}


void lcd_init(void)//lcd初始化
{
  RES="0";
  delay_ms(20);
  RES="1";
  REQ="0";
  LCDBUSY="0";
}
/********************************************************************


                        系统初始化函数


********************************************************************/
void UART_Init()
{
    SCON0     = 0x50;   //使能UART0并允许接收
}



void Timer_Init()  
                
{
    CKCON     = 0x10;
    TCON      = 0x40;
    TMOD      = 0x20;
    TH1       = 0xB8;  //用定时器3做为AD0的启动转换标志每100us启动一次采集,   


         
    TMR3CN    = 0x04;  //使用系统时钟12分频做为定时器3的时钟源(22.1184M)
    TMR3RLL   = 0xd1;  //T1使用系统时钟并产生9600的波特率用与UART0
    TMR3RLH   = 0xFF;
    TMR3L     = 0xd1;
    TMR3H     = 0xFF;


}


void ADC_Init()
{
    ADC0CF    = 0x40;   //ADC0为定时器3益处采集方式,时钟频率为2.5M,
    ADC0CN    = 0x04;   //增益为1,数据为右对齐方式                   
 AMX0SL=0X00;      
}


void Voltage_Reference_Init()
{
    REF0CN    = 0x03;    //ADC0的参考电压来自内部增益
}


void Port_IO_Init()  //IO口初始化
                  
{
    P0MDOUT   = 0x01;     //P0.0,P0.1做为UART0的通信引脚,其中TX0为推拉方式
    P3MDOUT   = 0x06;     //P3.0为BUSY读取引脚,设为开漏方式
                       //P3.1为请求标志位设为推拉方式
                 //P3.2为复位信号脚设置为推拉方式
    P74OUT    = 0x03;     //P4为液晶数据线设为推拉方式
    XBR0      = 0x04;
    XBR2      = 0x40;
}


void Oscillator_Init()//使用外部晶振22.1184M
{
    int i = 0;
    OSCXCN    = 0x67;
    for (i = 0; i < 3000; i++);   // Wait 1ms for initialization
    while ((OSCXCN & 0x80) == 0);
    OSCICN    = 0x08;
}


void Interrupts_Init()
{
  EIE2 = 0x02;   //允许ADC0中断  
}


void Init_Device(void)
{
    Timer_Init();
    UART_Init();
    ADC_Init();
    Voltage_Reference_Init();   //初始化主程序
    Port_IO_Init();
    Oscillator_Init();
    Interrupts_Init();
}
//end init//


/****************************************************************************


                              主函数定义开始


*****************************************************************************/


void main(void)
{
    WDTCN="0xde";
    WDTCN="0xad";        //关看门狗
    Init_Device();
    lcd_init();
    AD0EN=1;
    delay_ms(5);
    EA="1";
    TI0=1;
    while(1)
    {
      if(m==1)
      {
    
         m="0";
         TMR3CN&=0xFB;  //关定时器3
         Sjcl();        //处理数据
         TMR3CN|=0X04;   //开定时器3
      }
    }
}
/****************************************************************************
                    
                           ADC0中断处理


****************************************************************************/


void ADC0_ISR(void) interrupt 15 
{
    ADC0CN&=0xdf;
    if(ADC0_data_n%2==0)
 {
        ADC0_data1[ADC0_data_n1] = ADC0;
  ADC0_data_n1++;
        AMX0SL = 0x01;
     }


    else
 {
     ADC0_data2[ADC0_data_n2]=ADC0;
  ADC0_data_n2++;
  AMX0SL=0x00;
     }


    ADC0_data_n++;
    if(ADC0_data_n==1600)//两路采集完800点
    {
       m="1";
    }
}


/****************************************************************************
                            
                   数据采集完处理函数


****************************************************************************/


void Sjcl(void)

   /*unsigned int j;*/
   /*unsigned char xdata lcd_senddata[4];//四位LCD显示数据*/
   unsigned int i;
   unsigned long data ADC0_dataadd=0;//采集完毕的累加计算值
   unsigned long data a="0";
   unsigned long data b="0";
   float data c;
   float data d;
   float data P_dataadd=0;
   float data U="0";
   float data I="0";           
   float data S="0";
   float data P="0";
   float data Q="0";
   float data COSg="0";
   //通道一数据处理      
   for(i=0;i<=ADC0_data_n1;i++)
   {
      a="ADC0"_data1;
      ADC0_dataadd=ADC0_dataadd+a*a;


   }


   U="ADC0"_dataadd/ADC0_data_n1;//取平均值
   U="sqrt"(U);//取平方根值
   U=(U*2.451)/0x0fff;//计算实际电压值
  
   //通道二数据处理
    ADC0_dataadd=0;
    for(i=0;i<=ADC0_data_n2;i++)
   {
      a="ADC0"_data2;
      ADC0_dataadd=ADC0_dataadd+a*a;


   }
   I="ADC0"_dataadd/ADC0_data_n2;//取平均值
   I="sqrt"(I);//取平方根值
   I=(I*2.451)/0x0fff;//计算实际电压2值
   S="U"*I;
   for(i=0;i<=ADC0_data_n1;i++) //计算P值
   {
     c=((float)ADC0_data1*2.451)/0x0fff;
     d=((float)ADC0_data1*2.451)/0x0fff;
     P_dataadd=P_dataadd+c*d;
    }
   P="P"_dataadd/ADC0_data_n1;//取平均值
   Q="sqrt"(S*S-P*P);//计算Q值
   COSg="P/S";//计算cosg值
   printf("************************************\n");
   delay_ms(10);
   printf("U=%.3fv   I=%.3fv\n",U,I);
   delay_ms(10);
   printf("S=%.3fw   P=%.3fw   Q=%.3fw\n",S,P,Q);
   delay_ms(10);
   printf("COSg=%.3f\n",COSg);
   delay_ms(10);
   ADC0_data_n=0;
   ADC0_data_n1=0;
   ADC0_data_n2=0;
}


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条