www.pudn.com > dsPIC33_CDROM.rar > AD4.c, change:2014-08-27,size:4158b


#include "P33FJ32GP204.H" 
#include "PPS.H" 
#include "MATH.H" 
//禁止时钟切换,禁止引脚多次配置,振荡引脚,主振荡器为XT 
_FOSC(FCKSM_CSDCMD & IOL1WAY_ON & OSCIOFNC_OFF & POSCMD_XT) 
//使用用户设定的振荡器启动,初始振荡器为带PLL的主(XT,HS或EC)振荡器 
_FOSCSEL(IESO_OFF & FNOSC_PRIPLL); 
_FICD(JTAGEN_OFF & ICS_PGD2); 
#define P1 _LATC4 
#define K 0.0418117 
unsigned int AD1[64],AD2[64],AD3[64],AD4[64]; 
unsigned char N=0; 
float U1,U2,U3,U4; 
void __attribute__((__interrupt__, auto_psv)) _T2Interrupt(void); 
void __attribute__((__interrupt__, auto_psv)) _ADC1Interrupt(void); 
void __attribute__((__interrupt__, auto_psv)) _IC2Interrupt(void); 
 
int main(void) 
{	//外接4MHz晶振,通过PLL得到总振荡频率50MHz,Fcy=25MHz,Tcy=40ns 
	CLKDIVbits.PLLPRE=0;	// N1=2,此输出为4/2=2MHz,符合0.8MHz~8.0MHz的要求  
	PLLFBDbits.PLLDIV=48; 	// M=50,此输出为2×50≈100MHz,符合100MHz~200MHz的要求 
	CLKDIVbits.PLLPOST=0;	// N2=2,此输出为100/2=50MHz,符合12.5MHz~80MHz的要求 
	while(OSCCONbits.COSC != 0b011);	//等待时钟稳定 
	RCONbits.SWDTEN=0;	//禁止WDT 
//AD转换设置 
	TRISB=0xFFFF; 
	TRISC=0xFFEF; 
  //AD1PCFGL 
  	AD1PCFGL=0xE000;	//AN0-AN12全为模拟脚	 
  //AD1CON1	 
	_AD12B=0;		//10位AD 
	_FORM=0b00;		//AD结果为整数 
	_SSRC=0b010;	//定时器3比较匹配,结束采样立即转换 
	_SIMSAM=1;		//同时采样 
	_ASAM=1;		//转换结束即开始采样 
  //AD1CON2 
  	_VCFG=0;		//AD参考电压为电源电压 
  	_CSCNA=0;		//禁止扫描 
  	_CHPS=0b11;		//同时采样4个通道 
  	_SMPI=3;		//4次采样后中断(共得到16个转换值) 
  	_BUFM=0;		// 
  	_ALTS=0;		//只用A开关 
  //AD1CON3 
   	_ADRC=0;		//系统时钟作为ADC时钟 
   	_ADCS=3;		//TAD=4×TCY=160ns>117.6ns 
  //AD1CHS0 
  	_CH0NA=0;		//采样多路开关A的CH0的负输入GND 
  	_CH0SA=6;		//采样多路开关A的CH0的正输入为AN6 
  //AD1CHS123 
  	_CH123SA=0;		//A开关同相接法.CH1:AN0,CH2:AN1,CH3:AN2 
  	_CH123NA=0;		//A开关的CH1,CH2,CH3的反相端接VREF-即GND	 
  //TMR3设置,作为ADC转换的触发源 
	T3CONbits.TCKPS=0b00;	//分频系数为1:1 
  	PR3=0xFFFF;		//暂取最大值 
  	TMR3=0; 
   //T2设置,作为IC2的时基 
	T2CONbits.TCKPS=0b01;	//分频系数为1:8 
   //IC2设置 
	TRISCbits.TRISC9=1;	//设置IC2为输入 
	PPSUnLock; 
	RPINR7bits.IC2R=25;	//RC9/RP25为IC2引脚 
	PPSLock; 
	IC2CONbits.ICM=0b010;	//每个下降沿捕捉一次 
	IC2CONbits.ICI=0b00;	//1次捕捉中断一次 
	IC2CONbits.ICTMR=1;	//Timer2为时基 
	IC2BUF=0; 
   //IC2、ADC及总中断设置 
	_IC2IF=0; 
	_IC2IE=1; 
	_IC2IP=0b111;		//IC2中断优先级为7 
  	_T3IF=0; 
  	_AD1IF=0; 
  	_AD1IE=1; 
  	_AD1IP=6;			 
  	_IPL=4;		//CPU中断优先级为4 
	_IPL3=0;		//CPU中断优先级≤7 
	_NSTDIS=1;		//禁止嵌套中断 
	_ALTIVT=0;		//使用标准中断向量 
	T2CONbits.TON=1;	//启动T2 
  	AD1CON1bits.ADON=1;//启动ADC模块 
	P1=1; 
	while(1);		 
	return(0); 
} 
 
//4次采样,时间间隔为通过捕捉计算,每次采样4个通道,共有16个ADC数据 
void __attribute__((__interrupt__, auto_psv)) _ADC1Interrupt(void) 
{	volatile unsigned int *P=&ADC1BUF0; 
	unsigned long B0; 
	static unsigned long B1,B2,B3,B4; 
	unsigned char i; 
	P1=~P1; 
	_AD1IF=0; 
	if (N==0) 
	{	B1=0;B2=0;B3=0;B4=0; 
	}	 
	for (i=0;i<4;i++) 
	{	AD1[N]=*(P++); 
		AD2[N]=*(P++); 
		AD3[N]=*(P++); 
		AD4[N]=*(P++); 
		 
		B0=AD1[N]; 
		B0=B0*B0; 
		B1+=B0; 
		 
		B0=AD2[N]; 
		B0=B0*B0; 
		B2+=B0; 
		 
		B0=AD3[N]; 
		B0=B0*B0; 
		B3+=B0; 
		 
		B0=AD4[N]; 
		B0=B0*B0; 
		B4+=B0; 
		 
		N+=1; 
	} 
	if (N>=64)	//每周期采64个点 
	{	U1=(float)B1; 
		U1=sqrt(U1)*K; 
		U2=(float)B2; 
		U2=sqrt(U2)*K; 
		U3=(float)B3; 
		U3=sqrt(U3)*K; 
		U4=(float)B4; 
		U4=sqrt(U4)*K; 
		T3CONbits.TON=0;	//关闭Timer3		 
		_ADON=0;		//禁止ADC 
		N=0; 
	} 
} 
 
void __attribute__((__interrupt__,auto_psv)) _IC2Interrupt(void) 
{	unsigned int Y,Z; 
	static unsigned int X=0; 
	static unsigned char NUM=0; 
	IFS0bits.IC2IF=0; 
	Y=IC2BUF;		//读捕捉值 
	if (NUM==1)		//只有NUM=1的周期才进行捕捉计算,准备下一周期采样 
	{	if (Y>X) 
			Z=Y-X; 
		else 
			Z=(~X)+Y+1;	//如果后次捕捉值Y小于前次捕捉值,按此计算  
 
		Y=Z>>3;		//1周期采样64次,Timer2为8分频,Timer3为1分频,右移3次相当于除以8,得64分频 
		if ((Z & 0b0100)==0b0100) 
			Y++; 
		PR3=Y-1; 
		TMR3=PR3>>1;	//第一次采样提前 
		T3CONbits.TON=1;	//启动定时器T3,准备AD		 
		_ADON=1; 
	} 
	NUM++; 
	X=Y;				//记下本次捕捉值 
	if (NUM>=10)			//其余9个周期不采样 
		NUM=0; 
}