基于单片机的多功能信号发生器的源程序及电路图
- 格式:doc
- 大小:639.00 KB
- 文档页数:11
程序源代码#include <REGX52.H>#include <lcd1602.H>#include <AD9833_Serial.H>void Delay1ms(WORD count);//软件延时函数void display_freq(void); //更新频率函数BYTE code Cursor[]={0xC3,0XC4,0XC6,0XC7,0XC8,0XCA,0XCB,0XCC,0x85};//换算光标位置unsigned int a; //控制长时间不操作隐藏光标unsigned char step=4;//移动光标bit flag=0;//控制光标闪烁unsigned long int code Data []={10000000,1000000,100000,10000,1000,100,10,1}; //换算加减值unsigned long int Freqency_Out=1000; //初始化频率输出值unsigned char Wave_Out=1;unsigned char data DY[3] = {0x00,0x00,0x00} ;unsigned char DA;unsigned long int XS;sbit KEY1 = P1^0;sbit KEY2 = P1^1;sbit KEY3 = P1^2;sbit KEY4 = P1^3;sbit KEY5 = P1^4;sbit KEY6 = P1^5;sbit BEEP = P3^7;sbit din = P3^4;sbit clk = P3^5;sbit cs = P3^6;/*us级延时函数*//*******************************************************************/void DelayuS(unsigned int num){while( --num ) ;}/* 软件延时1*m毫秒*/void Delay1ms(WORD count){BYTE i, j;for( ; count>0; count--)for(i=2; i>0; i--)for(j=248; j>0; j--);}void display_freq(void) //显示频率{unsigned char j;unsigned long int temp;temp=Freqency_Out;tab2[3]=temp/10000000+0x30;//tab2[4]=temp%10000000/1000000+0x30;tab2[6]=temp%10000000%1000000/100000+0x30;tab2[7]=temp%10000000%1000000%100000/10000+0x30;tab2[8]=temp%10000000%1000000%100000%10000/1000+0x30;tab2[10]=temp%10000000%1000000%100000%10000%1000/100+0x30;tab2[11]=temp%10000000%1000000%100000%10000%1000%100/10+0x30;tab2[12]=temp%10000000%1000000%100000%10000%1000%100%10+0x30;WriteLCD(0,0xC0);// 设置显示位置为第二行第一个字for(j=0; j<15; j++){WriteLCD(1,tab2[j]);}switch(Wave_Out){case 1:Load_wave(0x2000,Freqency_Out,0xD000);break;case 2:Load_wave(0x2002,Freqency_Out,0xD000);break;case 3:Load_wave(0x2028,Freqency_Out,0xD000);break;}}void display_Wave(void) //变换波形{unsigned char j;switch(Wave_Out){case 1:WriteLCD(0,0x80);Load_wave(0x2000,Freqency_Out,0xD000);for(j=0; j<10; j++){WriteLCD(1,tab1_1[j]);}break;case 2:WriteLCD(0,0x80);Load_wave(0x2002,Freqency_Out,0xD000);for(j=0; j<10; j++){WriteLCD(1,tab1_2[j]);}break;case 3:WriteLCD(0,0x80);Load_wave(0x2028,Freqency_Out,0xD000);for(j=0; j<10; j++){WriteLCD(1,tab1_3[j]);}break;}// 设置显示位置为第二行第一个字}void initTimer(void) //定时器初始化初值{TMOD=0x2; //方式二TH0=0x49; //200usTL0=0x49;}/*******************************************************************/ /* 蜂鸣器响一声*//*******************************************************************/ void beep(){unsigned char y ;for (y=0 ;y<100 ;y++){DelayuS(60) ;BEEP=!BEEP ; //BEEP取反}BEEP=1 ; //关闭蜂鸣器DelayuS(40000) ;}void TLC5615(DA){unsigned char y;DA<<=6; //舍弃前6 位for(y=0;y<12;y++) //从高到低发送{if((DA&0x8000)==0)din=0;else din=1;//din = x&0x8000; //此处不能用din = x&0x8000;cs=0;clk=1;;;;clk=0;DA = DA<<1;}cs=1;}/* 电压转换与显示*//*******************************************************************/Disp_dianya(){DY[2]=XS/100+0x30 ;DY[0]=XS%100 ;DY[1]=DY[0]/10+0x30 ;DY[0]=DY[0]%10+0x30 ;WriteLCD(0,0x8B);WriteLCD(1,DY[2]);//十位数显示WriteLCD(0,0x8D);WriteLCD(1,DY[1]);//个位数显示WriteLCD(0,0x8E);WriteLCD(1,DY[0]);//小数显示}void main(void) //主函数{unsigned char i;initTimer();//定时器初始化TR0=1;ET0=1;DA=175;//DA初始电压XS=5;//显示初始电压TLC5615(DA);LCD_Initial(); //液晶初始化WriteLCD(0,0x80);// 设置显示位置为第一行第一个字for(i=0; i<16; i++){WriteLCD(1,tab1_1[i]);}//每行16个字,且光标自动右移WriteLCD(0,0xC0);// 设置显示位置为第二行第一个字for(i=0; i<16; i++){WriteLCD(1,tab2[i]);} //每行16个字,且光标自动右移Disp_dianya();DDSIni();//初始化AD9833Load_wave(0x2000,Freqency_Out,0xD000);//1KHz正弦信号display_freq();EA=1; //开启总中断WriteLCD(0,Cursor[step]);// 设置显示位置为第二行第一个字while(1){if(KEY2==0)//Right 光标右移{Delay1ms(50);if(KEY2==0){if(a!=0)//在没有光标时,第一次按下向左,向右按键时,光标不移动,只是显示出光标,并闪烁{step++;if(step==9) step=0;}WriteLCD(0,0x0F); // 开显示,开光标,闪烁WriteLCD(0,Cursor[step]);//显示出当前光标的位置EA=1;a=0; //当有按键按下时,开启定时器,计时开始。
beep();while(KEY2==0);}}if(KEY1==0)//Left 光标左移{Delay1ms(50);if(KEY1==0){if(a!=0)//在没有光标时,第一次按下向左,向右按键时,光标不移动,只是显示出光标,并闪烁{if(step==0) step=9;step--;}WriteLCD(0,0x0F); // 开显示,开光标,闪烁WriteLCD(0,Cursor[step]); //显示出当前光标的位置EA=1;a=0;//当有按键按下时,开启定时器,计时开始。
beep();while(KEY1==0);}}if(KEY3==0)//Up 加{Delay1ms(50);if(KEY3==0){if(a!=0)//在没有光标时,不能调整频率{if(step<8){if(Freqency_Out+Data[step]<=12500000) //判断频率是否大于12.5MHZ{Freqency_Out=Freqency_Out+Data[step];// Load_wave(0x2000,Freqency_Out,0xD000);display_freq();//液晶刷新显示,且更新频率、相位WriteLCD(0,Cursor[step]);//显示出当前光标的位置}}if(step>=8){Wave_Out++;if(Wave_Out==4)Wave_Out=1;display_Wave();WriteLCD(0,Cursor[step]);//显示出当前光标的位置}}a=0; //定时器重新开始计算开始时间,防止在按的时候隐藏光标beep();while(KEY3==0);}}if(KEY4==0)//Down 减{Delay1ms(50);if(KEY4==0){if(a!=0) //在没有光标时,不能调整频率{if(step<8){if(Freqency_Out>=Data[step])//判断频率是否大于0HZ{Freqency_Out=Freqency_Out-Data[step];//Load_wave(0x2000,Freqency_Out,0xD000);display_freq();//液晶刷新显示,且更新频率、相位WriteLCD(0,Cursor[step]);//显示出当前光标的位置}}if(step>=8){if(Wave_Out==1)Wave_Out=4;Wave_Out--;display_Wave();WriteLCD(0,Cursor[step]);//显示出当前光标的位置}}a=0;//定时器重新开始计算开始时间,防止在按的时候隐藏光标beep();while(KEY4==0);}}if(KEY5==0)//幅度加{Delay1ms(50);if(KEY5==0){DA++;XS++;TLC5615(DA);Disp_dianya();beep();Delay1ms(50);}}if(KEY6==0)//幅度减{Delay1ms(50);if(KEY6==0){DA--;XS--;TLC5615(DA);Disp_dianya();beep();Delay1ms(50);}}if(flag==1) //当按键超过4S不操作时光光标{flag=0;WriteLCD(0,0x0C);// 关光标,关闪烁a=0;EA=0;//关掉定时器,清除计数}}}void timer0(void) interrupt 1 //中断服务程序,用于隐藏光标{a++;if(a==30000){a=0;flag=1;}}#include <intrins.h>#define BYTE unsigned char //宏定义#define WORD unsigned intvoid WriteLCD(BYTE style, BYTE input); // 向LCD写入命令或数据函数BYTE Wait(void);//等待写操作结束函数void LCD_Initial(void);//初始化液晶函数/* 液晶管脚连线*/sbit LCDRS = P2^5; // 寄存器选择1:数据;0:指令sbit LCDRW = P2^6; // 读写操作选择1:读;0:写sbit LCDE = P2^7; // 使能信号sbit BUSY = ACC^7; // 忙标志位(非管脚)BYTE code tab1_1[]={"Wave=1 Sin 0.00V"}; //初始化液晶显示值正弦波BYTE code tab1_2[]={"Wave=2 Tri "}; //初始化液晶显示值三角波BYTE code tab1_3[]={"Wave=3 Squ "}; //初始化液晶显示值方波BYTE tab2[]={" F=00,000,000Hz "};void Delay(WORD count){BYTE i, j;for( ; count>0; count--)for(i=2; i>0; i--)for(j=248; j>0; j--);}/* 等待写操作结束函数*/BYTE Wait(void){LCDRS = 0;LCDRW = 1; _nop_();LCDE =1; _nop_(); // 读忙标志和AC码时,LCDE高电平do{ACC =P0; //判断忙信号为P0_7}while(BUSY == 1); // 写操作忙,等待LCDE = 0;Delay(1);return ACC;}void WriteLCD(BYTE style, BYTE input) // 向LCD写入命令或数据{LCDRS = style;LCDRW = 0; _nop_();LCDE = 1; _nop_(); // LCDE下降沿写入P0=input; _nop_(); //P0口为数据输入口LCDE = 0; _nop_();Wait(); //等待写入完成}void LCD_Initial(void) // 液晶初始化函数{LCDE =0;Delay(10);WriteLCD(0,0x38); // 8位数据口,两行显示,5*7点阵,// 功能设置WriteLCD(0,0x0f); // 开显示,光标,闪烁WriteLCD(0,0x06); // AC自动增一,画面不动WriteLCD(0,0x02); // 光标返回到00H AC=0WriteLCD(0,0x01); // 清屏}/*AD9833串行控制模式,采用25MHZ有源晶振,*/void DDSIni(void);void AD9833_reset(void);void SDelay(unsigned char DelayNum);void AD9833_writedata(unsigned int DDSdata);void Load_wave(unsigned int Contr_Reg_data,unsigned long int Freq_data,unsigned int Phs_data);//void Load_wave(unsigned int Contr_Reg_data,unsigned int Fre_MSBdata,unsigned int Fre_LSBdata,unsigned int Phs_data);//Load_wave(0x2000,0x4020,0x7020,0xD000);//50KHz正弦信号VPP=600MV//Load_wave(0x2002,0x4020,0x7020,0xD000);//50KHz三角波信号VPP=600MV//Load_wave(0x2028,0x4020,0x7020,0xD000);//50KHz方波信号0-5V 50%占空比//Load_wave(0x2020,0x4020,0x7020,0xD000);//25KHz方波信号0-5V 50%占空比sbit FSYNC= P2^2; //AD9833控制脚sbit SCLK= P2^1;sbit SDA TA= P2^0;void DDSIni(void){FSYNC=1; //FSYNC disableSCLK=1; //Clock highSDATA=0;AD9833_reset();}void AD9833_reset(void){//add code hereAD9833_writedata(0x0100); //寄存器复位AD9833_writedata(0x2000); //准备清空频率寄存器0AD9833_writedata(0x4000); //Filled with 0AD9833_writedata(0x4000); //Filled with 0AD9833_writedata(0x2000); //Prepare for clear Fre1AD9833_writedata(0x8000); //Filled with 0AD9833_writedata(0x8000); //Filled with 0AD9833_writedata(0xD000); //clear PHS 0AD9833_writedata(0xF000); //clear PHS 1}void SDelay(unsigned char DelayNum){while(DelayNum--);}//////////////////////////////////////*函数描述:AD9833写数据操作/*写入参数:AD9833 控制字,16bit/*返回参数:无/*描述:标准时序*////////////////////////////////////void AD9833_writedata(unsigned int DDSdata){unsigned char data_num=0;unsigned int DDSdata_temp;DDSdata_temp=DDSdata;SCLK=1;SDelay(4);FSYNC=0; //DDS ableSDelay(4);for(data_num=0;data_num<16;data_num++){if(DDSdata_temp & 0X8000 ){SDATA=1;}else{SDATA=0;}SDelay(5);SCLK=0;SDelay(5);SDA TA=0;SDelay(5);SCLK=1;DDSdata_temp=DDSdata_temp<<1;if(data_num < 15){SDelay(50);}}FSYNC=1;}//////////////////////////////////////*函数描述:AD9833加载波新/*写入参数:控制字、32bit(28bit有效)的频率数据,16bit(12bit有效)的相位数据/*返回参数:无*////////////////////////////////////void Load_wave(unsigned int Contr_Reg_data,unsigned long int Freq_data,unsigned int Phs_data) {unsigned long int Freq_temp = 0;unsigned int Fre_MSBdata,Fre_LSBdata;Freq_temp = (unsigned long int)(10.738*Freq_data); // SYSCLK = 25 MHz 2^28/25000000=10.7374 Fre_LSBdata=Freq_temp&0x3fff;Fre_LSBdata=Fre_LSBdata|0x4000;Fre_MSBdata=(Freq_temp>>14)&0x3fff;Fre_MSBdata=Fre_MSBdata|0x4000;AD9833_writedata(Contr_Reg_data);AD9833_writedata(Fre_LSBdata);AD9833_writedata(Fre_MSBdata);AD9833_writedata(Phs_data);}/*void Load_wave(unsigned int Contr_Reg_data,unsigned int Fre_MSBdata,unsigned int Fre_LSBdata,unsigned int Phs_data){//addunsigned int Fre_MSBdata_temp=Fre_MSBdata;unsigned int Fre_LSBdata_temp=Fre_LSBdata;unsigned int Contr_Reg_data_temp=Contr_Reg_data;unsigned int Phs_data_temp=Phs_data;AD9833_writedata(Contr_Reg_data_temp);AD9833_writedata(Fre_LSBdata_temp);AD9833_writedata(Fre_MSBdata_temp);AD9833_writedata(Phs_data);}*/附录 B 系统原理图附录 C 硬件实物图11。