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

📄 简易谐波分析仪.c

📁 简易谐波分析仪
💻 C
📖 第 1 页 / 共 4 页
字号:
			PORTA=(PORTA|0X09)&0XF9;								//<uuuu,1001>译码后选择第1片LCD.
		else
			PORTA=(PORTA|0X0A)&0XFA;								//<uuuu,1010>译码后选择第2片LCD.
		PORTB=(PORTB|0X60)&0XEF;									//<u110,uuuu>控制信号:可读-读-命令.
		STA=PORTD&0X20;														//将数据赋给PORTD端口.
		PORTB=PORTB&0XBF;													//<u000,uuuu>控制信号:锁存数据.
		if(STA==0X20)															//LCD显示器是否被关闭.
			break;																	//关闭,跳出循环.
	}
}

/* ************************************************************************
** 函 数 名:void LCDCLEAR(int E)
** 功能描述:将液晶显示器清屏.
*************************************************************************** */
void LCDCLEAR(int E)
{
	int PAGE,NUM,CLMD;														//页地址-增量-列地址.
	for(NUM=0X08,PAGE=0XB8;NUM>0;NUM--,PAGE++)		//页基地址0X80循环累加1.
	{							
		for(CLMD=0X40;CLMD<=0X7F;CLMD++)						//列基地址0X40循环累加1.
		{						
			LCDOUT(0X00,CLMD,PAGE,E);									//向当前地址输入0X00,清屏.
		}
	}
}

/* ************************************************************************
** 函 数 名:void LCDCLEARA(int CLMD,int PAGE,int CLMDN,int PAGEN,int E)
** 功能描述:选择性清屏,起始列(CLMD)起始页(PAGE)几列(CLMDN)几页(PAGEN).
*************************************************************************** */
LCDCLEAN(int CLMD,int PAGE,int CLMDN,int PAGEN)
{
	int C,P,CADD;														
																								//计算实际的初始页地址.
	for(P=PAGE+0XB8;PAGEN>0;PAGEN--,P++)					//页基地址0X80循环累加1.
	{	
		CADD=CLMDN;																	//计算实际的初始列地址.
		for(C=CLMD+0x40	;CADD>0;CADD--,C++)					//列基地址0X40循环累加1.
		{						
			if(C>0X7F)																//列地址判断.
				LCDOUT(0X00,C-64,P,2);									//向当前地址输入0X00,清屏.
			else				
				LCDOUT(0X00,C,P,1);											//向当前地址输入0X00,清屏.
		}
	}
}
/* ************************************************************************
** 函 数 名:LCDINITI(int E)
** 功能描述:LCD初始化程序
*************************************************************************** */
void LCDINITI(int E)
{
	LCDOFF(E);																	//关闭LCD.															
	LCDCLEAR(E);																//清屏.		
	LCDON(E);																		//打开LCD.			
}

/* ************************************************************************
** 函 数 名:void LCDCH(char *WORDS,int CLMD,int PAGE)
** 功能描述:向LCD输入汉字点阵(*WORDS)16*16,并以CLMD为初始列,PAGE为初始页.
*************************************************************************** */
void LCDCH(const char *WORDS,int CLMD,int PAGE)
{
	const char *ARW;														//定义汉字点阵入口数组.
	int P,C,NUM;																//页址-列址-计数脚标.
	ARW=WORDS;																	//数组首地址的传递.
	P=PAGE+0XB8;																//计算初始页地址.
	C=CLMD+0X40;																//计算初始列地址.
	for(NUM=0;NUM<16;NUM++,C++)									//列地址累加1,并记录累加次数.
	{
		if(C>0X7F)																//根据C的值判断在哪片LCD显示.
		{
			LCDOUT(ARW[NUM],C-64,P,2);							//向第1页当前列输入数据.
			LCDOUT(ARW[NUM+16],C-64,P+1,2);					//向第2页当前列输入数据.
		}
		else
		 {  LCDOUT(ARW[NUM],C,P,1);								//向第1页当前列输入数据.
		   LCDOUT(ARW[NUM+16],C,P+1,1);						//向第2页当前列输入数据.
		 }
	}
}

/* ************************************************************************
** 函 数 名:void LCDNUM(char *WORDS,int CLMD,int PAGE)
** 功能描述:向LCD输入字符数字点阵(*WORDS)8*8,并以CLMD为初始列,PAGE为页地址.
*************************************************************************** */
void LCDNUM(const char *WORDS,int CLMD,int PAGE)
{
	const char *ARW;														//定义数字字符点阵入口数组.
	int P,C,NUM;																//页址-列址-计数脚标.
	ARW=WORDS;																	//数组首地址的传递.
	P=PAGE+0XB8;																//计算初始页地址.
	C=CLMD+0X40;																//计算初始列地址.
	for(NUM=0;NUM<8;NUM++,C++)									//列地址累加1,并记录累加次数.
	{
		if(C>0X7F)																//根据C的值判断在哪片LCD显示
			LCDOUT(ARW[NUM],C-64,P,2);							//向当前列输入数据.
		else
			LCDOUT(ARW[NUM],C,P,1);									//向当前列输入数据.
	}
}

/* ************************************************************************
** 函 数 名:void OUTNUM(long N,int D,int CLMD,int PAGE)
** 功能描述:根据参数输出任意数字.
*************************************************************************** */
void OUTNUM(long N,int D,int CLMD,int PAGE)
{
    int i;	
    for(i=0;N>0||i<=D;i++)										//循环判断.
    {   
      if(i==D)																//个位?
	      LCDNUM(NUM[N%10+10],CLMD,PAGE);				//输出带点数.
      else
		   LCDNUM(NUM[N%10],CLMD,PAGE);						//输出无点数.
      CLMD=CLMD-6;														//数字的位置.
      N=N/10; 																//取数据某位的数字.
    }
}
/* ************************************************************************
** 函 数 名:void LCDPIEX(int X,int Y)
** 功能描述:根抿坐标(X,Y)在LCD上画点.
*************************************************************************** */
void LCDPIEX(int X,int Y)
{
	int i;																			//定义循环计数的变量.
 	int CLMD,PAGE,ROW,E,DATA;										//列-页-行-片-要写的数据-读出的数据.										
 	PAGE=0XB8;																	//第0页的地址.
 	DATA=0X01;																	//参考数据上.
 	ROW=Y;																			//取得行.
	for(i=0;i<8;i++)														//循环,多次判断,取得PAGE和数据.
	{
		if(ROW<8)																	//行值小于8,执行if内语句.
		{		
			PAGE=0XB8+i;														//取得页值.
			DATA=DATA<<ROW;													//取得数据.
		 	break;																	//跳出for循环.
		 }
		ROW=ROW-8;																//行值减8.	
	}
	if(X>63)																		//当列值大于63时.
	{
		E=2;																			//选择第2片LCD.
		CLMD=(X-64)+64;														//取得列值.
	}
	else																				//否则.
	{
		E=1;																			//选择第2片LCD.
		CLMD=X+64;																//取得列值.
	}	
	DATA=DATA|LCDIN(CLMD,PAGE,E);								//求或.
	LCDOUT(DATA,CLMD,PAGE,E);										//向当前地址输入数据.
}

/* ************************************************************************
** 函 数 名:void LCDXB(int XBCS,int WORDS)
** 功能描述:根据谐波次数(XBCS),幅度(WORDS)在LCD上自动选择位置显示频谱图.
*************************************************************************** */
void LCDXB(int XBCS,int WORDS)
{
	int CLMD,PAGE,i;														//列-页-计数参数.
	CLMD=0X40+XBCS*6;														//根据谐波次数计算列值.
	PAGE=0XB8;																	//页的初地址.											
	for(WORDS>7;WORDS>7;PAGE++)									//页地址累加1,至幅值小于8.
	{
		WORDS-8;																	//幅值减8.
		for(i=0;i<3;i++)													//在相邻3列输出.
			LCDOUT(0XFF,CLMD+i,PAGE,1);							//输出数据.	
	}
	for(i=0;i<3;i++)														//在相邻3列输出.
		LCDOUT(WORDS,CLMD+i,PAGE,1);							//输出最后数据.
}

/* ************************************************************************
** 函 数 名:void OUTADC(int WOEDS)
** 功能描述:向MAX197输入控制字.
*************************************************************************** */
void OUTADC(int WORDS)
{
	TRISD=0X00;																	//<0000,0000>设置PORTD为输出.
	PORTA=(PORTA|0X0E)&0XFE;										//<uuuu,1110>译码后实现地址选择.
	PORTB=(PORTB|0X10)&0XDF;										//<uu01,uuuu>控制信号:写.
	PORTD=WORDS;																//将数据赋给PORTD端口.
	PORTB=PORTB|0X30;										
	PORTA=PORTA&0XF0;														//屏蔽所有地址.
}

/* ************************************************************************
** 函 数 名:int INADC()
** 功能描述:读取MAX197高低12位的AD转换数据.
*************************************************************************** */
signed int INADC()
{
	signed int WORDS;														//定义数据入口参数.
	TRISD=0XFF;																	//<1111,1111>设置PORTD为输入.
	PORTA=(PORTA|0X0E)&0XFE;										//<uuuu,1110>译码后实现地址选择.			
	PORTB=(PORTB|0X60)&0XEF;										//<u110,uuuu>控制信号:读高4位数据.
	WORDS=PORTD&0X0F;														//读取PORTD端口数据.
	PORTB=(PORTB|0X20)&0XAF;										//<u010,uuuu>控制信号:读低8位数据.
	WORDS=PORTD+(WORDS<<8);											//读取PORTD端口数据,并与低8位求和.
	PORTB=PORTB|0X30;														//屏蔽所有地址.
	PORTA=PORTA&0XF0;														//将读取的数据作为返回值.
	if(CHX==1)																	//双极性?
	{
		WORDS=WORDS<<4;														//数据左对齐.
		WORDS=WORDS/16;														//得到最终数据.
	}
	return WORDS;                               //返回数据.
}
/* ************************************************************************
** 函 数 名:void ADCHX()
** 功能描述:根据参数进行双通道AD采样.
*************************************************************************** */
void ADCHX()
{
	for(ADD=0;ADD<64;ADD++)										//采样64点.
	{
		OUTADC(ADWORDS);												//送第一路AD控制字.
		DELAY(0);																//延时.
		DATA[CHAN*2][ADD]=INADC();							//读取第一路AD转换数据.
		OUTADC(ADWORDS+1);											//送第二路AD控制字.
		DELAY(0);																//延时.
		DATA[1+CHAN*2][ADD]=INADC();						//读取第二路AD转换数据.
		DELAY(AD);															//延时控制采样频率.
	}
}
/* ************************************************************************
** 函 数 名:void ADSHOW()
** 功能描述:数据处理后显示两路信号波形.
*************************************************************************** */
void ADSHOW()
{
	int CH1,CH2;	
	signed int data;															//取数据,显示位置.
	if(CHX==0)																		//单极性采样.
	{
		CH1=40;																			//波形位置.
		CH2=60;																			//波形位置.
	}
	else
	{
		CH1=20;																			//波形位置.
		CH2=40;																			//波形位置.
	}
	LCDCLEAR(2);																	//清屏.
	for(ADD=0;ADD<64;ADD++)												//64点.
	{
		data=(signed int)(40.0*DATA[CHAN*2][ADD]/4096.0);		//数据处理.
   	LCDPIEX(ADD+64,CH1-data);														//输出显示.			
   	data=(signed int)(40.0*DATA[1+CHAN*2][ADD]/4096.0);	//数据处理.
   	LCDPIEX(ADD+64,CH2-data);														//输出显示.	
	}
}	
/* ************************************************************************
** 函 数 名:void ADCHD()
** 功能描述:单通道高频采样,数据处理,显示.
*************************************************************************** */
void ADCHD()
{
	long D,SHU;																		//数据.
	int n_x,k_x,i;																//循环参数.
	float Ur,Ui,Urn,Uin;													//数据处理中间变量.
	ADWORDS=ADCAN+7;															//确定MAX197控制字.
	for(ADD=0;ADD<64;ADD++)												//采样.
	{
		OUTADC(ADWORDS);														//送控制字.
		DELAY(0);																		//延时.
		DATA[0][ADD]=INADC();												//读取数据.
	}
	for(ADD=0;ADD<64;ADD++)												//显示波形.
	{
		D=(int)(40.0*DATA[0][ADD]/4096.0);					//取数据.
   	LCDPIEX(ADD+64,40-D);												//显示.
   }
	for(n_x=0;n_x<5;n_x++)												//计算.
	{
		Urn=0.0;																		//实部.
		Uin=0.0;																		//虚部.
		for(k_x=0;k_x<32;k_x++)											//n_x次谐波.
		{
			D=DATA[0][k_x];														//取数据计算.
			Urn=Urn+D/409.6*cos((2*n_x+1)*(k_x+1)*0.196);
			Uin=Uin+D/409.6*sin((2*n_x+1)*(k_x+1)*0.196);
		}
		Ur=Urn/16.0;                       					//
		Ui=Uin/16.0;																//
		SHU=(long)(100*sqrt(Ur*Ur+Ui*Ui));
		UI[0][n_x]=SHU;															//第n_x次谐波幅值.
		UI[0][5]=SHU*SHU+UI[0][5]; 									//           
	}	
	UI[0][5]=(long)sqrt(UI[0][5]);								//总幅值.
	for(i=0;i<5;i++)															//
  {
	  SHU=UI[0][i]*1000;													//
	 	SHU=SHU/(UI[0][5]);													//
	 	UP[0][i]=SHU;																//第i次谐波占有率.															
	}
	SHU=1000*(UI[0][5]-UI[0][0]);									//
	UP[0][5]=SHU/UI[0][5]; 												//畸变率.
	LCDCLEAN(12,2,126,7);													//清除数据显示区.
	for(i=0;i<6;i++)
	{
		OUTNUM(UI[0][i],1,28,2+i);									//显示幅值.
		OUTNUM(UP[0][i],3,56,2+i);									//显示占有率.
	}	
	ADWORDS=ADCAN;																//还原控制字.

⌨️ 快捷键说明

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