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

📄 ad9835_v2.c

📁 51单片机工程应用实例
💻 C
字号:
//F=12MHz with LCD1602
//2008/4/13 AD9835 on AT89C51

#include <reg51.H>
#include <stdio.h>
#include <INTRINS.H>//_nop_()

typedef  unsigned char uchar;
typedef  unsigned int uint;

//键排列
// 7 8 9 C
// 4 5 6 D
// 1 2 3 E
// A 0 B F

//LCD 1602
sbit	LCD_D7=P2^7;
sbit	LCD_D6=P2^6;
sbit	LCD_D5=P2^5;
sbit	LCD_D4=P2^4;
sbit	LCD_E =P2^3;
sbit	LCD_RW=P2^2;
sbit	LCD_RS=P2^1;

//I/O
sbit 	BEP=P2^0;//Beep
sbit 	LED=P3^2;//RED LED
//AD9835
sbit 	DAT=P3^0;//
sbit 	CLK=P3^1;//
sbit 	SYC=P3^3;//

//FREQ
sbit 	FRQ=P3^5;//T1 check
#define No_key  255 

//键值
#define MHz 12	//MHz 
#define KHz 13	//KHz
#define Hzz 14	//Hz
#define point 15//小数点
#define shift 11//不用
#define back 10	//改正

uchar freq[8]={0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00};//8位频率数800.0Hz
uchar F_word[4];

uchar step=8,cur=7,act=0,key=No_key;//act有效位
uchar buf[9];//输入缓存

/*------------------------------------------------------------------
Public function prototypes
--------------------------------------------------------------------*/
void LCD_init       (void);
void LCD_en_write   (void);
void LCD_write_char (uchar cd,uchar ab);
void LCD_set_xy     (uchar x, uchar y);
void LCD_write_str 	(uchar X,uchar Y,uchar *s);
void LCD_byte		(uchar abc);

void delay_nus		(uint n);
void del_ms         (uint n);

uchar Key_scan		(void);
void  Key_num		(uchar n);	//输入数字并显示
uchar Key_table		(k);
void bee();						//低有效蜂鸣
void Long_bee		(void);		//低有效蜂鸣长声

void AD9835_byte	(uchar a);	//发一个字节
void AD9835_word	(uchar *p);	//发一个字两个字节
void AD9835_init	(void);		//初始化和写频
void AD9835_calc	(void); 	//计算出频率寄存器的四个字节值
void disp(void);				//显示

//------------------------------------
void LCD_init(void)       	//液晶初始化
{
 	P1=0xFF;
 	P3=0xff;				//输出
 	LCD_RS=0;  				//
 	del_ms(50);
                
    LCD_write_char(0x30,0); 
    del_ms(6); 
    LCD_write_char(0x30,0);	//
    del_ms(1); 
    LCD_write_char(0x30,0);	//上电即显示正常,无需复位        
    del_ms(1); 
    LCD_write_char(0x02,0);
    del_ms(1); 
    LCD_write_char(0x28,0); //4bit test显示模式设置(不检测忙信号) 
    del_ms(1);  
    LCD_write_char(0x08,0); // 显示关闭 
    del_ms(1); 
   	LCD_write_char(0x01,0); // 显示清屏 
    del_ms(1); 
    LCD_write_char(0x06,0); // 显示光标移动设置 
    del_ms(1); 
    LCD_write_char(0x0C,0); // 显示开及光标设置 
    del_ms(10); 
}
//---------------------------------------------
void LCD_write_str(uchar X,uchar Y,uchar *s)
  {
    LCD_set_xy( X, Y ); 	//写地址    
    while (*s)  			// 写显示字符
      {
        LCD_write_char( 0, *s );
		s ++;
      }
  }
  void LCD_set_xy( uchar x, uchar y )  //写地址函数
  {
    uchar address;
    if (y == 0) address = 0x80 + x;
    else 
       address = 0xc0 + x;
    LCD_write_char( address, 0 );
  }
//------------------------------------------------
void LCD_en_write(void)  	//液晶使能
{
  _nop_();
  LCD_E=1;//EN=1
  _nop_();
  LCD_E=0;//EN=0
}
//------------------------------------------------
void LCD_write_char(uchar cd,uchar ab) // 写数据
{ 
 delay_nus(20);
 if(cd==0)
 {
  LCD_RS=1;  				//RS=1,写显示内容  
  LCD_byte(ab);
 }
 else
 {
  LCD_RS=0;   				//RS=0,写命令
  LCD_byte(cd);
  }
}
//-----------------------------------------------
void LCD_byte(uchar abc)//
{
	delay_nus(50);
	if(((abc<<0)&0x80)==0) 	//MSB is output first
	 LCD_D7=0;      		//abc=0
	 else LCD_D7=1; 		//abc=1
	if(((abc<<1)&0x80)==0) 	//MSB is output first
	 LCD_D6=0;      		//abc=0
	 else LCD_D6=1; 		//abc=1
	if(((abc<<2)&0x80)==0) 	//MSB is output first
	 LCD_D5=0;      		//abc=0
	 else LCD_D5=1; 		//abc=1
	if(((abc<<3)&0x80)==0) 	//MSB is output first
	 LCD_D4=0;      		//abc=0
	 else LCD_D4=1; 		//abc=1
	LCD_en_write();
	
	if(((abc<<4)&0x80)==0) 	//MSB is output first
	 LCD_D7=0;      		//abc=0
	 else LCD_D7=1; 		//abc=1
	if(((abc<<5)&0x80)==0) 	//MSB is output first
	 LCD_D6=0;      		//abc=0
	 else LCD_D6=1; 		//abc=1
	if(((abc<<6)&0x80)==0) 	//MSB is output first
	 LCD_D5=0;      		//abc=0
	 else LCD_D5=1; 		//abc=1
	if(((abc<<7)&0x80)==0) 	//MSB is output first
	 LCD_D4=0;      		//abc=0
	 else LCD_D4=1; 		//abc=1
	LCD_en_write();
	 	
}

//-------------------------------------
uchar Key_table(k)
{	
	uchar TempNum;
	switch (k)
	{
	case 0x11:TempNum=12;break;
	case 0x12:TempNum=13;break;
	case 0x14:TempNum=14;break;
	case 0x18:TempNum=15;break;
	case 0x88:TempNum=10;break;
	case 0x28:TempNum=11;break;
	case 0x48:TempNum=0;break;
	case 0x84:TempNum=1;break;
	case 0x44:TempNum=2;break;
	case 0x24:TempNum=3;break;
	case 0x82:TempNum=4;break;
	case 0x42:TempNum=5;break;
	case 0x22:TempNum=6;break;
	case 0x81:TempNum=7;break;
	case 0x41:TempNum=8;break;
	case 0x21:TempNum=9;break;
	default:break;
	}
	return TempNum;
}

//--------------------------------------
uchar Key_scan(void)
{uchar sccode,recode;
   P1=0xf0;
   if((P1&0xf0)!=0xf0) 			/* 若有健按下*/
   {del_ms(12);              	/*延时去抖动*/
     if((P1&0xf0)!=0xf0)   
	  {sccode=0xfe;     		/*逐行扫描初值*/
	   while((sccode&0x10)!=0)
	    {P1=sccode;     		/*输出行扫描码*/
		 if((P1&0xf0)!=0xf0)   	/*本行有键按下*/
		 {recode=(P1&0xf0)|0x0f;
		  return((~sccode)+(~recode)); 	/*返回特征字节码*/
		 }
		 else
		   sccode=(sccode<<1)|0x01; 	/*行扫描码左移一位*/
		}
	  }
	}
	 return No_key;  			/*无键按下返回0*/
 }

//-------------------------------
void Key_num(unsigned char n)//输入数字并显示
{
	if(step==0){Long_bee();}
	else {	
	buf[step]=n;n=n|0x30;
	LCD_set_xy(cur,0);		//地址						
	LCD_write_char(0,n);	
	step--;cur++;}
	key=No_key;
}

//---------------------------
void bee()//低有效蜂鸣
{ 
  P2=P2&0xFE;//P2.0=0
  del_ms(100);
  P2=P2|0x01;//P2.0=1
}
//---------------------------
void Long_bee(void)//长蜂鸣
{ 
  BEP=0;//PB0=1
  del_ms(400);
  BEP=1;//PB0=0
}
//----------------------------------------------
void delay_nus(uint n)       //N us延时函数
  {
   uint i=0;
   for (i=0;i<n;i++)
   _nop_();
  }
  
//--------------------------------------
void del_ms(uint n)//n毫秒延时
{ uchar j;
 while(n--)
 {for(j=0;j<125;j++);}
}

//---------------------------
void disp(void)//显示
{   
	uchar disbuf[8];
    uchar i;
	for(i=0;i<=7;i++)
	{disbuf[i]=freq[i]|0x30;}
	if(disbuf[7]==0x30)
		{disbuf[7]=0x20;
		if(disbuf[6]==0x30)
			{disbuf[6]=0x20;
			if(disbuf[5]==0x30)
				{disbuf[5]=0x20;
				if(disbuf[4]==0x30)
					{disbuf[4]=0x20;
					if(disbuf[3]==0x30)
						{disbuf[3]=0x20;
						if(disbuf[2]==0x30)
							{disbuf[2]=0x20;
						}
					}
				}
			}
		}
	}
	LCD_set_xy(0,1);//地址						
	LCD_write_char(0,disbuf[7]); 
	LCD_write_char(0,disbuf[6]); 
	LCD_write_char(0,disbuf[5]); 
	LCD_write_char(0,disbuf[4]); 
	LCD_write_char(0,disbuf[3]); 
	LCD_write_char(0,disbuf[2]); 
	LCD_write_char(0,disbuf[1]);
	LCD_write_char(0,0x2e);//小数点
	LCD_write_char(0,disbuf[0]); 	
	LCD_write_str(9,1," Hz TJX");
	
}

//--------------------------------
void AD9835_byte(uchar a)//发一个字节
{
	uchar n=0;
	for(n=0;n<8;n++)
	{
	 if(((a<<n)&0x80)==0){DAT=0;} 	//DATA=0 MSB is output first
	 else{DAT=1;} 					//DATA=1
	
	 CLK=0;							//SCLK=0
	 _nop_();
	 _nop_();
	 CLK=1;							//SCLK=1
	 
	}
}
//---------------------------
void AD9835_word(uchar *p)//发一个字两个字节
{

	SYC=0;//FSYNC=0

    AD9835_byte(*p);	
    p++;
	AD9835_byte(*p);

	SYC=1;//FSYNC=1
}

//--------------------------------
void AD9835_init(void)//passed!
{
	uchar dds[2]={0xF8,0X00};

	AD9835_word(dds);

	dds[0]=0x33;
	dds[1]=F_word[0];
	AD9835_word(dds);
	dds[0]=0x22;
	dds[1]=F_word[1];
	AD9835_word(dds);
	dds[0]=0x31;
	dds[1]=F_word[2];
	AD9835_word(dds);
	dds[0]=0x20;
	dds[1]=F_word[3];
	AD9835_word(dds);

	dds[0]=0xC0;
	dds[1]=0x00;
	AD9835_word(dds);

}
//-------------------------------------
//Fc=50MHz K=85.8993459 passed!!
//计算出频率寄存器的四个字节值
void AD9835_calc(void)
{
	unsigned long z=0;
	float x;
	x=(freq[0]*0.1+freq[1]*1+freq[2]*10+freq[3]*100+freq[4]*1000+freq[5]*10000
+freq[6]*100000+freq[7]*1000000)*85.8993459;
	z=x;	
	F_word[3]=(char)z;
	F_word[2]=(char)(z>>8);
	F_word[1]=(char)(z>>16);
	F_word[0]=(char)(z>>24);
}

//------------------------------------
int main(void) 
{
	uchar smalkey=0,flag=0;//位置
	uchar i,j,k1=No_key,k2=No_key;
	uchar dot=0xff;//小数点cursor
	uchar intc=0;//整数位,有效数位 
    
	del_ms(100);	
	LCD_init();	
	LCD_write_str(0,0,"InputF=           ");//显示第一行
	
	del_ms(100);
	disp(); 								//第二行显示默认值800Hz
	AD9835_calc();
	AD9835_init();							//输出800Hz正弦波
	
	while(1)
  {
    	del_ms(200);	
		k2=Key_scan();
		if (k2!=No_key)
		{key=k2;k2=No_key;bee();
		key=Key_table(key);
		switch(key) 
		{case 1:
    		{Key_num(1);}break; 
		case 2:
    		{Key_num(2);}break;
		case 3:
    		{Key_num(3);}break;
		case 4:
    		{Key_num(4);}break;
		case 5:
    		{Key_num(5);}break;
		case 6:
    		{Key_num(6);}break;
		case 7:
    		{Key_num(7);}break;
		case 8:
    		{Key_num(8);}break;
		case 9:
    		{Key_num(9);}break;
		case 0:
    		{Key_num(0);}break;
		case MHz:
			{
	 			if(dot<7)
				{
				for(i=0;i<=7;i++)
					{freq[i]=9;}
				 Long_bee();
				}
				else if(dot==0xff)
				{
				for(i=0;i<=7;i++)
				 	{freq[i]=0;}
					if(step<7)
					{
					for(i=0;i<=7;i++)
					{freq[i]=9;}
				 	Long_bee();
					}
					else 
					{
					freq[7]=buf[8];
					}
				}
	 			else 
				{
					for(i=0;i<=7;i++)
						{freq[i]=0;}							
					intc=8-dot;
					act=7+intc;			//整数位					
					i=6+intc;j=8;       //起始位										
					for(;act>0;act--)
					{freq[i]=buf[j];i--;j--;}					
				}
				disp();
				LCD_write_str(0,0,"InputF=           ");
				AD9835_calc();
				AD9835_init();
 			    dot=0xff;
				act=0;
				step=8;
				cur=7;
				for(i=0;i<=8;i++)
					{buf[i]=0;}
	 			key=No_key;
			}break;
		case KHz:
			{	
	 			if(dot<4)
				{for(i=0;i<=7;i++)
					{freq[i]=9;}
					Long_bee();}
				else if(dot==0xff)
				{	
				 for(i=0;i<=7;i++)
					{freq[i]=0;}
					if(step<4)
					{
						for(i=0;i<=7;i++)
						{freq[i]=9;}
						Long_bee();}
					else 
					{
						for(i=0;i<=7;i++)
						{freq[i]=0;}							
						act=8-step;	
						i=act+3;j=8;							      							
						for(;act>0;act--)
						{freq[i]=buf[j];i--;j--;}
					}
				}
	 			else
				{
					for(i=0;i<=7;i++)
					{freq[i]=0;}							
					intc=8-dot;
					act=4+intc;	
					i=3+intc;j=8;       					
					for(;act>0;act--)
					{freq[i]=buf[j];i--;j--;}					
				}
				disp();
				LCD_write_str(0,0,"InputF=           ");
				AD9835_calc();
				AD9835_init();
 			    dot=0xff;
				act=0;
				step=8;
				cur=7;
				for(i=0;i<=8;i++)
					{buf[i]=0;}
	 			key=No_key;
			}break;
		case Hzz:
			{
	 			if(dot<1)
				{	for(i=0;i<=7;i++)
					{freq[i]=9;}
					Long_bee();}
		 		else if(dot==0xff)//no dot
				{	
				 	for(i=0;i<=7;i++)
				 	{freq[i]=0;}
					if(step<1)
					{
						for(i=0;i<=7;i++)
							{freq[i]=9;}
							Long_bee();}
					else 
					{
						for(i=0;i<=7;i++)
							{freq[i]=0;}							
							act=8-step;	
							i=act;j=8;							      							
							for(;act>0;act--)
							{freq[i]=buf[j];i--;j--;}
					}
				}		
	 			else 
				{
						for(i=0;i<=7;i++)
							{freq[i]=0;}							
							intc=8-dot;
							act=1+intc;
							i=intc;j=8;      			
							for(;act>0;act--)
							{freq[i]=buf[j];i--;j--;}					
				}
				for(i=0;i<=7;i++)
				{
					if(freq[i]>0)
					{flag=1;}}//Not all=0;
					if(flag==0)
					{Long_bee();
					freq[0]=1;}//all=0 
					else {flag=0;}
				disp();
				LCD_write_str(0,0,"InputF=           ");
				AD9835_calc();
				AD9835_init();
 			    dot=0xff;
				act=0;
				step=8;
				cur=7;
				for(i=0;i<=8;i++)
					{buf[i]=0;}
	 			key=No_key;
			}break;
		case point:
			{ 
				if(step==0)
				{Long_bee();}
				else 
				{	
					LCD_write_str(cur,0,".");
					dot=step;
					cur++;}
					key=No_key;
			}break;
		case back://
			{  	
				if(cur==7)
					{
						Long_bee();
						key=No_key;break;
					}
				if(dot==step)
					{dot=0xff;}
				else {step++;}
					cur--; 						
					LCD_set_xy(cur,0);
					LCD_write_char(0x0d,0);  //display blink on
					key=No_key;
			}break;
		case shift://
	 			{ key=No_key;}break;//
				
		default:break; 
		}//switch   
		}//if
 	
   } //while  

} 

⌨️ 快捷键说明

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