|
今天開始每天把學(xué)習(xí)C8051F的感受記下來 今天上傳一個AD采集交流電的程序50HZ的交流電經(jīng)過精密整流以后每個周期單通道采集800個點(diǎn)分兩個通道采集電壓和電流并計(jì)算S,P,Q,相位角g ; 感覺玩C8051F的AD好爽啊 還有DA 功能強(qiáng)啊 就是爽 /******************************************************************* C8051F020 AD采集 2006.09.26 *******************************************************************/ /************************預(yù)定義************************************/ #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復(fù)位信號位 sfr16 ADC0 = 0xbe; unsigned int xdata ADC0_data1[800]; //AD通道一采集數(shù)據(jù)存放數(shù)組 unsigned int xdata ADC0_data2[800]; //AD通道二采集數(shù)據(jù)存放數(shù)組 unsigned int data ADC0_data_n; //AD采集次數(shù) unsigned int data ADC0_data_n1; //通道一采集次數(shù) unsigned int data ADC0_data_n2; //通道二采集次數(shù) bit m;//AD采集完標(biāo)志 /******************************************************************* 函數(shù)聲明 *******************************************************************/ void Sjcl(void);//AD采集完100次數(shù)據(jù)處理函數(shù) void ADC0_ISR(void);//ADC0中斷函數(shù)聲明 void write_data(unsigned char writedata);//寫數(shù)據(jù)到LCD void send_ascii8(unsigned char x,unsigned char y,unsigned char ascii);//顯示8*8ASCII /******************************************************************** 子函數(shù)定義 ********************************************************************/ void delay_us(int timer)//us沿時 { timer*=20;//時鐘周期調(diào)整 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; } /******************************************************************** 系統(tǒng)初始化函數(shù) ********************************************************************/ void UART_Init() { SCON0 = 0x50; //使能UART0并允許接收 } void Timer_Init() { CKCON = 0x10; TCON = 0x40; TMOD = 0x20; TH1 = 0xB8; //用定時器3做為AD0的啟動轉(zhuǎn)換標(biāo)志每100us啟動一次采集,
TMR3CN = 0x04; //使用系統(tǒng)時鐘12分頻做為定時器3的時鐘源(22.1184M) TMR3RLL = 0xd1; //T1使用系統(tǒng)時鐘并產(chǎn)生9600的波特率用與UART0 TMR3RLH = 0xFF; TMR3L = 0xd1; TMR3H = 0xFF; } void ADC_Init() { ADC0CF = 0x40; //ADC0為定時器3益處采集方式,時鐘頻率為2.5M, ADC0CN = 0x04; //增益為1,數(shù)據(jù)為右對齊方式 AMX0SL=0X00; } void Voltage_Reference_Init() { REF0CN = 0x03; //ADC0的參考電壓來自內(nèi)部增益 } void Port_IO_Init() //IO口初始化 { P0MDOUT = 0x01; //P0.0,P0.1做為UART0的通信引腳,其中TX0為推拉方式 P3MDOUT = 0x06; //P3.0為BUSY讀取引腳,設(shè)為開漏方式 //P3.1為請求標(biāo)志位設(shè)為推拉方式 //P3.2為復(fù)位信號腳設(shè)置為推拉方式 P74OUT = 0x03; //P4為液晶數(shù)據(jù)線設(shè)為推拉方式 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// /**************************************************************************** 主函數(shù)定義開始 *****************************************************************************/ void main(void) { WDTCN=0xde; WDTCN=0xad; //關(guān)看門狗 Init_Device(); lcd_init(); AD0EN=1; delay_ms(5); EA=1; TI0=1; while(1) { if(m==1) { m=0; TMR3CN&=0xFB; //關(guān)定時器3 Sjcl(); //處理數(shù)據(jù) 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點(diǎn) { m=1; } } /**************************************************************************** 數(shù)據(jù)采集完處理函數(shù) ****************************************************************************/ void Sjcl(void) { /*unsigned int j;*/ /*unsigned char xdata lcd_senddata[4];//四位LCD顯示數(shù)據(jù)*/ unsigned int i; unsigned long data ADC0_dataadd=0;//采集完畢的累加計(jì)算值 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; //通道一數(shù)據(jù)處理 for(i=0;i<=ADC0_data_n1;i++) { a=ADC0_data1[i]; ADC0_dataadd=ADC0_dataadd+a*a; } U=ADC0_dataadd/ADC0_data_n1;//取平均值 U=sqrt(U);//取平方根值 U=(U*2.451)/0x0fff;//計(jì)算實(shí)際電壓值 //通道二數(shù)據(jù)處理 ADC0_dataadd=0; for(i=0;i<=ADC0_data_n2;i++) { a=ADC0_data2[i]; ADC0_dataadd=ADC0_dataadd+a*a; } I=ADC0_dataadd/ADC0_data_n2;//取平均值 I=sqrt(I);//取平方根值 I=(I*2.451)/0x0fff;//計(jì)算實(shí)際電壓2值 S=U*I; for(i=0;i<=ADC0_data_n1;i++) //計(jì)算P值 { c=((float)ADC0_data1[i]*2.451)/0x0fff; d=((float)ADC0_data1[i]*2.451)/0x0fff; P_dataadd=P_dataadd+c*d; } P=P_dataadd/ADC0_data_n1;//取平均值 Q=sqrt(S*S-P*P);//計(jì)算Q值 COSg=P/S;//計(jì)算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; } |