⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adc12.c

📁 移植UCOS于增强型51单片机上
💻 C
字号:
#include <msp430x14x.h>
#include <math.h>
#include <stdlib.h> 
#include <string.h>
#include "ADC12.H"
#include "TimerA.H"
#include "Globe.H"
#include "FlashMemOP.H"
#include "TimerB.H"
#include "includes.h"
#include "GaoJin.h"

//unsigned int Factor[ADINPUTNUM];				//AD转换得到的数值和实际电压电流值之间的比例因子,这个比例因子需要校准

Buff adBuff;
value val[ADINPUTNUM];			//最终的计算结果

//初始化MyAdcFlag
void InitMyAdcFlag(void)
{
	MyAdcFlag.SampCounter	= 0;	//初始时置已经采样的点数为零
	
	MyAdcFlag.Channel		= 0;		//初始采样通道设为电压通道
	MyAdcFlag.SampleOK	=false;	
	MyAdcFlag.adMoniCount=0;		//在AD中断里面计数
}

//初始化AD转换模块
//每周波采集128个点的数据,实际上采集
//使用内部2.5V参考
void InitADC12(void)
{
	int i;
		
	P6DIR		&=~0xff;
	P6SEL		|=0xff;
	STOP_ADC();			//Set ENC=0;
	
	//ADC12CTL0	|=	SHT0_12;		//采样时间定为1024个ADC12CLK,125ns×512=128us+13个转换周期13*0.125=1.625us 共129.625us
	ADC12CTL0	|=	SHT0_11;		//所以AD输入端的RC电路的时间常数不能大于128us,现在的r=100K C=0.001uf
									//时间常数为100us
									//每周波等间隔采集128个点,一个点的采样加转换时间最多不能超过20ms/128=0.15625ms
	ADC12CTL0	|=	SHT1_10;		
	//ADC12CTL0	|=	MSC;			//Multiple Sample
	ADC12CTL0	|=	REF2_5V;			//Internal Reference 2.5V
	ADC12CTL0	|=	REFON;			//Internal Reference on
	ADC12CTL0	|=	ADC12ON;		//turn on ADC12
		
	ADC12CTL1	|=	CSTARTADD_0;	//Conversion start at mem0
	ADC12CTL1	|=	SHS_3;			//Sample and hold source is TB OUT1
	ADC12CTL1	|=	SHP;			//Pulse-mode SAMPCON signal is sourced from the Sampling Timer
	ADC12CTL1	&=	~ISSH;			//The sample-input signal is not inverted
	ADC12CTL1	|=	ADC12SSEL_2;	//select MClk for ADC12 clock source 8M
	ADC12CTL1	|=	ADC12DIV_0;		//ADC12CLK's divider=1  8M
	//ADC12CTL1	|=	CONSEQ_1;		//Sequence-of-channels,一次一序列通道采样.
	ADC12CTL1	|=	CONSEQ_0;		//Single conversion,单通道单次采样
	
		
	i=ADC12MEM0;    //清除中断标志ADCIFG.0
	i=ADC12MEM1;
	i=ADC12MEM2;
	i=ADC12MEM3;
	i=ADC12MEM4;
	i=ADC12MEM5;
	i=ADC12MEM6;
	i=ADC12MEM7;
	i=ADC12MEM8;
	i=ADC12MEM9;
	i=ADC12MEM1 ;
	i=ADC12MEM11;
	i=ADC12MEM12;
	i=ADC12MEM13;
	i=ADC12MEM14;
	i=ADC12MEM15;
	i=i;
	//所有通道的参考都是内部参考2.5V和AGND
	ADC12MCTL0 =  INCH_0+REF_VREF_AVSS; 			//UA	
    ADC12MCTL1 =  INCH_1+REF_VREF_AVSS;           	//UB
    ADC12MCTL2 =  INCH_3+REF_VREF_AVSS;           	//IA
    ADC12MCTL3 =  INCH_4+REF_VREF_AVSS;           	//IB
    ADC12MCTL4 =  INCH_2+REF_VREF_AVSS;           	//UC
    ADC12MCTL5 =  INCH_5+REF_VREF_AVSS;           	//IC
    ADC12MCTL6 =  INCH_6+REF_VREF_AVSS;           	//电源
   // ADC12MCTL7 =  INCH_7+REF_VREF_AVSS;         	//备用通道
    ADC12MCTL7 =  INCH_10+REF_VREF_AVSS;         	//备用通道,
    ADC12MCTL8 =  INCH_10+REF_VREF_AVSS+EOS;		//内部温度传感器
    //ADC12MCTL9 =  INCH_9+REF_VREF_AVSS;
    //ADC12MCTL10 = INCH_10+REF_VREF_AVSS+EOS;
    //ADC12MCTL11 = INCH_11+REF_VREF_AVSS+EOS;
    
    ADC12IE = 0xff;	//允许中断
    START_ADC();
}


#define CHANNELNUM 8
char adSamecount=0;
#pragma vector=ADC_VECTOR
__interrupt void isrADC12(void)
{
	unsigned int i;
	
	//i=ADC12MEM8;
	//ADC12IFG=0;		//清除中断标志
		
	
	switch(MyAdcFlag.Channel)	//根据当前采样通道号读取相应的采样值
	{
		case UA:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM0;
			break;
		case UB:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM1;
			break;
		case IA:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM2;
			break;
		case IB:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM3;
			break;
		case UC:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM4;
			break;
		case IC:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM5;
			break;
		case PWR:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM6;
			break;
		case TMP:
			adBuff.buff[MyAdcFlag.SampCounter]=ADC12MEM7;
			break;
	}
	i=ADC12MEM0;    //清除中断标志ADCIFG.0
	i=ADC12MEM1;
	i=ADC12MEM2;
	i=ADC12MEM3;
	i=ADC12MEM4;
	i=ADC12MEM5;
	i=ADC12MEM6;
	i=ADC12MEM7;
	i=ADC12MEM8;
	i=ADC12MEM9;
	i=ADC12MEM1 ;
	i=ADC12MEM11;
	i=ADC12MEM12;
	i=ADC12MEM13;
	i=ADC12MEM14;
	i=ADC12MEM15;
	i=i;
	AGAIN_ADC();
	if(MyAdcFlag.Channel<6)
		{
			if(adBuff.buff[MyAdcFlag.SampCounter]>2300 ||adBuff.buff[MyAdcFlag.SampCounter]<800)
				{
					if(abs(adBuff.buff[MyAdcFlag.SampCounter-1]-adBuff.buff[MyAdcFlag.SampCounter])<3)
						{
							if(adSamecount++>20)	//严重削顶了
								{
									GJSta.urgency=1;
								}
						}
				}
		}
	MyAdcFlag.SampCounter++;		//增加一个转换点记录
	MyAdcFlag.adMoniCount=0;			//
	if(MyAdcFlag.SampCounter>=SAMPLENUM)	//如果已经完成SAMPLENUM个采样点的采样
	{										//则转换采样通道
		StopTimerB();						//停止TB		
		MyAdcFlag.SampleOK=true;			//置通道采样完成标志
		MyAdcFlag.SampCounter = 0;			//计数值清零
		adSamecount=0;
 	}
}

void AdcTask(void *pdata)
{
	double result;
	pdata=pdata;
	InitFreqTrack();
	InitTimerA();
	InitMyAdcFlag();
	InitADC12();
	
	OSTimeDly(50);//等待频率跟踪完成
	while(1)
	{
		ModifySampTime();	//根据频率跟踪的结果修正采样时间
		for(MyAdcFlag.Channel =0;MyAdcFlag.Channel <CHANNELNUM;MyAdcFlag.Channel++)
		{			
			STOP_ADC();
			ADC12CTL1	&=0xfff;	
			ADC12CTL1 |=(MyAdcFlag.Channel*0x1000);	//更改采样通道
			START_ADC();
			AGAIN_ADC();
			OSTimeDly(6);
			if(MyAdcFlag.Channel<4)
				{
					StartTimerB(MyAdcFlag.Ch1TBCCR1);	//启动TimerB,timerB启动后将触发AD进行采样,直到SAMPLENUM个采样点完成后停止TB
				}
			else
				{
					StartTimerB(MyAdcFlag.Ch2TBCCR1);	//启动TimerB,timerB启动后将触发AD进行采样,直到SAMPLENUM个采样点完成后停止TB
				}
			
			while(!MyAdcFlag.SampleOK)
				OSTimeDly(1);	//等待采样完成
			STOP_ADC();
			MyAdcFlag.SampleOK=false;
			
			//采样完成,以下进行处理
			result=CalcuValue(MyAdcFlag.Channel);	//计算有效值
			val[MyAdcFlag.Channel].Value=(unsigned int)(result*1000);
			GJCheckExtra(MyAdcFlag.Channel);
			
		}
		OSTimeDly(1);
	}
} 

#define ADJFACTOR	(100.0/4.3)	//放大100倍
#define REFVOLT		(2.5)			//放大10倍
double CalcuValue(char channel)	//计算有效值
{
	unsigned long	adAverage;//用于计算ad采样的平均值
	int i,temp;
	double aa;
	union
	{							//这个因子存储在Flash中,每个通道的因子都需要在出厂前校准
		unsigned long 	value;				//计算后的结果,存放电流或电压值
		unsigned int ValueInt[2];
	}tempValue;
	if(channel<6)
		{
			adAverage=0;
			for(i=0;i<SAMPLENUM;i++)
				{			
					adAverage+=	(adBuff.buff[i]);
				}
			i=0;
			temp=SAMPLENUM;
			do
				{
					temp/=2;
					i++;
				}
			while(temp);
			adAverage=adAverage>>(i-1);	//求得平均值
			//adAverage=
			for(i=0;i<SAMPLENUM;i++)
				{
					temp=adBuff.buff[i]-adAverage;
					MAC=abs(temp);
					OP2	=abs(temp);
				}
			tempValue.ValueInt[1]=RESHI;
			tempValue.ValueInt[0]=RESLO;	//得到乘积累加和
			
			aa=(double)(tempValue.value/SAMPLENUM);
			aa=sqrt(aa);	//求均方根
			aa*=REFVOLT;
			aa/=4095.0;
			aa*=ADJFACTOR;	
		}
	else if(channel==6)	//电源通道
		{
			adAverage=0;
			for(i=0;i<SAMPLENUM;i++)
				{			
					adAverage+=	(adBuff.buff[i]);
				}
			i=0;
			temp=SAMPLENUM;
			do
				{
					temp/=2;
					i++;
				}
			while(temp);
			aa=adAverage>>(i-1);	//求得平均值
			aa*=REFVOLT;
			aa/=4095.0;
			aa*=ADJFACTOR;
		}
	else		//温度传感器通道
		{
			adAverage=0;
			for(i=0;i<SAMPLENUM;i++)
				{			
					adAverage+=	(adBuff.buff[i]);
				}
			
			i=0;
			temp=SAMPLENUM;
			do
				{
					temp/=2;
					i++;
				}
			while(temp);
			aa=adAverage>>(i-1);	//求得平均值
			aa*=REFVOLT;
			aa/=4095.0;	//得到温度传感器输出的电压值
			aa-=0.986;
			aa=aa*20000/71;//得到温度值
			//aa-=11;
		}
	return aa;
}



unsigned long sqrt32(unsigned long x)
{
  unsigned long small, big, mid, t;
  small = 0;
  big = 0xffff;                  //?a·??á1?2?3?1y65535
  mid = (small + big) >>1;       //?t·?
  while (small < (big-1))        //?±μ??t??2??μ?a1
  {                               
    t = mid * mid; 
    if (t == x) 
      break; 
    if ( t > x)
    {
      big = mid; 
    } 
    else
    {
      small = mid;
    }
    mid = (small + big) >>1;
  }
  return mid;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -