找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 22942|回复: 34
收起左侧

基于51单片机函数信号发生器完整论文下载 带源码 原理图

  [复制链接]
ID:195456 发表于 2017-5-3 17:15 | 显示全部楼层 |阅读模式
这个51单片机函数信号发生器论文,大家可以看看

摘要
本文以STC89C51单片机为核心设计了一个低频函数信号发生器。信号发生器采用数字波形合成技术,通过硬件电路和软件程序相结合,可输出自定义波形,如正弦波、方波、三角波、三角波、梯形波及其他任意波形,波形的频率和幅度在一定范围内可任意改变。波形和频率的改变通过软件控制,幅度的改变通过硬件实现。介绍了波形的生成原理、硬件电路和软件部分的设计原理。本系统可以产生最高频率798.6HZ的波形。该信号发生器具有体积小、价格低、性能稳定、功能齐全的优点。


1设计选题及任务
设计题目:基于单片机的信号发生器的设计与实现
任务与要求:
设计一个由单片机控制的信号发生器。运用单片机系统控制产生多种波形,这些波形包括方波、三角波、锯齿波、正弦波等。信号发生器所产生的波形的频率、幅度均可调节。并可通过软件任意改变信号的波形。
基本要求:
1.              产生三种以上波形。如正弦波、三角波、矩形波等。
2.最大频率不低于 500Hz。并且频率可按一定规律调节,如周期按1T,2T,3T,4T或1T,2T,4T,8T变化。
3.幅度可调,峰峰值在0——5V之间变化。
扩展要求:产生更多的频率和波形。


2系统概述
2.1方案论证和比较
211总体方案:
方案一:采用模拟电路搭建函数信号发生器,它可以同时产生方波、三角波、正弦波。但是这种模块产生的不能产生任意的波形(例如梯形波),并且频率调节很不方便。
方案二:采用锁相式频率合成器,利用锁相环,将压控振荡器(VCO)的输出频率锁定在所需频率上,该方案性能良好,但难以达到输出频率覆盖系数的要求,且电路复杂。
方案三:使用集成信号发生器发生芯片,例如AD9854,它可以生成最高几十MHZ的波形。但是该方案也不能产生任意波形(例如梯形波),并且价格昂贵。
方案四:采用AT89C51单片机和DAC0832数模转换器生成波形,加上一个低通滤波器,生成的波形比较纯净。它的特点是可产生任意波形,频率容易调节,频率能达到设计的500HZ以上。性能高,在低频范围内稳定性好、操作方便、体积小、耗电少。
经比较,方案四既可满足课程设计的基本要求又能充分发挥其优势,电路简单,易控制,性价比高,所以采用该方案.

212改变幅度方案:
方案一:可以将送给DA的数字量乘以一个系数,这样就可以改变DA输出电流的幅度,从而改变输出电压;但是这样做有很严重的问题,单片机在做乘法运算时需要很长的时间,这样的话输出波形的频率就会很低,达不到至少500HZ的要求;
并且该方案的输出电压做不到连续可调,当DA的输入数字量比较小时,输出的波形失真就会比较严重。
方案二:将输出电压通过一个运算放大器的放大。这样还有个优点是幅度连续可调。
经比较,方案二既可满足课程设计的基本要求,并且电路也挺简单。



2.2工作原理
数字信号可以通过数/模转换器转换成模拟信号,因此可通过产生数字信号再转换成模拟信号的方法来获得所需要的波形。89C51单片机本身就是一个完整的微型计算机,具有组成微型计算机的各部分部件:中央处理器CPU、随机存取存储器RAM、只读存储器ROM、I/O接口电路、定时器/计数器以及串行通讯接口等,只要将89C51再配置键盘及、数模转换及波形输出、放大电路等部分,即可构成所需的波形发生器,其信号发生器构成系统框图如下图所示。

1.001.jpg
系统框图

89C51是整个波形发生器的核心部分,通过程序的编写和执行,产生各种各样的信号,并从键盘接收数据,进行各种功能的转换和信号幅度的调节。当数字信号电路到达转换电路,将其转换成模拟信号也就是所需要的输出波形。
波形ROM表是将信号一个周期等间距地分离成64个点,储存在单片机得RON内。具体ROM表是通过MATLAB生成的,例如正弦表,MATLAB生成的程序如下:
x=0:2*pi/64:2*pi; y=round(sin(x)*127)+128



3单元电路设计与分析
3.1.1主控电路
设计中主要采用STC89C51型单片机,它具有如下优点:(1)拥有完善的外部扩展总线,通过这些总线可方便地扩展外围单元、外围接口等。(2)该单片机内部拥有4K字节的FLASH ROM程序存储器空间和256字节的RAM数据存储空间,完全可以满足程序的要求。由于该芯片可电擦写,故可重复使用。如果更改程序内容,可将芯片拿下重新烧写。(3)该单片机与工业标准的MCS-51型机的指令集和输出引脚兼容。
中断系统是使处理器具有对外界异步事件的处理能力而设置的。当中央处理器CPU正在
处理某件事的时候外界发生了紧急事件,要求CPU暂停当前的工作,转而去处理这个紧
急事件。
在波形发生器中,用两个开光直接与外部中断0和外部中断1的管脚相连,其中S1开光用来改变波形,S2开光用来改变频率。在程序主函数中,我们写了个死循环一直输出一个默认的波形,当S1或S2按下又抬起时,程序会暂时跳出死循环,进入中断处理程序,从而对波形和频率进行改变。
时钟电路。由于频率较大时,三角波、正弦波、方波等波中每一点延时时间为几微秒,故延时时间还要加上指令时间即可得到指定频率的波形,该电路用11.0592MHz晶振。
1.002.jpg
主控电路图

3.1.2 数/模转换电路
由于单片机产生的是数字信号,要想得到所需要的波形,就要把数字信号转换成模拟信号,所以该文选用价格低廉、接口简单、转换控制容易并具有8位分辨率的数模转换器DAC0832。DAC0832主要由8位输入寄存器、8位DAC寄存器、8位D/A转换器以及输入控制电路四部分组成。但实际上,DAC0832输出的电量也不是真正能连续可调,而是以其绝对分辨率为单位增减,是准模拟量的输出。DAC0832是电流型输出,在应用时外接运放使之成为电压型输出。
根据对DAC0832的数据锁存器和DAC寄存器的不同的控制方式,DAC0832有三种工作方式:直通方式、单缓冲方式和双缓冲方式。本设计选用直通方式。
DAC0832的数据口和单片机的P0口相连。
CSDA:片选信号输入线(选通数据锁存器),低电平有效;
WR:数据锁存器写选通输入线,负脉冲(脉宽应大于500ns)有效。由ILE、CS、WR1的逻辑组合产生LE1,当LE1为高电平时,数据锁存器状态随输入数据线变换,LE1的负跳变时将输入数据锁存;
1.003.jpg
数模转换电路

3.1.3运算放大电路和低通滤波电路
1.004.jpg
LM324的5管脚与DAC0832的(IOUT2)12管脚相连,LM324的6管脚与DAC0832的(IOUT1)11管脚相连,LM324的7管脚与DAC0832的REF(9)管脚相连.
第一级运算放大器的作用是将DAC0832输出的电流信号转化为电压信号V1,第二级运算放大器的作用是将V1通过反向放大电路-(R2/R1)倍。
题目要求输出的电压在0-5V可调,而V1的电压大约是5V,所以R1选择5K的电阻,R2选择10K的电位器,这样最大的输出电压为5*(10/2)=10,最小电压为0,可以实现题目要求的0-5V。
在第二个运算放大器的输出端连了一个低通滤波器。如果不加低通滤波器,也能够生成波形,但是产生的信号中毛刺很多,加一个低通滤波器不仅起到的滤波的作用,还起到了平滑的作用。低通滤波器的截止频率F=1/(2*pi*R3*C6),这里我们选择R3 为100欧姆电阻,C6为104电容,截止频率F=16KHZ。实验表明,此时的输出波形效果不错。

3.1.4串口通信电路
通用异步收发器(UART)是一种串行接口,一般微处理器中都包含这种外设接口。异步串行接口提供了一种简单的途径,使两个器件无需共享同一个时钟信号就能进行通信。如果再加入一个合适的电平转换器MAX232,串口就能能用在RS232和RS485等网络中实现通信,或者与计算机的COM端口连接。串口只需两根信号线(RX和TX)即可实现,而且只要两端器件都采用同样的位格式和波特率,那么它们无需其它任何对方的信息就可以成功传输数据。
1.005.jpg
                                                        串口通信电路图

3.2系统软件设计
软件设计上,根据功能分了几个模块编程。模块主要有:主程序模块、外部中断0模块,外部中断1模块。
主程序:
              主程序先是进行一些初始化的工作,然后根据波形标志a,b,c,d,e的值进入相应的while 循环。这样写的好处是输出的波形频率可以790多HZ。在while循环中,单片机根据地址标志位不停低查表,然后把查得的值赋给DAC0832的数据口,然后地址标志位加一,并判断地址标志位是否等于64,如果是就置0再往下执行,如果不是直接往下执行。然后根据频率标志位进行相应的延时。
1.006.jpg
主程序流程图

中断服务程序:
本程序中两个外部中断分别起到了控制波形和频率的作用。在程序中还加入了消抖部分。
1.007.jpg

4安装调试及测量数据分析
4.1调试过程;
1. 不通电,用万用表根据电路图仔细检查各线路连接是否正常。
2. 首先是调试单片机部分,DA和运算放大器芯片不接。用STC_ISP_V483软件通过串口下程序。看是否可以正常下程序。
3.当可以正常下程序时,给51单片机下一个让所有I/0口一会儿输入0,延时,再输出1,以此类推。用万用表测量各I/O口得电压是不是一会儿高,一会儿低。
4.安上DA和运算放大器芯片,给单片机下一个输出正弦波的测试程序,通过示波器看输出是否正常。
5. 给单片机下一个完整的程序,分别按下S1,看波形是否改变。按下S2,看频率是否改变。



4.2频率的测量数据:
                                                                                                                                                                                                                             单位:HZ
周期
T
2T
3T
4T
5T
6T
7T
8T
理论值
798.6
399.3
266.2
199.7
159.7
133.1
114.1
99.8
实际值
798.6
399.6
266.5
199.9
159.9
133.3
114.2
99.9


4.3出现的问题与解决的方法:
1.
调试单片机的串口时,发现不能正常的下程序。我想可能是单片机坏了借了一块学习板测试了一下单片机芯片,发现可以正常下载。这说明很可能是MAX232的电路出了问题。我仔细查看了电路图,又上网查了下其他的MAX232的电路图,发现我的电路图和别人的不一样。我是按照郭天翔的那本《新概念51单片机C语言教程 入门、提高、开发、拓展全》第130页的串口电路画的图,电路图中MAX232的TIOU1接串口的第3脚。而其他书上有些电路图却是MAX232的TIOU1接到了串口的第2脚。于是我将MAX232的TIOU1接串口的第2脚,再下程序,终于可以正常下载了。
2.刚开始写的测试程序输出的波形失真很大。我想可能是波形的ROM表里的数据值过小,导致DA输出的误差很大。因而卧将波形的ROM表里的数据值调大,在测试时发现波形变得好多了。
3.
调试波形的时候我发现矩形波的失真比较大。我想到可能是低通滤波器的截止频率太低了,因而我将RC低通滤波器的电阻由1K换成了100欧姆,效果好了很多。

4.4系统仿真波形:
矩形波
1.008.jpg
锯齿波
1.009.jpg
正弦波
1.010.jpg

4.5效果分析:
由4.2的频率理论值与实际值,可知频率在T,2T,3T,4T,5T,6T,7T,8T上频率误差很小。
最终的波形输出效果也很不错。

4.6测量仪器
示波器
直流稳压电源
万用表

5结束语
基于单片机的信号发生器设计,这个信号发生器的设计中涉及到一个典型的控制过程。通过单片机控制一个模数转换器DAC0832产生所需要的电流,然后使用运算放大器LM324可以将其电流输出线性地转换成电压输出,再将电压经过运算放大器的放大,可以得到足够幅度的信号。通过程序的控制,可以产生一系列有规律的波形。这样一个信号发生装置在控制领域有相当广泛的应用范围。
最终做出来的信号发生器满足了题目中的所有要求:
1.产生五种波形。正弦波、三角波、矩形波、梯形波,锯齿波。
2.最大频率为798.6HZ。并且频率可按按1T,2T,3T,4T,5T,6T,7T,8T变化。
3.幅度可调,峰峰值在0——5V之间变化。
当然还是存在不足的地方,比如不能实现频率的按一个小的步进调整。并且当频率太小时矩形波会有些失真。
信号发生器可以生成更多的波形,只需要再加些波形表即可。
在这里得感谢学校为我们提供个这样一个实践的机会,当然还得感谢实验室指导老师们的细心指导。


参考文献:
[1] 郭天翔.新概念51单片机C语言教程 入门、提高、开发、拓展全.北京.电子工业出版社 2009.1
[2] 童诗白.模拟电路技术基础[M].北京:高等教育出版社,2000.171~202.



附录
1:总电路图

1.011.jpg


附录2:源程序

  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. sbit csda=P2^2;
  5. sbit wr=P2^1;
  6. sbit s1=P3^2;
  7. sbit s2=P3^3;
  8. uchar k=0,p=0,delay=0;
  9. uchar bxxz=0;pinglv=0;
  10. uchar a=1,b=0,c=0,d=0,e=0;

  11. uchar code sin[64]={
  12. 135,145,158,167,176,188,199,209,218,226,234,240,245,249,252,254,254,253,251,247,243,237,230,222,213,204,193,182,170,158,
  13. 146,133,121,108,96,84,72,61,50,41,32,24,17,11,7,3,1,0,0,2,5,9,14,20,28,36,45,55,66,78,90,102,114,128
  14. };
  15. uchar code juxing[64]={
  16. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  17. 255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  18. };
  19. uchar code juchi[64]={
  20. 0,4,8,12,16,20,24,28,32,36,40,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,130,134,138,142,
  21. 146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,215,219,223,227,231,235,239,243,247,251,255
  22. };
  23. uchar code tixing[64]={
  24. 0,13,26,39,52,65,78,91,104,117,130,143,156,169,182,195,208,221,234,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,
  25. 247,247,247,247,247,247,247,242,229,216,203,190,177,164,151,138,125,112,99,86,73,60,47,34,21,8
  26. };
  27. uchar code sanjiao[64]={
  28. 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,
  29. 248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,0
  30. };
  31. void delay1()
  32. {
  33.               int a,b;
  34.               for(a=1;a>0;a--)
  35.                             for(b=122;b>0;b--);
  36. }
  37. void int0() interrupt 0
  38. {            
  39.               EX0=0;
  40.               delay1();
  41.               if(s1==0){                           
  42.               bxxz++;
  43.               if(bxxz==5)
  44.                             bxxz=0;
  45.               switch(bxxz)
  46.                             {
  47.                             case 0 :
  48.                                           {a=1,b=0,c=0,d=0,e=0;}
  49.                                           break;
  50.                             case 1 :
  51.                                           {a=0,b=1,c=0,d=0,e=0;}
  52.                                           break;
  53.                             case 2 :
  54.                                           {a=1,b=0,c=1,d=0,e=0;}
  55.                                           break;            
  56.                             case 3 :
  57.                                           {a=0,b=0,c=0,d=1,e=0;}
  58.                                           break;
  59.                             case 4 :
  60.                                           {a=0,b=0,c=0,d=0,e=1;}
  61.                                           break;
  62.                             }
  63.               delay1();
  64.               while(!s1);            
  65.                             }
  66.               while(!s1);
  67.               EX0=1;
  68. }
  69. void int1() interrupt 2
  70. {
  71.               EX1=0;            
  72.               delay1();
  73.               if(s2==0){                           
  74.               p++;
  75.               if(p==8)
  76.                                p=0;
  77.               switch(p)
  78.                             {
  79.                             case 1 :
  80.                                           pinglv=3;
  81.                                           break;
  82.                             case 2 :
  83.                                           pinglv=6;
  84.                                           break;            
  85.                             case 3 :
  86.                                           pinglv=9;
  87.                                           break;
  88.                             case 4 :
  89.                                           pinglv=12;
  90.                                           break;
  91.                             case 5 :
  92.                                           pinglv=15;
  93.                                           break;
  94.                             case 6 :
  95.                                           pinglv=18;
  96.                                           break;
  97.                             case 7 :
  98.                                           pinglv=21;
  99.                                           break;                                                      
  100.                             default :
  101.                                           pinglv=0;
  102.                                           break;
  103.                             }
  104.                             delay1();
  105.                             while(!s2);            
  106.                             }
  107.               while(!s2);            
  108.               EX1=1;
  109. }
  110. void main()
  111. {
  112.               csda=0;
  113.               wr=0;
  114.               EA=1;
  115.               IT0=1;
  116.               EX0=1;
  117.               IT1=1;
  118.               EX1=1;
  119.               while(1)
  120.               {
  121.                             while(a)
  122.                             {
  123.                             delay=pinglv;
  124.                             P0=sin[k];
  125.                             k++;
  126.                             if(k==64)
  127.                                           k=0;
  128.                             while(delay)           
  129.                                               delay--;
  130.                             }
  131.                             while(b)
  132.                             {
  133.                             delay=pinglv;
  134.                             P0=juxing[k];
  135.                             k++;
  136.                             if(k==64)
  137.                                           k=0;
  138.                             while(delay)         
  139.                                               delay--;
  140.                             }
  141.                             while(c)
  142.                             {
  143.                             delay=pinglv;
  144.                             P0=juchi[k];
  145.                             k++;
  146.                             if(k==64)
  147.                                           k=0;
  148.                             while(delay)           
  149.                                               delay--;
  150.                             }
  151.                             while(d)
  152.                             {
  153.                             delay=pinglv;
  154.                             P0=tixing[k];
  155.                             k++;
  156.                             if(k==64)
  157.                                           k=0;
  158.                             while(delay)           
  159.                                               delay--;
  160.                             }


  161. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

完整论文下载:
基于51单片机的信号发生器-完整电路、程序.doc (384 KB, 下载次数: 527)

评分

参与人数 8黑币 +46 收起 理由
13340255415 + 5 很给力!
客户开具 + 12
Saigetsu + 3 共享资料的黑币奖励!
ko44 + 8 共享资料的黑币奖励!
yuyu628 + 5 很给力!棒棒哒
xiegh + 5 很给力!
龙与少年游 + 3 赞一个!
111hh + 5 很给力!

查看全部评分

回复

使用道具 举报

ID:205737 发表于 2017-8-13 15:02 | 显示全部楼层
给力给力
回复

使用道具 举报

ID:261271 发表于 2017-12-13 21:16 | 显示全部楼层
赞赞赞
回复

使用道具 举报

ID:209836 发表于 2018-3-10 15:33 | 显示全部楼层
厉害~~~
回复

使用道具 举报

ID:255776 发表于 2018-3-14 16:13 | 显示全部楼层
看起来很不错,有没有器材清单
回复

使用道具 举报

ID:291991 发表于 2018-3-14 20:26 | 显示全部楼层
学到了
回复

使用道具 举报

ID:294850 发表于 2018-4-12 15:37 来自手机 | 显示全部楼层
xiegh 发表于 2018-3-14 16:13
看起来很不错,有没有器材清单

做出来了吗?
回复

使用道具 举报

ID:294850 发表于 2018-4-12 15:47 来自手机 | 显示全部楼层
串口通信电路要程序吗?
回复

使用道具 举报

ID:320927 发表于 2018-5-3 04:10 | 显示全部楼层
很好的一个分享
回复

使用道具 举报

ID:314270 发表于 2018-5-15 17:35 | 显示全部楼层
delay=pinglv;请问这句是什么意思 啊
回复

使用道具 举报

ID:332824 发表于 2018-5-18 11:19 | 显示全部楼层
不错,赞一个
回复

使用道具 举报

ID:367664 发表于 2018-7-9 12:10 | 显示全部楼层
很给力,谢谢
回复

使用道具 举报

ID:320325 发表于 2018-7-16 22:01 | 显示全部楼层
很好的资源,感谢分享!
回复

使用道具 举报

ID:369904 发表于 2018-7-20 10:37 | 显示全部楼层
这个挺厉害的,但是原材料清单有没有
回复

使用道具 举报

ID:404725 发表于 2018-10-1 20:46 | 显示全部楼层
感谢分享!!!
回复

使用道具 举报

ID:411929 发表于 2018-10-31 21:34 | 显示全部楼层
拿来参考非常不错
回复

使用道具 举报

ID:92810 发表于 2018-11-4 22:45 | 显示全部楼层
好东西啊。谢谢了
回复

使用道具 举报

ID:420804 发表于 2018-11-5 09:29 | 显示全部楼层
蛮详细的
回复

使用道具 举报

ID:425726 发表于 2018-11-13 15:39 | 显示全部楼层
很给力,帮助很大
回复

使用道具 举报

ID:425919 发表于 2018-11-13 19:31 | 显示全部楼层
努力,学习中,谢谢!
回复

使用道具 举报

ID:434224 发表于 2018-11-27 16:22 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:444866 发表于 2018-12-12 14:44 | 显示全部楼层
厉害呀
回复

使用道具 举报

ID:453293 发表于 2018-12-24 11:51 | 显示全部楼层
给力给力
回复

使用道具 举报

ID:457968 发表于 2019-1-5 16:53 | 显示全部楼层
厉害
回复

使用道具 举报

ID:469441 发表于 2019-1-16 23:00 | 显示全部楼层
下载了,只有主函数啊,没有DAC0832的函数啊
回复

使用道具 举报

ID:477054 发表于 2019-2-26 09:45 | 显示全部楼层
sss123123 发表于 2019-1-16 23:00
下载了,只有主函数啊,没有DAC0832的函数啊

怎么下载啊
回复

使用道具 举报

ID:513159 发表于 2019-4-15 22:12 | 显示全部楼层
希望你可以把极限频率提高到1Khz
回复

使用道具 举报

ID:515552 发表于 2019-4-18 17:23 | 显示全部楼层
太棒了这东西
回复

使用道具 举报

ID:537558 发表于 2019-5-14 00:17 | 显示全部楼层
厉害了哦  看一看
回复

使用道具 举报

ID:537562 发表于 2019-5-14 11:25 来自手机 | 显示全部楼层
相当不错
回复

使用道具 举报

ID:537018 发表于 2019-5-14 16:17 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:567016 发表于 2019-6-25 15:30 | 显示全部楼层
很完整,很棒
回复

使用道具 举报

ID:662569 发表于 2019-12-12 16:31 | 显示全部楼层
很棒的帖子
回复

使用道具 举报

ID:425434 发表于 2020-7-7 15:47 | 显示全部楼层
有sch原理图文件吗
回复

使用道具 举报

ID:188773 发表于 2020-9-4 11:55 | 显示全部楼层
正想做个函数信号发生器,下载学习参考下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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