矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 34011|回复: 74

【参赛】软硬皆施DIY信号发生器DDS上位机AD9851(50)PC端射频信号源音频发生器软件发射

[复制链接]
     
发表于 2014-9-26 10:14:40 | 显示全部楼层 |阅读模式
本帖最后由 laghi 于 2014-9-26 10:20 编辑

由于业余玩,硬件打造的比较简单,我会抽空侧重于软件的打造,并会不断直播,有什么意见看法欢迎跟帖拍砖

补充内容 (2014-9-27 20:09):
接下来是想说明他能给我们做什么呢?
首先,它是一台频率精准的音频信号发生器,频率步进值0.029Hz范围宽,0--20000(45000000)
其次,它是收音机的信号发生器,中波短波通吃。
再次,它是一台宽频中频扫频仪。....
     
 楼主| 发表于 2014-9-26 11:26:20 | 显示全部楼层
参考电路
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 11:44:02 | 显示全部楼层
laghi 发表于 2014-9-26 11:38
所用到的全部硬件在这里:

单片机用的是STC15F104E的8脚的

STC的8脚单片机有直插和SOP两种形式的封装,其中有6个IO口,剩下2个是VCC和GND ,不需要带晶振内部自带有时钟发生电路,在此要说明这种型号的单片机有专用的烧录软件,在宏晶官网都有下载。这6个IO口实际上是我们普通单片机上的P3口,实际编程时也是使用P3.X来实现IO口操作。唯一的不同就是没有硬件的串口,需要用到定时器来模拟(这点不好),但是下载电路和STC的串口下载电路时一样的。不做修改。这个有点费解?下载时用到的是串口形式的下载电路,硬件上使用时却没有串口。杯具啊!  关于IO口的复用功能,除P3.1没有复用功能外,其他引脚均有复用功能。分别是5个外部中断,3个时钟输出,一个复位输入 。芯片默认是不需要复位电路的,上电自复位的。可以通过软件来选择引脚作为复位脚。同时在烧录软件上可以选择低压复位。手册上说的是8种。软件上只显示了6种-不解???让人惊喜的是烧录软件上提供硬件开启看门狗功能。还可以选择看门狗分频级数。还是蛮方便的嘛。。。程序又少了几句话 。最后要说一点的是该种单片机以E结尾的都有EEPROM喔。例如我买的STC15F104E。

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 14:02:16 | 显示全部楼层
这个单片机有6个IO口,其中5,6脚(P3^0和P3^1口)用于和电脑通信,该单片机没有硬件串口,所以只能软件模拟。
用这两个脚的另一个原因是它们还是单片机下载程序的接口,这样方便日后的升级。
RXB = P3^0; //定义串口的2个I/O管脚
TXB = P3^1;发送口
//和AD9850/51的通信接口
sbit ad9850_w_clk    =P3^2;//接ad9850的w_clk脚/PIN7
sbit ad9850_fq_up    =P3^3;//接ad9850的fq_up脚/PIN8
sbit ad9850_bit_data =P3^4;//接ad9850的D7脚/PIN25
sbit ad9850_rest     =P3^5;//接ad9850的rest脚/PIN12,
为什么这样安排,这与我焊接的电路板有关,坛友可以自己观察
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 14:09:22 | 显示全部楼层
接下来是和电脑的连接,我的笔记本没有串口,我用的是U口转串口的那个模块,淘宝只卖2-3元,自己可以看看。芯片是PL2303,是需要装驱动的,在这里就不提供了,买时他给带的
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 15:43:05 | 显示全部楼层
好了,该上单片机的软件了,kc环境下c语言编写
  1. #include <REG51.H>
  2. #include <intrins.h>
  3. //#define BAUD  0xFF40  //38400bps @ 22.1184MHz
  4. #define BAUD  0xFD00// STC15F104的串行波特率9600bps @ 22.1184MHz时钟
  5. sfr AUXR = 0x8E;//定时器模式寄存器
  6. sbit RXB = P3^0; //定义串口的2个I/O管脚
  7. sbit TXB = P3^1;
  8. //和AD9850/51的通信接口
  9. sbit ad9850_w_clk    =P3^2;//接ad9850的w_clk脚/PIN7
  10. sbit ad9850_fq_up    =P3^3;//接ad9850的fq_up脚/PIN8
  11. sbit ad9850_bit_data =P3^4;//接ad9850的D7脚/PIN25
  12. sbit ad9850_rest     =P3^5;//接ad9850的rest脚/PIN12

  13. //-----STC15F104的EEprom用于掉电记忆和脱离电脑工作-------
  14. sfr IAP_DATA    =   0xC2;//IAP数据寄存器
  15. sfr IAP_ADDRH   =   0xC3;//IAP地址寄存器高字节
  16. sfr IAP_ADDRL   =   0xC4;//IAP地址寄存器低字节
  17. sfr IAP_CMD     =   0xC5;//IAP命令寄存器
  18. sfr IAP_TRIG    =   0xC6;//IAP命令触发寄存器
  19. sfr IAP_CONTR   =   0xC7;//IAP控制寄存器
  20.           //写入首地址
  21. #define IAP_ADDRESS 0x0400
  22. #define CMD_IDLE    0//空闲模式
  23. #define CMD_READ    1//IAP字节读命令
  24. #define CMD_PROGRAM 2//IAP字节编程命令
  25. #define CMD_ERASE   3//IAP扇区擦除命令
  26. #define ENABLE_IAP 0x81//if SYSCLK<24MHz
  27. //-----------------------------------------------


  28. unsigned char TBUF;//RBUF;
  29. unsigned char TDAT,RDAT;
  30. unsigned char TCNT,RCNT;
  31. unsigned char TBIT,RBIT;
  32. bit TING,RING;
  33. bit TEND,REND;
  34. unsigned char TmpF[6]={0x0f,0x00,0x01,0x00,0x00,0x00};
  35. unsigned char W[5];
  36. unsigned char i,j;
  37. //芯片控制函数
  38. void ad_reset();
  39. void ad_write();
  40. void answer();
  41. //---------------EEprom------------------
  42. //void Delay(unsigned char n);
  43. void IapIdle();
  44. unsigned char IapReadByte(unsigned int addr);
  45. void IapWriteByte(unsigned int addr, unsigned char dat);
  46. void IapEraseSector(unsigned int addr);
  47. //-----------------------------------------------
  48. main ()
  49. {
  50.          P3=0x03;//初始化管脚口
  51.     TMOD = 0x00;
  52.     AUXR = 0x80;   //timer0 工作在1T模式
  53.     TL0 = BAUD;
  54.     TH0 = BAUD>>8;
  55.     TR0 = 1;
  56.     ET0 = 1;
  57.     PT0 = 1;
  58.     EA = 1;
  59. //初始化串口设置
  60.     TING = 0;
  61.     RING = 0;
  62.     TEND = 1;
  63.     REND = 0;
  64.     TCNT = 0;
  65.     RCNT = 0;
  66.     j=0;
  67.          ad_reset();//AD985X芯片复位准备
  68. //         ad_write();//ce shi
  69.          for (i=0;i<5;i++) W[i]=IapReadByte(IAP_ADDRESS+i);
  70.     for (i=0; i<5; i++) TmpF[i] = W[i];
  71.          TmpF[5]=0x83;
  72. //使芯片开始工作
  73. while( 1 )
  74.    {
  75.     //while (!REND);

  76.         switch (TmpF[5])
  77.         {
  78.         case 0x80://读取
  79.                      //W[0]=0x01;
  80.                          TmpF[5]=0x01;
  81.                      answer();//向Pc发送数据回答
  82.                          //j=0;
  83.         break;
  84.         case 0x81://联机
  85.                      //W[0]=0x02;
  86.                          TmpF[5]=0x02;
  87.                      answer();
  88.                          //j=0;
  89.         break;
  90.         case 0x82://复位
  91.                          //W[0]=0x03;
  92.                          TmpF[5]=0x03;
  93.                ad_reset();
  94.                          answer();
  95.                          //j=0;
  96.         break;
  97.         case 0x83://置频
  98.                 //W[0]=0x04;
  99.                           TmpF[5]=0x04;
  100.                 ad_reset();//AD985X芯片复位准备
  101.                      ad_write();
  102.                           answer();
  103.         break;
  104.         case 0x84://写入
  105.                 //W[0]=0x05;
  106.                           TmpF[5]=0x05;
  107.                           IapEraseSector(IAP_ADDRESS);//扇区擦除
  108.                           for (i=0;i<5;i++)
  109.                                 {
  110.                                 IapWriteByte(IAP_ADDRESS+i, W[i]);
  111.                                 }
  112.                           answer();
  113.         //写ISP/IAP/EEPROM数据
  114.         break;
  115.         case 0x85://扫频
  116.                 //W[0]=0x06;
  117.                           TmpF[5]=0x06;
  118.        
  119.         break;
  120.         }
  121.    if(j>=6)
  122.                         {
  123.                         j=0 ;
  124.                         for (i=0; i<5; i++) W[i]=TmpF[i];
  125.                         }
  126.    }
  127. }

  128. //发送数据到串口
  129. void answer()
  130. {
  131.     for (i=0; i<6; i++)//发6个字节
  132.     {
  133.     while (!TEND);
  134.     TEND = 0;
  135.     TBUF = TmpF[i];
  136.     TING = 1;//发送数据到串口
  137.     }
  138. }
  139. //定时器模拟串口
  140. void tm0() interrupt 1 using 1
  141. {
  142.     if (RING)
  143.     {
  144.         if (--RCNT == 0)
  145.         {
  146.             RCNT = 3;      //复位发送波特率计数器
  147.             if (--RBIT == 0)
  148.             {
  149.                 TmpF[j] = RDAT;//保存数据到RBUF
  150.                 RING = 0;   //停止接收
  151.                 REND = 1;   //接收完成标记
  152.                                          j++ ;
  153.             }
  154.             else
  155.             {
  156.                 RDAT >>= 1;
  157.                 if (RXB) RDAT |= 0x80;
  158.             }
  159.         }
  160.     }
  161.     else if (!RXB)
  162.     {//检测接收脚电平
  163.         RING = 1; //set start receive flag
  164.         RCNT = 4; //初始化波特率计数器
  165.         RBIT = 9; //initial receive bit number (8 data bits + 1 stop bit)
  166.     }
  167.     if (--TCNT == 0)
  168.     {
  169.         TCNT = 3;
  170.         if (TING)
  171.         {
  172.             if (TBIT == 0)
  173.             {
  174.                 TXB = 0;
  175.                 TDAT = TBUF;
  176.                 TBIT = 9;
  177.             }
  178.             else
  179.             {
  180.                 TDAT >>= 1;
  181.                 if (--TBIT == 0)
  182.                 {
  183.                     TXB = 1;
  184.                     TING = 0;
  185.                     TEND = 1;  
  186.                 }
  187.                 else
  188.                 {
  189.                     TXB = CY;
  190.                 }
  191.             }
  192.         }
  193.     }
  194. }


  195. //***************************************************//
  196. //              ad9850复位(串行模式)                 //
  197. //---------------------------------------------------//
  198. void ad_reset()
  199. {
  200. ad9850_w_clk=0;
  201. ad9850_fq_up=0;
  202. //rest信号
  203. ad9850_rest=0;
  204. ad9850_rest=1;
  205. ad9850_rest=0;
  206. //w_clk信号
  207. ad9850_w_clk=0;
  208. ad9850_w_clk=1;
  209. ad9850_w_clk=0;
  210. //fq_up信号
  211. ad9850_fq_up=0;
  212. ad9850_fq_up=1;
  213. ad9850_fq_up=0;
  214. }
  215. //***************************************************//
  216. //          向ad9850中写命令与数据(串行)             //
  217. //---------------------------------------------------//
  218. void ad_write()
  219. {
  220. unsigned char ji;
  221. for(ji=0;ji<5;ji++)
  222.   {
  223.                 for(i=0;i<8;i++)//写w数据
  224.                 {
  225.                 ad9850_bit_data=(W[ji]>>i)&0x01;
  226.                 ad9850_w_clk=1;
  227.                 ad9850_w_clk=0;
  228.                 }
  229.   }
  230. ad9850_fq_up=1;//移入始能
  231. ad9850_fq_up=0;
  232. }//完成

  233. /*----------------------------
  234. EEprom 软件延时
  235. ----------------------------*/
  236. /*
  237. void Delay(unsigned char n)
  238. {
  239.     unsigned int x;

  240.     while (n--)
  241.     {
  242.         x = 0;
  243.         while (++x);
  244.     }
  245. }
  246. */
  247. /*----------------------------
  248. 关闭IAP
  249. ----------------------------*/
  250. void IapIdle()
  251. {
  252.     IAP_CONTR = 0;   //关闭IAP功能
  253.     IAP_CMD = 0;     //清除命令寄存器
  254.     IAP_TRIG = 0;    //清除触发寄存器
  255.     IAP_ADDRH = 0x80;//将地址设置到非IAP区域
  256.     IAP_ADDRL = 0;
  257. }
  258. /*----------------------------
  259. 从ISP/IAP/EEPROM区域读取一字节
  260. ----------------------------*/
  261. unsigned char IapReadByte(unsigned int addr)
  262. {
  263.     unsigned char dat;              //数据缓冲区

  264.     IAP_CONTR = ENABLE_IAP;//使能IAP
  265.     IAP_CMD = CMD_READ;    //设置IAP命令
  266.     IAP_ADDRL = addr;      //设置IAP低地址
  267.     IAP_ADDRH = addr >> 8; //设置IAP高地址
  268.     IAP_TRIG = 0x5a;       //写触发命令(0x5a)
  269.     IAP_TRIG = 0xa5;       //写触发命令(0xa5)
  270.     _nop_();               //等待ISP/IAP/EEPROM操作完成
  271.     dat = IAP_DATA;        //读ISP/IAP/EEPROM数据
  272.     IapIdle();             //关闭IAP功能

  273.     return dat;            //返回
  274. }
  275. /*----------------------------
  276. 写一字节数据到ISP/IAP/EEPROM区域
  277. ----------------------------*/
  278. void IapWriteByte(unsigned int addr, unsigned char dat)
  279. {
  280.     IAP_CONTR = ENABLE_IAP;//使能IAP
  281.     IAP_CMD = CMD_PROGRAM; //设置IAP命令
  282.     IAP_ADDRL = addr;      //设置IAP低地址
  283.     IAP_ADDRH = addr >> 8; //设置IAP高地址
  284.     IAP_DATA = dat;        //写ISP/IAP/EEPROM数据
  285.     IAP_TRIG = 0x5a;       //写触发命令(0x5a)
  286.     IAP_TRIG = 0xa5;       //写触发命令(0xa5)
  287.     _nop_();               //等待ISP/IAP/EEPROM操作完成
  288.     IapIdle();
  289. }
  290. /*----------------------------
  291. 扇区擦除
  292. ----------------------------*/
  293. void IapEraseSector(unsigned int addr)
  294. {
  295.     IAP_CONTR = ENABLE_IAP;//使能IAP
  296.     IAP_CMD = CMD_ERASE;   //设置IAP命令
  297.     IAP_ADDRL = addr;      //设置IAP低地址
  298.     IAP_ADDRH = addr >> 8; //设置IAP高地址
  299.     IAP_TRIG = 0x5a;       //写触发命令(0x5a)
  300.     IAP_TRIG = 0xa5;       //写触发命令(0xa5)
  301.     _nop_();               //等待ISP/IAP/EEPROM操作完成
  302.     IapIdle();
  303. }
复制代码
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 16:10:56 | 显示全部楼层
接着把电脑端软件发上来供大家拍砖,源代码和功能,原理后面会公布解释的
DDS控制面板.rar (93.6 KB, 下载次数: 549)

补充内容 (2014-9-29 16:03):
大家可以先下这个软件去测试,记住是com1口连接的
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-27 11:15:48 | 显示全部楼层
shadow 发表于 2014-9-26 17:31
STC15F104E外部中断触发有bug,软件补丁会影响其他中断的使用,所以价值不大,据说B版纠正,要买STC15F104W ...

感谢这位朋友的建议,这个问题在起初我也考虑过,但从stc的官方pdf看,说是外部偶尔异常,再加之就没有用外部中断(代码中可以看出),想让单片机只是实现传递指令的功能,而且A版的价格比B版 的便宜,本着不浪费的思想限制,最后选了A版。最终的目的是吧所有的编程问题移植到电脑上来,因为电脑的功能强大,配置高,程序易更改,可操作性强,运算速度快,界面友好且可以随意更改
QQ图片20140927110146.jpg
曾经也考虑把单片机直接嵌入那个模块,最后还是放弃
回复 支持 反对

使用道具 举报

     
发表于 2014-9-27 20:59:23 | 显示全部楼层
内容我百度的:AD9851是ADI公司采用先进的DDS技术推出的高集成度DDS频率合成器,它内部包括可编程DDS系统、高性能DAC及高速比较器,能实现全数字编程控制的频率合成和时钟发生。AD9851接口功能控制简单,可以用8位并行口或串行口直接输入频率、相位等控制数据。32位频率控制字,在180MHz时钟下,输出频率分辨率达0.0372Hz。先进的CMOS工艺使AD9851不仅性能指标一流,而且功耗低,在3.3V供电时,功耗仅为155mW。

具体还能干啥我想不起来,淘宝上资料说在20兆赫后杂波很多记得有一期无线电上有介绍,用两个这个东西,倍频混频可以得到纯净的正玄波,还可以做pLL的基准。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-29 15:51:25 | 显示全部楼层
et23v 发表于 2014-9-29 14:26
那是检测机器的好工具,输入接USB接口?是你DIY的板上输出终端信号?

是USB接口的(那个用了一个小转换板PL2303,图中可以看出,价格2-3元吧)。输出信号在50欧姆电阻上有0.5V左右,频率高电压下降,还有两个方波输出口,输出接口4个,2个正弦波的
QQ图片20140929155035.jpg
QQ图片20140929154857.jpg
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 10:23:29 | 显示全部楼层
先上设计的软件布局,由于Windows原窗体太普遍,所以这次要换外形
未命名.JPG
这样看着不新颖,所以不采用
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 10:27:24 | 显示全部楼层
laghi 发表于 2014-9-26 10:23
先上设计的软件布局,由于Windows原窗体太普遍,所以这次要换外形

这样看着不新颖,所以不采用

以前参赛我看大家都侧重于硬件的DIY,这次我的侧重于软件(由于上班忙,硬件打造不方便,所以就抽空搞软件上的DIY),这个帖子希望大家能够接受
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 10:30:49 | 显示全部楼层
电脑端软件是用VB语言编写的,先上界面说明图,我会陆续公布源代码的
复件 jie.JPG
回复 支持 反对

使用道具 举报

发表于 2014-9-26 10:48:22 | 显示全部楼层
本帖最后由 鬼脚七 于 2014-9-26 10:49 编辑

上位机软件通过串口下发数据?硬件平台做出来了吗?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 11:06:52 | 显示全部楼层
鬼脚七 发表于 2014-9-26 10:48
上位机软件通过串口下发数据?硬件平台做出来了吗?

是的,是串口控制的,接下来该展示硬件了,谢谢关注
QQ图片20140926110523.jpg
我给孩子剪的五角星,看下,

补充内容 (2014-9-29 16:04):
谢谢关注,软件硬件平台都出来了,接下来是不断完善
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 11:09:54 | 显示全部楼层
硬件是这个
QQ图片20140610085400.jpg
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 11:20:58 | 显示全部楼层
硬件的主角是它,以前在淘宝20几元买的,现在好像涨价了,真是搞不懂
QQ图片20140926110523.jpg
它的连线图可以借鉴这个帖子http://www.crystalradio.cn/thread-247107-1-1.html
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2014-9-26 11:38:24 | 显示全部楼层
所用到的全部硬件在这里:
问1111问.jpg
单片机用的是STC15F104E的8脚的
问问.jpg
电路焊接在洞洞板上
11问问.jpg
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2024-4-25 06:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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