找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1050|回复: 2
收起左侧

单片机+AD9833+LCD1602+独立按键程序

[复制链接]
ID:109865 发表于 2024-3-16 22:23 来自手机 | 显示全部楼层 |阅读模式
输出正弦波,三角波,方波,LCD显示,独立按键可调。分享给大家,应该是硬件问题吧,噪声比较大,不知如何处理。

制作出来的实物图如下:
IMG_20240316_212746.jpg

波形图:
IMG_20240316_212450.jpg

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <math.h>
  3. #define uchar8 unsigned char
  4. #define uint16 unsigned int
  5. #define ulong32 unsigned long
  6. //给正弦、三角、方波编码
  7. #define SIN 0
  8. #define TRI 1
  9. #define SQU 2
  10. //显示字库
  11. uchar8 code table_desk[]="WAV FRE M  K  1";
  12. uchar8 code table_wave[]="sintrisqu";
  13. uchar8 code table_num[]="0123456789";
  14. uint16 Config_Data[8]={0};
  15. //AD9833控制端
  16. sbit  FSYNC=P3^4;
  17. sbit  SCLK=P3^3;
  18. sbit  SDATA=P3^2;
  19. //1602液晶控制端
  20. sbit lcden = P0^7;
  21. sbit lcdrs = P0^6;
  22. //
  23. sbit KEY0 = P0^0;
  24. sbit KEY1 = P0^1;
  25. sbit KEY2 = P0^2;
  26. sbit KEY3 = P0^3;
  27. sbit KEY4 = P0^4;
  28. sbit KEY5 = P0^5;
  29. //
  30. sbit LED0 = P1^0;
  31. sbit LED1 = P1^1;
  32. sbit LED2 = P1^2;
  33. sbit LED3 = P1^3;
  34. sbit LED4 = P1^4;
  35. sbit LED5 = P1^5;

  36. bit fre_r = 0;//AD9833的两个频率字寄存器建议交替使用
  37. uchar8 wav = 0;//波形,默认正弦波
  38. ulong32 fre = 1000;//频率,默认1KHz
  39. uchar8 meg = 0 ,hunk= 0, tenk = 0,tho = 1,hun=0 ,ten = 0, uni = 0;//频率字的各个位
  40. uchar8 bit_select = 0;//频率位调节的选择标志
  41. uchar8 num; //公用循环增量


  42. //AD9833的驱动函数
  43. void  Wave_Generate(ulong32,uchar8);
  44. //1ms延时函数
  45. void delay(uint16 z)
  46. {
  47.   uint16 x,y;
  48.   for(x = z;x>0;x--)
  49.     for(y =110;y>0;y--);
  50. }

  51. //向液晶写命令,rs端置低
  52. void write_com(uchar8 com)
  53. {
  54.   delay(5);
  55.         delay(5);
  56.   P2 = com;
  57.         lcdrs = 0;
  58.   lcden = 1;
  59.   lcden = 0;
  60. }
  61. //向液晶写数据,rs端置高即可
  62. void write_date(uchar8 date)
  63. {
  64. delay(5);
  65.         delay(5);
  66.         P2  =  date;
  67.         lcdrs  = 1;
  68.   lcden = 1;
  69.   lcden = 0;
  70. }
  71. //液晶初始化
  72. void init_lcd()
  73. {
  74.   lcden = 0;
  75.   write_com(0x38);//16×2显示,5×7点阵,8位数据接口
  76.   delay(5);
  77.   write_com(0x0c);//开显示,不显示光标
  78.   delay(5);
  79.   write_com(0x06);//写一个字符之后地址指针自动加1
  80.   delay(5);
  81.   write_com(0x01);//显示清零,数据指针清零
  82. }
  83. //波形标示函数,在第二行前三个字符标明信号波形
  84. void wave(uchar8 w_wave)
  85. {
  86.   write_com(0xc0);//定位到第二行第一字符
  87.   switch(w_wave)
  88.   {
  89.     case 0:
  90.    for(num = 0;num < 3;++num)
  91.       {
  92.         write_date(table_wave[num]);
  93.         delay(5);
  94.       }
  95.    break;
  96. case 1:
  97.    for(num = 3;num < 6;++num)
  98.       {
  99.         write_date(table_wave[num]);
  100.         delay(5);
  101.       }
  102.    break;
  103. case 2:
  104.    for(num = 6;num < 9;++num)
  105.       {
  106.         write_date(table_wave[num]);
  107.         delay(5);
  108.       }
  109.    break;
  110. default:
  111.    for(num = 0;num < 3;++num)
  112.    {
  113.      write_date('?');
  114.   delay(5);
  115.    }
  116.    break;
  117.   }
  118. }
  119. //////////////////////////////////////////
  120. //向ad9833写一命令字(2Bytes)
  121. void AD9833_Send_Word(uint16 Data_In)
  122. {
  123.    uchar8 i;
  124.    uchar8 j;

  125.    SCLK=1;
  126.    FSYNC=0;
  127.    for(i=0;i<16;i++)
  128.    {
  129.      SCLK=1;
  130.      SDATA=(bit)((Data_In & 0x8000)>>15);
  131.      j=0x01;
  132.      while(j--);
  133.      SCLK=0;
  134.      Data_In=Data_In<<1;
  135.      j=0x01;
  136.      while(j--);
  137.    }
  138.    FSYNC=1;
  139.    SCLK=0;
  140. }


  141. //波形发生函数
  142. //入口参数: 频率:Freq (<=12000000)
  143. //          形状:0(正弦波),1(三角波),2(方波)
  144. //默认: Fmclk=25MHz, 0相移,方波不分频.
  145. void  Wave_Generate(ulong32 Freq,uchar8 Shape)
  146. {
  147.    ulong32 temp;
  148.    uchar8 k;
  149.    if(Freq>12000000) Freq=12000000;
  150.    switch(Shape)
  151.    {
  152.      case 0: Config_Data[0]=0x2108; // 0010 0001 0000 1000  reset(D8) =1
  153.              Config_Data[7]=0x2008; // 0010 0000 0000 1000
  154.              break;
  155.      case 1: Config_Data[0]=0x210A; //0010 0001 0000 1010
  156.              Config_Data[7]=0x200A; //0010 0000 0000 1010
  157.              break;
  158.      case 2: Config_Data[0]=0x2128; //0010 0001 0010 1000
  159.              Config_Data[7]=0x2028; //0010 0000 0010 1000
  160.              break;
  161.      default:Config_Data[0]=0x2108; //0010 0001 0000 1000
  162.              Config_Data[7]=0x2008; //0010 0000 0000 1000
  163.    }
  164.    temp=(long)(((double)Freq)*10.737418);   //temp=Freq*(0x10000000/20000000);
  165.    Config_Data[1]=temp&0x00003fff;  //0000 0000 0000 0000 0011 1111 1111 1111
  166.    Config_Data[3]=Config_Data[1];
  167.    Config_Data[2]=(temp&0x0fffc000)>>14;  //0000 1111 1111 1111 1100 0000 0000 0000
  168.    Config_Data[4]=Config_Data[2];

  169.    Config_Data[1]=Config_Data[1]|0x4000;  //0100 0000 0000 0000
  170.    Config_Data[2]=Config_Data[2]|0x4000;  //0100 0000 0000 0000
  171.    Config_Data[3]=Config_Data[3]|0x8000;  //1000 0000 0000 0000
  172.    Config_Data[4]=Config_Data[4]|0x8000;  //1000 0000 0000 0000
  173.    Config_Data[5]=0xC000;                 //1100 0000  0000 0000
  174.    Config_Data[6]=0xE000;                 //1110 0000  0000 0000

  175.    for(k=0;k<8;k++)
  176.    {
  177.      AD9833_Send_Word(Config_Data[k]);
  178.    }
  179. }


  180. void  Wave_Fre_ALT(bit fre_reg,ulong32 Freq)//寄存器
  181. {
  182.    ulong32 temp;
  183.    if(Freq>12000000) Freq=12000000;

  184.    temp=(long)(((double)Freq)*10.737418);   //temp=Freq*(0x10000000/20000000);268435456/25=10.737418,25是晶振频率268435456/30=8.947848
  185.    Config_Data[0]=Config_Data[0] & 0x3eff; // 0011 1110 1111 1111
  186.    Config_Data[1]=temp&0x00003fff;  //0000 0000 0000 0000 0011 1111 1111 1111
  187.    Config_Data[2]=(temp&0x0fffc000)>>14;  //0000 1111 1111 1111 1100 0000 0000 0000
  188.    Config_Data[5]=0xC000;                 //1100 0000 0000 0000
  189.    Config_Data[6]=0xE000;                 //1110 0000 0000 0000

  190.      if(fre_reg)
  191.      {
  192.        Config_Data[1]=Config_Data[1]|0x8000;  //1000 0000 0000 0000连续的两个频率字的16 15位为10
  193.        Config_Data[2]=Config_Data[2]|0x8000;  //1000 0000 0000 0000表示写到频率寄存器1
  194.        Config_Data[7]=Config_Data[7]|0x0800; //0000 1000 0000 0000控制字的FSELECT为1/////////^^^^^^^^^^^^^^^^^
  195.      }
  196.      else
  197.      {
  198.        Config_Data[1]=Config_Data[1]|0x4000;  //0100 0000 0000 0000
  199.        Config_Data[2]=Config_Data[2]|0x4000;  //0100 0000 0000 0000  
  200.        Config_Data[7]=Config_Data[7]&0xf7ff; //1111 0111 1111 1111//……………………………………………………………………………………………………………难道是以前的写错了?
  201.      }
  202.   AD9833_Send_Word(Config_Data[0]);
  203.   AD9833_Send_Word(Config_Data[1]);
  204.   AD9833_Send_Word(Config_Data[2]);
  205.   AD9833_Send_Word(Config_Data[5]);
  206.   AD9833_Send_Word(Config_Data[6]);
  207.   AD9833_Send_Word(Config_Data[7]);
  208. }

  209. ////////////////////////////////////////////
  210. //在1602指定位显示数据
  211. void write_lcd(uchar8 whe,uchar8 n)
  212. {
  213. if(whe < 16)//第一行
  214. {
  215.    write_com(0x80+whe-1);
  216.    write_date(n);
  217. }
  218. else       //第二行 21表示第二行第一个位置
  219. {
  220.       write_com(0x80+0x40 + whe-21);
  221.       write_date(n);
  222. }
  223. }

  224. //键盘扫描函数,根据不同的按键进行相应波形和频率的设置
  225. void keyscan()
  226. {
  227.   if(!KEY0)//切换波形
  228.   {
  229.     delay(10);
  230.     if(!KEY0)
  231.     {
  232.       ++wav;
  233.    if(wav > 2)
  234.      wav = 0;
  235.    LED0 = 0;
  236.      wave(wav);
  237.    write_com(0x0c);
  238.       Wave_Generate(fre,wav);
  239.       while(!KEY0);
  240.       LED0 = 1;
  241.     }
  242.   }

  243.   if(!KEY1)//切换频率的不同数位
  244.   {
  245.     delay(10);
  246.     if(!KEY1)
  247.     {
  248.       LED1 = 0;
  249.    write_com(0x0e);//显示光标
  250.    ++bit_select;   //选择的频率字的位移动
  251.    if(bit_select > 7)
  252.    {
  253.      bit_select = 1;
  254.    }
  255.    write_com(0xcf - bit_select ); //光标移动到相应的位上
  256.       while(!KEY1);
  257.       LED1 = 1;
  258.     }
  259.   }

  260.   if(!KEY2)//频率数字加按钮
  261.   {
  262.     delay(10);
  263.     if(!KEY2)
  264.     {
  265.       LED2 = 0;
  266.    switch(bit_select)
  267.    {
  268.      case 1:
  269.     ++uni;
  270.     if(uni > 9)uni = 0;
  271.           write_lcd(35,table_num[uni]);
  272.     write_com(0xce);//写完光标自动加1了,要把光标移回来
  273.     break;
  274.      case 2:
  275.     ++ten;
  276.     if(ten > 9)ten = 0;
  277.     write_lcd(34,table_num[ten]);
  278.     write_com(0xcd);
  279.     break;
  280.   case 3:
  281.     ++hun;
  282.     if(hun > 9)hun = 0;
  283.     write_lcd(33,table_num[hun]);
  284.     write_com(0xcc);
  285.     break;
  286.      case 4:
  287.     ++tho;
  288.     if(tho > 9)tho = 0;
  289.     write_lcd(32,table_num[tho]);
  290.     write_com(0xcb);
  291.     break;
  292.   case 5:
  293.     ++tenk;
  294.     if( tenk > 9)tenk = 0;
  295.     write_lcd(31,table_num[tenk]);
  296.     write_com(0xca);
  297.     break;
  298.   case 6:
  299.     ++hunk;
  300.     if( hunk > 9)hunk = 0;
  301.     write_lcd(30,table_num[hunk]);
  302.     write_com(0xc9);
  303.     break;
  304.   case 7:
  305.     ++meg;
  306.     if(meg > 2)meg = 0;
  307.     write_lcd(29,table_num[meg]);
  308.     write_com(0xc8);
  309.     break;
  310.    }
  311.       while(!KEY2);
  312.       LED2 = 1;
  313.     }
  314.   }
  315.   if(!KEY3)
  316.   {
  317.     delay(10);
  318.     if(!KEY3)
  319.     {
  320.       LED3 = 0;
  321.    fre = 1000000*((ulong32)meg) + 100000*((ulong32)hunk) + 10000*((ulong32)tenk) + 1000*((ulong32)tho) + 100*((ulong32)hun) + 10*((ulong32)ten) + (ulong32)uni;
  322.    write_com(0x0c);//关闭光标
  323.    fre_r = !fre_r;//这里要写个LED灯的测试程序试试
  324.    Wave_Fre_ALT(fre_r,fre);
  325.       while(!KEY3);
  326.       LED3 = 1;
  327.     }
  328.   }
  329. }



  330. void init_scr()
  331. {
  332.   //在第一行显示 WAV FRE M  K  1
  333.   write_com(0x80);
  334.   for(num = 0;num<15;num++)
  335.   {
  336.     write_date(table_desk[num]);
  337.     delay(5);
  338.   }
  339.   //在第二行显示默认sin       00001000
  340.   //即正弦波,频率1KHz
  341.   write_com(0xc0);
  342.   for(num = 0;num < 3;++num)
  343.   {
  344.     write_date(table_wave[num]);
  345.     delay(5);
  346.   }
  347.   write_com(0xc0 + 8);
  348.   for(num = 0;num < 7;++num)
  349.   {
  350.     if(3 == num)
  351. {
  352.    write_date('1');
  353.    delay(5);
  354. }
  355. else
  356. {
  357.       write_date('0');
  358.    delay(5);
  359. }
  360.   }
  361. }

  362. void main()
  363. {
  364.         
  365.   init_lcd();
  366. init_scr();
  367.   Wave_Generate(50000,0);
  368.   while(1)
  369.   {
  370.                   keyscan();
  371.   }
  372. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:109865 发表于 2024-3-17 14:34 | 显示全部楼层
Keil代码在这里

ad9833_092613.rar

40.89 KB, 下载次数: 23, 下载积分: 黑币 -5

回复

使用道具 举报

ID:402383 发表于 2024-3-25 16:43 | 显示全部楼层
LZ请把原理图发一下出来,让大家分析一下硬件。
我以前用过51+AD9833,做出来的效果不错。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表