输出正弦波,三角波,方波,LCD显示,独立按键可调。分享给大家,应该是硬件问题吧,噪声比较大,不知如何处理。
制作出来的实物图如下:
波形图:
单片机源程序如下:- #include <reg52.h>
- #include <math.h>
- #define uchar8 unsigned char
- #define uint16 unsigned int
- #define ulong32 unsigned long
- //给正弦、三角、方波编码
- #define SIN 0
- #define TRI 1
- #define SQU 2
- //显示字库
- uchar8 code table_desk[]="WAV FRE M K 1";
- uchar8 code table_wave[]="sintrisqu";
- uchar8 code table_num[]="0123456789";
- uint16 Config_Data[8]={0};
- //AD9833控制端
- sbit FSYNC=P3^4;
- sbit SCLK=P3^3;
- sbit SDATA=P3^2;
- //1602液晶控制端
- sbit lcden = P0^7;
- sbit lcdrs = P0^6;
- //
- sbit KEY0 = P0^0;
- sbit KEY1 = P0^1;
- sbit KEY2 = P0^2;
- sbit KEY3 = P0^3;
- sbit KEY4 = P0^4;
- sbit KEY5 = P0^5;
- //
- sbit LED0 = P1^0;
- sbit LED1 = P1^1;
- sbit LED2 = P1^2;
- sbit LED3 = P1^3;
- sbit LED4 = P1^4;
- sbit LED5 = P1^5;
- bit fre_r = 0;//AD9833的两个频率字寄存器建议交替使用
- uchar8 wav = 0;//波形,默认正弦波
- ulong32 fre = 1000;//频率,默认1KHz
- uchar8 meg = 0 ,hunk= 0, tenk = 0,tho = 1,hun=0 ,ten = 0, uni = 0;//频率字的各个位
- uchar8 bit_select = 0;//频率位调节的选择标志
- uchar8 num; //公用循环增量
- //AD9833的驱动函数
- void Wave_Generate(ulong32,uchar8);
- //1ms延时函数
- void delay(uint16 z)
- {
- uint16 x,y;
- for(x = z;x>0;x--)
- for(y =110;y>0;y--);
- }
- //向液晶写命令,rs端置低
- void write_com(uchar8 com)
- {
- delay(5);
- delay(5);
- P2 = com;
- lcdrs = 0;
- lcden = 1;
- lcden = 0;
- }
- //向液晶写数据,rs端置高即可
- void write_date(uchar8 date)
- {
- delay(5);
- delay(5);
- P2 = date;
- lcdrs = 1;
- lcden = 1;
- lcden = 0;
- }
- //液晶初始化
- void init_lcd()
- {
- lcden = 0;
- write_com(0x38);//16×2显示,5×7点阵,8位数据接口
- delay(5);
- write_com(0x0c);//开显示,不显示光标
- delay(5);
- write_com(0x06);//写一个字符之后地址指针自动加1
- delay(5);
- write_com(0x01);//显示清零,数据指针清零
- }
- //波形标示函数,在第二行前三个字符标明信号波形
- void wave(uchar8 w_wave)
- {
- write_com(0xc0);//定位到第二行第一字符
- switch(w_wave)
- {
- case 0:
- for(num = 0;num < 3;++num)
- {
- write_date(table_wave[num]);
- delay(5);
- }
- break;
- case 1:
- for(num = 3;num < 6;++num)
- {
- write_date(table_wave[num]);
- delay(5);
- }
- break;
- case 2:
- for(num = 6;num < 9;++num)
- {
- write_date(table_wave[num]);
- delay(5);
- }
- break;
- default:
- for(num = 0;num < 3;++num)
- {
- write_date('?');
- delay(5);
- }
- break;
- }
- }
- //////////////////////////////////////////
- //向ad9833写一命令字(2Bytes)
- void AD9833_Send_Word(uint16 Data_In)
- {
- uchar8 i;
- uchar8 j;
- SCLK=1;
- FSYNC=0;
- for(i=0;i<16;i++)
- {
- SCLK=1;
- SDATA=(bit)((Data_In & 0x8000)>>15);
- j=0x01;
- while(j--);
- SCLK=0;
- Data_In=Data_In<<1;
- j=0x01;
- while(j--);
- }
- FSYNC=1;
- SCLK=0;
- }
- //波形发生函数
- //入口参数: 频率:Freq (<=12000000)
- // 形状:0(正弦波),1(三角波),2(方波)
- //默认: Fmclk=25MHz, 0相移,方波不分频.
- void Wave_Generate(ulong32 Freq,uchar8 Shape)
- {
- ulong32 temp;
- uchar8 k;
- if(Freq>12000000) Freq=12000000;
- switch(Shape)
- {
- case 0: Config_Data[0]=0x2108; // 0010 0001 0000 1000 reset(D8) =1
- Config_Data[7]=0x2008; // 0010 0000 0000 1000
- break;
- case 1: Config_Data[0]=0x210A; //0010 0001 0000 1010
- Config_Data[7]=0x200A; //0010 0000 0000 1010
- break;
- case 2: Config_Data[0]=0x2128; //0010 0001 0010 1000
- Config_Data[7]=0x2028; //0010 0000 0010 1000
- break;
- default:Config_Data[0]=0x2108; //0010 0001 0000 1000
- Config_Data[7]=0x2008; //0010 0000 0000 1000
- }
- temp=(long)(((double)Freq)*10.737418); //temp=Freq*(0x10000000/20000000);
- Config_Data[1]=temp&0x00003fff; //0000 0000 0000 0000 0011 1111 1111 1111
- Config_Data[3]=Config_Data[1];
- Config_Data[2]=(temp&0x0fffc000)>>14; //0000 1111 1111 1111 1100 0000 0000 0000
- Config_Data[4]=Config_Data[2];
- Config_Data[1]=Config_Data[1]|0x4000; //0100 0000 0000 0000
- Config_Data[2]=Config_Data[2]|0x4000; //0100 0000 0000 0000
- Config_Data[3]=Config_Data[3]|0x8000; //1000 0000 0000 0000
- Config_Data[4]=Config_Data[4]|0x8000; //1000 0000 0000 0000
- Config_Data[5]=0xC000; //1100 0000 0000 0000
- Config_Data[6]=0xE000; //1110 0000 0000 0000
- for(k=0;k<8;k++)
- {
- AD9833_Send_Word(Config_Data[k]);
- }
- }
- void Wave_Fre_ALT(bit fre_reg,ulong32 Freq)//寄存器
- {
- ulong32 temp;
- if(Freq>12000000) Freq=12000000;
- temp=(long)(((double)Freq)*10.737418); //temp=Freq*(0x10000000/20000000);268435456/25=10.737418,25是晶振频率268435456/30=8.947848
- Config_Data[0]=Config_Data[0] & 0x3eff; // 0011 1110 1111 1111
- Config_Data[1]=temp&0x00003fff; //0000 0000 0000 0000 0011 1111 1111 1111
- Config_Data[2]=(temp&0x0fffc000)>>14; //0000 1111 1111 1111 1100 0000 0000 0000
- Config_Data[5]=0xC000; //1100 0000 0000 0000
- Config_Data[6]=0xE000; //1110 0000 0000 0000
- if(fre_reg)
- {
- Config_Data[1]=Config_Data[1]|0x8000; //1000 0000 0000 0000连续的两个频率字的16 15位为10
- Config_Data[2]=Config_Data[2]|0x8000; //1000 0000 0000 0000表示写到频率寄存器1
- Config_Data[7]=Config_Data[7]|0x0800; //0000 1000 0000 0000控制字的FSELECT为1/////////^^^^^^^^^^^^^^^^^
- }
- else
- {
- Config_Data[1]=Config_Data[1]|0x4000; //0100 0000 0000 0000
- Config_Data[2]=Config_Data[2]|0x4000; //0100 0000 0000 0000
- Config_Data[7]=Config_Data[7]&0xf7ff; //1111 0111 1111 1111//……………………………………………………………………………………………………………难道是以前的写错了?
- }
- AD9833_Send_Word(Config_Data[0]);
- AD9833_Send_Word(Config_Data[1]);
- AD9833_Send_Word(Config_Data[2]);
- AD9833_Send_Word(Config_Data[5]);
- AD9833_Send_Word(Config_Data[6]);
- AD9833_Send_Word(Config_Data[7]);
- }
- ////////////////////////////////////////////
- //在1602指定位显示数据
- void write_lcd(uchar8 whe,uchar8 n)
- {
- if(whe < 16)//第一行
- {
- write_com(0x80+whe-1);
- write_date(n);
- }
- else //第二行 21表示第二行第一个位置
- {
- write_com(0x80+0x40 + whe-21);
- write_date(n);
- }
- }
- //键盘扫描函数,根据不同的按键进行相应波形和频率的设置
- void keyscan()
- {
- if(!KEY0)//切换波形
- {
- delay(10);
- if(!KEY0)
- {
- ++wav;
- if(wav > 2)
- wav = 0;
- LED0 = 0;
- wave(wav);
- write_com(0x0c);
- Wave_Generate(fre,wav);
- while(!KEY0);
- LED0 = 1;
- }
- }
-
- if(!KEY1)//切换频率的不同数位
- {
- delay(10);
- if(!KEY1)
- {
- LED1 = 0;
- write_com(0x0e);//显示光标
- ++bit_select; //选择的频率字的位移动
- if(bit_select > 7)
- {
- bit_select = 1;
- }
- write_com(0xcf - bit_select ); //光标移动到相应的位上
- while(!KEY1);
- LED1 = 1;
- }
- }
- if(!KEY2)//频率数字加按钮
- {
- delay(10);
- if(!KEY2)
- {
- LED2 = 0;
- switch(bit_select)
- {
- case 1:
- ++uni;
- if(uni > 9)uni = 0;
- write_lcd(35,table_num[uni]);
- write_com(0xce);//写完光标自动加1了,要把光标移回来
- break;
- case 2:
- ++ten;
- if(ten > 9)ten = 0;
- write_lcd(34,table_num[ten]);
- write_com(0xcd);
- break;
- case 3:
- ++hun;
- if(hun > 9)hun = 0;
- write_lcd(33,table_num[hun]);
- write_com(0xcc);
- break;
- case 4:
- ++tho;
- if(tho > 9)tho = 0;
- write_lcd(32,table_num[tho]);
- write_com(0xcb);
- break;
- case 5:
- ++tenk;
- if( tenk > 9)tenk = 0;
- write_lcd(31,table_num[tenk]);
- write_com(0xca);
- break;
- case 6:
- ++hunk;
- if( hunk > 9)hunk = 0;
- write_lcd(30,table_num[hunk]);
- write_com(0xc9);
- break;
- case 7:
- ++meg;
- if(meg > 2)meg = 0;
- write_lcd(29,table_num[meg]);
- write_com(0xc8);
- break;
- }
- while(!KEY2);
- LED2 = 1;
- }
- }
- if(!KEY3)
- {
- delay(10);
- if(!KEY3)
- {
- LED3 = 0;
- fre = 1000000*((ulong32)meg) + 100000*((ulong32)hunk) + 10000*((ulong32)tenk) + 1000*((ulong32)tho) + 100*((ulong32)hun) + 10*((ulong32)ten) + (ulong32)uni;
- write_com(0x0c);//关闭光标
- fre_r = !fre_r;//这里要写个LED灯的测试程序试试
- Wave_Fre_ALT(fre_r,fre);
- while(!KEY3);
- LED3 = 1;
- }
- }
- }
-
- void init_scr()
- {
- //在第一行显示 WAV FRE M K 1
- write_com(0x80);
- for(num = 0;num<15;num++)
- {
- write_date(table_desk[num]);
- delay(5);
- }
- //在第二行显示默认sin 00001000
- //即正弦波,频率1KHz
- write_com(0xc0);
- for(num = 0;num < 3;++num)
- {
- write_date(table_wave[num]);
- delay(5);
- }
- write_com(0xc0 + 8);
- for(num = 0;num < 7;++num)
- {
- if(3 == num)
- {
- write_date('1');
- delay(5);
- }
- else
- {
- write_date('0');
- delay(5);
- }
- }
- }
- void main()
- {
-
- init_lcd();
- init_scr();
- Wave_Generate(50000,0);
- while(1)
- {
- keyscan();
- }
- }
复制代码
|