輸出正弦波,三角波,方波,LCD顯示,獨立按鍵可調。分享給大家,應該是硬件問題吧,噪聲比較大,不知如何處理。
制作出來的實物圖如下:
IMG_20240316_212746.jpg (1.19 MB, 下載次數: 39)
下載附件
2024-3-16 22:23 上傳
波形圖:
IMG_20240316_212450.jpg (1.18 MB, 下載次數: 41)
下載附件
2024-3-16 22:23 上傳
單片機源程序如下:- #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();
- }
- }
復制代碼
|