最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

基于DAC0832的函数发生器

来源:动视网 责编:小OO 时间:2025-09-27 21:37:44
文档

基于DAC0832的函数发生器

摘要本系统设计以STCC52RC单片机和DAC0832数模转换芯片为核心的函数发生器。这个设计的组成模块分别为1X4键盘、STCC52RC单片机、DAC0832数模转换芯片、信号放大模块和显示模块。1X4键盘是用来更换波形和频率的变化所需要的。单片机控制的D/A转换芯片与显示模块是本函数发生器的执行单位,实现了数字信号转换为模拟信号。LCD1602与STC12C5A60S2数字示波器为显示模块的组成部分,LCD1602作为函数发生器信号选择显示,STC12C5A60S2数字示波器作为检
推荐度:
导读摘要本系统设计以STCC52RC单片机和DAC0832数模转换芯片为核心的函数发生器。这个设计的组成模块分别为1X4键盘、STCC52RC单片机、DAC0832数模转换芯片、信号放大模块和显示模块。1X4键盘是用来更换波形和频率的变化所需要的。单片机控制的D/A转换芯片与显示模块是本函数发生器的执行单位,实现了数字信号转换为模拟信号。LCD1602与STC12C5A60S2数字示波器为显示模块的组成部分,LCD1602作为函数发生器信号选择显示,STC12C5A60S2数字示波器作为检
摘    要

本系统设计以STCC52RC单片机和DAC0832数模转换芯片为核心的函数发生器。这个设计的组成模块分别为1X4键盘、STCC52RC单片机、DAC0832数模转换芯片、信号放大模块和显示模块。1X4键盘是用来更换波形和频率的变化所需要的。单片机控制的D/A转换芯片与显示模块是本函数发生器的执行单位,实现了数字信号转换为模拟信号。LCD1602与STC12C5A60S2数字示波器为显示模块的组成部分,LCD1602作为函数发生器信号选择显示,STC12C5A60S2数字示波器作为检测输出信号。

论文主要介绍了上述各模块的工作原理及其实现方法。重点介绍了如何运用STCS52控制DAC0832芯片输出正弦波、三角波、方波、梯形波和锯齿波,同时也详细介绍STC12C5A60S2数字示波器的实现。最后,论文还对用本方案做出来的函数发生器产品进行了数据测试与分析,结果均符合设计要求。

关键词   函数发生器 ;数模转换;数字示波器

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

第1章 绪论

1.1 研究内容及意义

基于单片机的函数发生器的实现是通过编程的方法产生不同的波形,三角波、梯形波、方波、正弦波都是在matalbe软件下生产的坐标,再通过数模转换而产生的。按照要求,编写好要生成的波形的频率和幅度的程序,用keil编程软件生成hex文件,然后下载到单片机的存储器中。单片机上电复位,接着单片机就会执行下载的程序,程序运行过程中,当有按键按下的时候,就会跳到相应的中断服务子程序和波形发生程序,生成的模拟信号经过数模转换模块变成模拟信号,再通过运算放大器处理后,就生成了我们所需要的波形信号了。

研究函数发生器是由有一点的意义的,它可以用作信号的载波,用来调制信号,SPWM技术就是要用到三角波作为载波的了。函数发生器还有很多的作用。例如用作电路的检测,仪器的检测等等。就目前最常用的呼吸灯,通过出函数发生器生成的脉冲信号给LED小灯达到有暗渐渐变亮的效果呢。用函数发生器生成的信号用作载波还可以用在通信、广播、电视系统中,幅度、频率的变化把射频(低频)波信息嵌入到高频波,这样可以产生高频的振荡器。国际规定了低频波的范围是30-150HZ,中频波的范围是150-500HZ,高频波的范围是5K-16KHZ。这么高的频率一般的仪器是生成不了的,所以需要函数发生器来帮忙了。

好一点的函数发生器价格是很昂贵的,而我们一般的实验需要的信号频率都是低频或中高频的信号,所以用单片机做的函数发生器的意义重大。它的造价很低,而且体积又小,比起有FPGA用的函数发生器还要便宜,所以做个单片机的函数发生器是很有用的。

1.2设计内容与要求

1.2.1设计内容

设计的的元器件分别为:STCC52RC单片机、DAC0832数模转换芯片、LM358运算放大器、1X4键盘和LCD1602显示屏。通过编程让单片机产生波形的数字信号,通过P0口输出到DAC0832数模转换模块,在经过运算放大器的反相、滤波、放大,是电流转换为电压信号,且反相比例增大输出电压。波形的产生原理如下所示:

 (一)方波信号:通过设计定时时间,调到中断子程序,执行P0口按位取反,就能产生方波信号了,且通过设计定时时间来改变频率;

 (二)三角波信号:与方波产生的方法大致相同,通过定时器,调用中断子程序,查三角波ROM表,通过多次的调用中断子程序而产生数字信号,再转换为模拟信号,经放大输出;

 (三)锯齿波信号:锯齿波的产生方法跟三角波产生的方法差不多,不过它的ROM表计算是先从0以此加到0xff,再回归到0,这一个周期一个周期的显示;

 (四)梯形波:梯形波也是一样,它的ROM表示充0加到0xff,接着延迟一段时间,在充0xff减下去,这就是也个周期;

 (五)正弦波:这个波形分为4个ROM表,1/4个周期来做的,这样做的效果等到一条比较均匀的波形。

1.2.1设计要求

基于数模转换芯片DAC0832实现的函数发生器,利用到单片机控制产生的数字信号,通过数模转换得到模拟信号。通过程序实现频率的变,利用到单片机内置的定时器0,幅值变化。多种的波形的显示,并且可以在示波器上观察。STC12A5C60S2数字示波器,可以采样到0~10KHZ频率的信号,128显示出信号波形的信息。

           第2章 硬件电路的原理与设计

2.1 概述

(1)多种波形的输出,具体的波形输出:

1)三角波:三角波,波形的ROM表是从0x00加1到0x01,依次增加的,它的一个周期是从0x00到0xff再到0x00周期不断的循环就能产生了三角波。频率的的范围是22-227HZ。:

2)锯齿波:它的实现很简单,只需要一开始定义一个初值,然后不断的加1,当溢出后又重初值开始加起,就这样循环下去;

3)方波:它的实现方法是用定时器中断产生的,每次中断时,将输出的信号;

4)梯形波:是将输出的二进制数字信号依次加1,达到0xff时保持一段时间,然后依次减1直至0x00,并实时将数字信号经D/A转换得到的;

5)正弦波:通过matlab产生的正弦波,经过均匀取样,等到的数据,数据算是的公式为x=0.2*pi/:2*pi,y=round(sin(x)*127)+128,然后写在正弦波的ROM表。中断程序通过不断的查阅ROM值表,然后输出数字信号转换为模拟信号,再经放大电路将信号放大。

(2)单片机的P0口是连接DAC0832的数据端口的,1X4按键是连接在单片机的P3口,通过按键就可以控制波形的输出了。k0(SELECT_ WAVE)是用来切换波形的状态的,k1(ADD_FREQUENCY)是控制频率增加,k2(DELETE_FREQUENCY)是控制频率的减少,k3按钮是选择低电平输出。

(3)单片机的P1口是连接LCD1602的D0~D7的,让LCD1602显示波形的状态以及信息。

2.2 电路设计选择

2.2.1电路选型

方案一:采用DDS,即直接数字频率合成,它通过启动DDS,把内存缓存区的数据读出送到DDS后输出相应的频率,并把数据转换为BCD码,通过液晶显示器进行显示。但是这个技术相对难,且价格也不便宜,所以不选取。

方案二:采用锁相式频率合成方案,锁相式频率合成是将一个高稳定度和高精度的标准频率经过加减乘除的运算产生同样稳定度和精确度的 大量离散频率的技术,它在一定程度上解决了既要频率稳定精确,又要频率在较大范围内可变的矛盾,但频率受VCO可变频率范围响,高低频率比不可能作得很高。

方案三:利用单片机和数模转换模块生成波形,再加上一个低通滤波器,生成的波形比较纯净。通过单片机编程可以生成任意的波形,而且电路简单,适合你自己设计。以上的三个方案,都是可以采取,不过按照实际的设计来说,选取第三个方案是最合适的,难度低,容易控制,用软件的方法就可以生成多种波形,所以采用该方案三。.

                                

2.2.2.放大电路

方案一: 用增益可变运放AD603,其传输带宽高达90MHZ,完全可以满足输出信号频率的要求,由于输出的频率不需要这么大频率宽度,所以没有选取这款。

方案二:  用TL082双运放放大器实现电路的放大。TL082运算放大器具这样的特点:在较低的输入电压时,偏置电压不会受到影响。因为在调幅电路时,输入的电压是12V,输出的幅值调度范围是4.5V-12V。还有TL082内置频率补偿电路,所以它能使输出的信号更加的精确。TL082是一款老式的运算法大器,放大电路有很多查考资料,所以放大电路选型时,选用的运算放大器应选取TL082。但是在实际的电路调试在选取TL082放大器,在双电源的环境下工作,没有达到实际的效果,甚至使输出信号不稳定,考虑到市面上可以找的TL082运算放大器的替换的型号有LM358、LM393、NE555等,经过不同选取不同的运算放大器,调试不同的运算放大器,最后确定了LM358这款。LM358可以在单电源的环境下工作,且可以在5V供电的情况下使用,所以我把它的8引脚直接与5V相接,4引脚接GND。但是LM358在单电源条件工作下的放大电路与我之前使用的TL082放大电路有所不同,所以还是使用了双电源来驱动它。这样使用了这款运算放大器能达到预期的效果。放大电路使用的是,一级用电压比较,经过DAC0832输出的模拟信号与它自己的反馈信号进行比较,等出的值才进行放大增益。放大电路选取的是反相放大器放大电路,放大值为。

选取方案二即可实现调频。这样显然简单而容易控制,且精度较高。因此我选择方案二。

2.2.3显示模块

方案一 LED显示模块,它虽然编程是简单,但是显示的内容较少,而且电量的消耗又大,不应选取。

方案二 LCD1602显示模块,单片开发板自带的LCD1602显示模块可以满足我这个设计的要求,2X16个点阵,足够让我编写的字符串显示,而且编程的方法有很多相关的资料,关键是耗电低,所以用LCD1602来做显示屏是最佳的。

2.2.4D/A转换模块

方案一  用8位D/A转换器DAC0832实现数字量到模拟量的转换过程。

2.2.5调幅电路

方案一 通过软件实现。控制DA输出的的电流幅度的方法是在编程的时候将波形的ROM表的幅度降下来,不过这个方法不可取,假如我设置10个幅度等级,那么我就要设计10个对应的波形ROM表,这样做的话一点都不实际。首先这会大大增大程序的字节,因为单机的RAM只有256B,再者,程序会变的更加的繁琐,臃肿,所以不采取。

方案二 通过硬件来实现。在设计电路的时候,由于DAC0832与LM358的8脚和4脚,一开始我接的是5V电压,电路是可以驱动的但是幅度不能调,所以我在原来的PCB的基础上增加了一个调幅电路。+12V的电源接入,连接在1K的电阻上,然后接个10K的可调电阻,最后在接个1K的电阻,才接地。在这个简单的电路中,12V接1K的电阻是上拉电阻,这样的话才接入到电路中作为基准电压给DAC0832和LM358,从而实现幅度可调。

所以我选择了方案二。

2.3 键盘模块

 有一个1X4的键盘模块就可以了。在编程是应注意的是,选取的是机械键盘,就会出现所谓的抖动现象。抖动现象的出现会使单片机有误操作出现,所以在编程是要消去抖动,常用的方法是加入延迟程序,不过这个方案在实际开发中会影响到程序的跑偏(开发程序一般都是几千行的,只要在用一个移位指令就可以解决了),定时不准确,不过我在编写这个设计的程序时,行数不是很多,所以延迟的方案还是能使用的。

2.4 单片机控制模块

2.4.1 STCC52RC简介

单片机选型问题。在众多的单片机型号,我选取了STC系列的C52RC单片,这款单机比较简单,功能满足设计要求,价格便宜,编程容易,而没有选取比较高端的单片机的一个重要的原因是不熟悉它的操作,引脚定义等。

STCC52RC单片机与51单片机一样,只是扩展了一个功能,所以我在51单片机的基础上学习用52单片机能够很快的掌握其功能。该款单片有32个I/O口,3个16位的定时器/计数器(计数器这个功能一般是不用到,实际只用到定时器),4个外部中断接口,512B的RAM,所以在编写程序的时候一定要注意不要超过512B的RAM不然单片机就不能正常工作了。STC系列的单片,有些是不用复位电路以及晶振电路的,但是这款老式的单片机一定要有外部时钟才能工作,也就是振荡电路。它的18、19脚分别是XTAL1和XTAL2这两个引脚就是时钟的输入端。40引脚是接VCC,20引脚是接GND,这款单片机的工作电压范围是3.3V~5.5V才能正常工作。所以单机机I/O输出的电压范围是0~5v,在给一些仪器供电是,会在I/O口加上上拉电阻,这是为了增大驱动能力。上拉电阻的选取也有要求,在选取的电阻过大的,I/O在改变输出值时过渡过程会比较长的,一般上拉电阻的选取是根据实践经验来的。其实单片机的I/O输出时只能是0或1,也就是0V或5V,这就是TTL电平,如果让单片机直接输出0~5变化的值,就要接一个数模转换器才可以实现的。它的工作频率范围是在0~40MHZ。

STCC52RC单片机时40个引脚的,PDIP封装(直插式)所以在用Altium designer画元器件封装的时候一定要注意。单机机I/O口是标准的双向I/O,所谓的双向I/O是指,单片机内部输出1,才可以检测到外部发生的信号。

2.4.2STC12A5C60S2单片机的介绍

STC系列的单片机,大多数都有AD,PWM功能,这有老款的单片机没有这两个功能。

STC12A5C60S2单片机的封装方式是PDIP,40个引脚,内置一个10位ADC,可有有效的进行数模转换,其转换速率为250K/S,所以它可以满足我设计的要求。还有就是它的速度非常快,在同样的晶振电路下,它的速度是普通51单片机的8~12倍。它的其他引脚和普通51单片机类似,都是40脚接VCC,20脚接GND。还有它自带了2路的PWM,所以这款增强型的单片机非常适合我的设计要求。

2.4.2 单片机电路

函数发生器的设计电路是根据单片机最小系统,外接外围电路组成的。单片机最小系统由STCC52R单片机、12M晶振、22pf的电容,由于STCC52R单片自己内部不带复位电路,所以要在外围额外增加复位电路,确保单片机上电。

1.单片机最小系统

单片机最小系统在学习的单片机时是非常有用,就算开发的电路十分复杂,外围电路很多,使用的逻辑器件很多,但是还是离不开单片机最小系统。在STC系列中已经有的单片机内置了最小系统了,只需要给单片机供电,单片机就可以正常的工作了。在这了我选取的是STCC52RC,该电路没内置的晶振、复位电路等最小系统需要的电路,不过该电路的优势在于,价格便宜,符合我的开发需要。

单片机的18、19引脚是时钟信号的输入端口,把12M的晶振直接接在这两个端口上,为了是时钟能震荡起来需要在晶振的两个引脚接入22pf的电容,这样才可以是电路震荡起来,就能给单片机一个时钟命令。在电路中的晶振是石英振荡器。晶振具有非常好的频率稳定性和抗外界干扰的能力,所以晶振是用来产生时钟信号的,通过时钟信号来控制电路工作。数字电路的工作是根据电路设计,在某个时刻专门完成特定的任务,如果没有一个时序控制的标准时刻,整个数字电路就不知道什么时刻做什么事情了。所以一定要假如晶振时钟电路。

复位电路。单片机的RES引脚需要上电复位,就是给它一个高电平信号,不过不能直接接5V电压,这样单片机就一直处于复位状态,那单片机就不用工作了。这里应该是电源信号接一个0.47uf的电容,这样一上电,单片机就能复位了,也要可以接一个机械按键,通过按键是电容内的电压经过按键电路流入地,高电平就可以个RES引脚了,单片机就可以复位了。

单片机的40脚和20脚。40脚是接电源,20脚是接地。单片机这能在3.3V-5.5下工作,超过或低于这样的环境单片机时不会工作的。还要注意的是单片机的EA脚。所有的引脚空置的时候都是高电平,EA脚需要的是高电平的环境,可以空置,但是空置的话,有时会受到外界环境的干扰,所以还是需要把该引脚接上高电平。

2.外围电路

单片机有32个I/O口,在编程的时候我使用了20个I/O口,P0的8个端口接的是DAC0832的D0~D7的数据端口,P1的8个端口我接的是LCD1602的D0~D7数据端口,P2^4、P2^3、P2^2接的是LCD1602的控制端口,1X4键盘通过一个4选1的逻辑器件接在P3^2上,由于要用一个4选1的器件,在PCB的布局上会增加难度,所以我选优个1N4007的这一款二极管,利用二极管的单向导通性,实现了4选1,完美的替代了4选1的逻辑器件,降低了成本,且美观。

外围电路只需要用到了LCD1602、DAC0832、LM358等器件。

2.5 数模转换模块

DAC0832芯片介绍:

DAC0832输出方式有两种分别为:单极性输出和双极性输出,这次我采取的是双极性输出方式。DAC0832是一款能与单片完美结合的数模转换芯片,因为它的数据端口接的是单片机的I/O,I/O输出的是TTL电平,而DAC0832的D0~D7就是根据TTL电平变化的。它的ILE、CS、WR1 、WR2和XFER的接法是有技巧的,不能随便输送高电平或低电平,只有当CS为低电平时、WR1为低电平、ILE和XFER为高电平,这款芯片才可以正常的工作。这个接法是根据DAC0832芯片内部结构定义的。

DAC0832的内部结构框图如下图所示。

DAC0832的外部引脚及功能介绍图如下:

图2-3 DAC0832引脚图

      实际电路接法是D0~D7接单片机的P0口,由于I/O口驱动能力不足,会使产生的信号失真,所以加了一个上拉电阻,这个上拉电阻是一个9针的10K的排阻。然后把CS与WR1接在一起,再接到单片的P2^0,通过单片机控制,是否让数模转换模块工作,9(RFB)脚输出的是一个反馈值,从DAC0832的机构图可以看出来的,通过与11(OUT1)脚输出的值比较就可以输出波形的信号了。8(VREF)脚电压基准引脚用作为参考电压,其电压范围是正负10V,所以当我设计调幅电路是接入的是12V,但是输出的电压只有10V,就是因为参考的设置的范围。3脚是模拟电路接地,直接跟10脚相接,再接地就行了。

2.7 显示模块

2.7.1LCD1602显示

LCD1602是一款简单的LCD显示器,它分为2行,每行有16个5X8的点阵,所以在编写程序的时候要先定义坐标。按照LCD1602的手册的说明,第一行的开始地址为0X00,第二行为0X40,它的入口地址为0X80。对它进行操作时,一定要先读它的状态,是否在忙,如果不忙,才可以在数据写进去。所以在编写LCD1602显示的程序分为以下步骤:先初始化,然后读取它的状态,判断状态是否为忙,再进行写数据,只让才可以让他工作,在写数据之前一定要先定义好坐标。RS、RW、E不同状态是有不同的作用。

LCD1602的引脚定义简单,把2脚和15脚接上5V的电压,在把1脚与16脚接上地,3脚是偏置信号,所谓的偏置信号就是控制LCD1602的清晰度,让该显示的小灯达到一定的发光程度,让不该光的小灯不会发亮,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会 产生“鬼影”,这样就能便于观察LCD1602屏幕的信息。4、5、6脚分别是RS(寄存器)、RW(读写信号)、E(使能脚),这三个脚与单片机的P2.4、P2.3、P2.2端口相接,什么时候让它置高低电平是根据LCD1602的数据手册来定义的,单片机通过控制这三个脚就可以对LCD1602进行读写操作了,7-14脚是双向数据端口用来初始化LCD1602的。

LCD1602的通讯方式为UART,即异步通信,所谓的异步通信是单片机的时钟与它的时钟是不同步的,如果不同步怎么通讯?其实异步通信的工作原理是将传输数据的每个字符一位接一位地传输,它自己有个奇偶校验位,用来判断传输字节时是否有错误。

2.7.2STC12A5C60S2数字示波器

STC12A5C60S2数字示波器的简单介绍。

这个通过数据采集并且可以显示波形的简单示波器是由一个128(驱动芯片ST7565)和一块STC12C5A60S2组成的。由于没用使用外部的AD芯片,采用了一块自带AD的单片机,测量范围是10K,虽然不是很精确,但是可以用来测量自己做的函数发生器产生的波形,这样就可以省去用示波器观察的步骤的,直观的在128上可以看到波形。

数字示波器的工作原理很简单,而且在电路布局的时候我应经尽量采用小的仪器件,因为这个不是我主要的设计要求,所以尽可能简单就做多简单。数据采集是这样的,信号通过一个0.47uf的电容,对杂波的过滤,然后接着连接到P1^2的管脚上,这是就是单片机工作的时候了。采集的信号是模拟信号,要转换为数字信号,单片机才能认识,用单片机自带的AD进行转换就行了。10位精度ADC,共8路,转换速度可达250K/S(每秒钟25万次)。转化成数字信号后就是让128显示出波形了。选取的128用的驱动芯片ST7565,这种液晶屏的好处是只需要用到8个管脚就可以对它进行读写操作了,这比一般的128要好,普通的要用的16个管脚,占用了太多的管脚,在布线的时候不方便的,不过用普通的编程的时候有一点好处,就是它跟LCD1602驱动一样,会简单一点,但是在开发设计的时候有一个大原则,就是能用软件实现的尽量用软件实现,而不用硬件来替代。

 编程设计的时候这种单片机有点难度,因为之前都是用STCC52的,用来它编程的话是挺容易的,但是这个涉及算法,要用到一个电压衰减的算法,由于在这方面涉及的不多,所以我上网查询了好多资料,讲解这些方面的很少,通过不停的更换关键搜索,终于给我找到了这方面的内容了。这样很成功的做出了个简易示波器。

2.8本章小结

函数发生器的选型方案真的很多,到底哪一个方案符合需要,要按照设计要求才可以。其实一个函数发生器,做出来只需要一个内置PWM和AD的单片机,再外围接个放大电路就能实现了不同波形的输出,而这次的设计我使用的是DAC0832这款芯片,所以这种方案是不能选取的,所以方案的选取会影响到后期的程序设计以及硬件电路。

硬件电路的设计设计的知识点真的很多,由于PCB电路板是自己做的所以在画PCB的时候尽可能的画单面板,双面板在优化设计上以及做PCB板技术提高的情况下再选取,所以优先选取单面的PCB板。Altium designer这个软件画原理图的时候尽量小用网络表示符号,一但用了再画PCB的时候,会出现网络符号丢失,这样线就连不过去了,对后期的做板有很大的影响,因为做好了板了,元器件都焊接好了,程序又可以,这样检测是问题就很难找到了,所以还是建议把原理图画好在导入到PCB中。布线的时候要自己布线,自动布线的功能非常不好用,它会把线布的很多,而且有时候还会出现断线,却线的情况,所以还是自己对元器件布局,自己布线,才能更好的熟悉自己的做的东西。

器件的选型至关重要,优先考虑的选型方案是简洁,稳定,便宜。做PCB也是先做到能做单层,尽量做单层,能自己布线的,就自己布线。硬件的设计是很有讲究的,一定不能马马虎虎,不然做出来的东西就会很麻烦,特别是在调试的过程中,问题会很多。

第3章 软件设计

3.1 系统主程序设计

(1)总体方框图

通过matlab采样得到的值在y轴上表示,通过单片机自身的定时器0,跳入到中断子程序查波形ROM表输出数字信号。通过定时器产生的数字信号比较稳定,不过也可以用延迟产生的波形,一个while语句里面嵌套一个延迟程序,但是这样做产生的波形会失真,所以没有用这个方法。产生的数字信号传送给数模转换芯片,在由放大电路放大,这样就可以有波形输出了。在没有放大电路的作用下,DAC0832产生的信号过于低,不能由示波器观察。

STC12A5C60S2数字示波器的机构框图:

128数字显示

单片机处理

外部信号

AD采集

AD模数转换跟DA数模转换的道理是一样的,这是DA的逆过程。AD的参考电压是5V,那么最小的电压是5/256V(8位的AD转换器是256),假设输入电压为x,那么转换给单片机的数字信号为,x/(5/256),再把这个值转换为二进制,这样单片机就能识别,这就是AD采集的过程,单片机把该值存放在寄存器,在输送给128,让128显示一个动态过程,其实是很多张图片的叠加,只是设置好它刷新频率,就可有动画显示了。

(2)程序设计

程序是单片机的核心部分,会了程序等于会了单片机。编写一个函数发生器的程序有很多种方法,哪一种是真正的适合自己的设计呢?所以要不断的尝试才能找到适合自己的。

这次的程序设计我用的方法是利用定时器0,定时时间就是波形的频率。在主函数里设计好定时器0的工作方式后,单开中断入口地址,接着就是一个while(1)的死循环了。单片机中中断程序有执行等级的,单片机默认的优先等级为:外部中断0>定时器0>外部中1>定时器1,中断入口地址分别为0、1、2、3,所以这里我用到的是定时器0,中断入口地址为1。键盘输入时用到的是外部中断0,中断入口地址是0。所以在设计程序的时候我帮TH0、TL0放在外部中断0,当有按键动作是,程序就调到外部中断0的子程序,开始设计定时时间,当定时时间到了,就会调到中断1的子程序,执行一个波形的子程序,该子程序就是让P0口输出波形的数字信号,通过定时器不断循环,从而产生一个完整周期的波形。在中断0的子程序还执行的内容是让LCD1602显示字符串,就可以做到按一下按键同时可以做到波形的切换和LCD1602的波形类型的显示。这个程序就是函数发生器的核心内容。

而STC12A5C60S2数字示波器的程序设置稍微有点麻烦,当采集的信号小于100us时,直接采样,软件延迟的方法,而没有有定时器,这样虽然不能精确的定时,但是可以加快扫描时间,这样128的刷新频率会加快的。当采样时间大于等于100us时,采用的是定时器采样得方式,这种方案可以做到波形更加的精准,但是采样时间很有点慢。采集完信号够就是对电压衰减处理过程了。用个状态机,所谓的状态机就是swich语句,每个电压值有个衰减过程,假如是1V电压输入,先进入一个for循环进行检测,再通过2个if语句进行判断,接着就是将该点在上128上显示。128(st7565),做个表格ROM,if语句判断过后就是读取ROM表上值,这个值在送个128,这样就能显示图片了。

(3)波形产生过程

1)三角波的产生

    三角波,波形的ROM表是从0x00加1到0x01,依次增加的,它的一个周期是从0x00到0xff再到0x00周期不断的循环就能产生了三角波。频率的的范围是22-227HZ。

流程图如下图所示:

三角波产生流程图

程序:

void triangle_out()    //三角波输出

{    

    DAdata=triangle_tab[wavecount++];

if(wavecount>) wavecount=0;

    DA_S1=0;  //打开8位输入寄存器

    DA_S1=1;  //关闭8位输入寄存器

2)方波的产生过程

此波形的实现更加简单,只需开始的时候设置一个初值然后直接输出这个值就行了,输出一段时间后,然后再重新置一个数据,然后再输出这个数据一段时间,但是此时的时间一定要等于前面那段时间。这样才是一个方波,如果两个时间不相同,那就相当于一个脉冲波了,也是运用到定时作用。

流程图如下图所示:

方波产生流程图

程序:

void square_out()  //方波输出

{    

    judge=~judge;

    if(judge==1) DAdata=0xff;

    else  DAdata=0x00;

    DA_S1=0;  //打开8位输入寄存器

    DA_S1=1;  //关闭8位输入寄存器

3)锯齿波的产生过程

锯齿波的产生方法跟三角波产生的方法差不多,不过它的ROM表计算是先从0以此加到0xff,再回归到0,这一个周期一个周期的显示,流程图如下图所示:

锯齿波产生流程图

程序:

void triangle_out()    /锯齿波输出

{    

    DAdata=triangle_tab[wavecount++];

if(wavecount>) wavecount=0;

    DA_S1=0;  //打开8位输入寄存器

    DA_S1=1;  //关闭8位输入寄存器

4)正弦波的产生过程

这个波形分为4个ROM表,1/4个周期来做的,这样做的效果等到一条比较均匀的波形。

流程图如下图所示:

   

 

                         正弦波产生流程图

程序:

void sine_out()     //正弦波输出

{    

    DAdata=sine_tab[wavecount++];

    DA_S1=0;  //打开8位输入寄存器

    DA_S1=1;  //关闭8位输入寄存器

5)梯形波的产生过程

梯形波也是一样,它的ROM表示充0加到0xff,接着延迟一段时间,在充0xff减下去,这就是也个周期;

流程图如下图所示:

   

 

梯形波产生流程图

程序:

void triangle_out()    /梯形波输出

{    

    DAdata=triangle_tab[wavecount++];

if(wavecount>) wavecount=0;

    DA_S1=0;  //打开8位输入寄存器

    DA_S1=1;  //关闭8位输入寄存器

3.2 键盘按键

      通过按钮实现波形的切换比较简单只需通过输出波形后不断返回到检测按钮的子程序中,判断是否有别的按钮的拨动,与中断into输入相关,其中由于选用4选1的与非门的布线较为麻烦,所以本设计没有采用与非门,而是选用了4个1N4007二极管与into相连,进而每按动相应按钮,作出相应变化,k0按钮,每按一下有序选择输出波形,k1按钮是进行波形频率的增加,k2按钮是进行波形频率的减少,k3按钮是选择低电平输出。扭动电位器可调整输出幅度。

键盘扫描模块。在单片机学习过程中,需要学习的是开发板上的4X4的键盘,4X4的键盘扫描需要的是键盘扫描模块驱动。首先单片机准双向I/O口,单片机内部输出一个高电平,才可以读取按键信号,当有按键按下的时候就能读取低电平,假如单片机内部输出一个高电平的话,内部的三极管就会导通,所以按键有没按下都无关的。按键是这样实现的,4X4键盘也是这个道理,在这里我选取的是4X1键盘,所以没有4X4那么麻烦。4X4键盘扫描的驱动程序,先扫描4行,确定那一行,在扫描哪一列,其实可以建立一个4X4的矩阵,通过读取来获得地址。不过现在才用的4X1的,程序设计就会变的很简单了,只需要扫描一列就可以读取到按键动作了。

3.7 本章小结

程序设计要模块处理,这样程序就不会显得这么臃肿。一个.C文件也可以实现,但是在查考程序,以及修改程序和检查程序的时候回显得很繁琐,排查难度增加了不了。当是模块块处理会是程序显得简单了,一个工程下多个.C文件,可以很好的排查问题。写程序的时候一定要多用//这种注释,可以方便自己后期的查看。

在编写程序的时候波形的ROM表要写入到单片机的ROM中,要使用关键字code,这样ROM表就不用占用单片机的RAM,之所以不占用RAM,是因为单片机的RAM只有512K,一个程序下来可能占用200K的内存,而且波形的ROM表是不用反复修改的,所以没必要占用RAM,只需要写进ROM中就可以了。

第4章 安装调试

4.1 硬件电路的调试

根据方案设计要求,调试过程公分三大部分,硬件调试,软件调试,软件和硬件联调。电路按模块逐个调试,各模块调试通过后在联调。程序先在最小系统板调试,通过后在软硬联调。

将本设计放在protues中进行仿真。

仿真电路

仿真通过通过后,在开发板上按照仿真电路进行实物连接,由于没有数模转换模块就暂时没有在开发版上连接,只用了LCD1602、单片机最小系统和4X4键盘。开发板上连接实现了,通过按键的切换,LCD1602上的字符串的更变。

以上的都实现了电路的功能之后,就开始画PCB 图,做板。函数发生器的PCB用的是单面板,而数字示波器用的双面板,两块板的尺寸是10X6和10X7,这样两块上下叠加的时候可以空出1X1的位置来控制1X4的键盘,来切换不同的波型。

4.1.1 供电电路的检测

        PCB板做好后进行焊接,接着就是对电路的供电检测,看一下焊点是否饱满,防止虚焊。用万能表对电路的检测,是否出现断路,断路的情况,如果出现了要及时补救,这样可以减少问题的出现。以上的步骤都做完了就对电路进行供电。供电后电路正常工作,LCD1602能正常显示字符串,通过按键可以对波形的切换,接着就是用双12V给LM358供电,再用实验室的示波器观察。结果通过按键的切好可以产生不同波形,并且在示波器上能正常显示,频率切换也可以,这证明这块PCB 板的供电情况正常。

4.2 软件调试

 Proteus在进行的仿真,仿真图画好后,就把之前写好的程序通过keil V4编译器生成的hex文件下载到Protues中的C51中,如后仿真。在Protues中有些模型是不能使用,就好像C52、DAC0832、LM358这些器件的模型不行的,要找到跟它们相识的器件才可以替换才可以进行仿真。在keil V4中可以使用debug来对程序进行仿真,可以一步步对程序进行检测。

4.3 软硬件联调

 程序的烧写是通过ISP这个软件下载到单片机的,单片机的通讯方式是异步通信(UART),两个元件不用在同一时钟信号下都可以显示通讯。用一个专用的TTL转换模块接到单片的RS和TX上,但是要注意的是TTL转换模块的RS端口连接的是单片机的TX口,而TX连接的是单片的RS,这样,才能与单片机正常的通讯。

 软件、硬件都可以行了,把下载程序的单片机安装到硬件上,再把电路给上5V的电源,运放接双12V的电源。LCD1602能显示,通过按键能对LCD1602上的字符串进行改变,通过示波器能观察到波形。

4.4 本章小结

    在调试过程中,我一开始选取的运放是按照我电脑仿真软件上的TL082,但是把它安装在实际电路中,用示波器检测,会发现出来的不是波形,而且信号也不好,这个让我反复的检测电路,是否出现了断路、虚焊、元器件问题等原因,按照常理来说仿真通过的话,硬件一般都可以的,再次浪费我了好长时间,而且我还重新画过了PCB,确保电路没问题。对着电路检测我发现了一个问题,当我用示波器接到DAC0832的11脚上,且通过按键切换到方波输出时,示波器上是有波形的,但是其他波形就不会出现,而且重新把探头接到运放的7脚上,示波器上是没有波形,这使我考虑到是我的运放出现了问题,所以我就更换了几个TL082,但是问题依旧没有解决。这时我请教了老师以及同学,他们给我的答复是更换功能一样的运放来尝试,所以我就在网上搜索了一翻,发现还有几款功能一样,也是双运放的,我就挑选了LM393、LM324、LM358,这三款来尝试,由于LM324是8个引脚,与我的电路封装不一样,因此不能使用,我就用了LM393和LM358来用。LM393可以单电源工作的,是一个电压比较器,我安装后发现问题还是没用解决,我就用LM358来做最后的尝试,结果发现示波器上可以显示波形了,而且波形没有失真。

在学习单片机,和开发产品的时候不要一直依赖仿真软件,要多东说、多尝试才可以的。

    第5章  数据测试与分析

5.1 实际波形输出

5.1.1

单片机通上电后,给运算放大器加上正负12V的电源,这个函数发生器就能正常的工作,在输出端口接上DS1022C型号的示波器的探头,通过调动示波器的参数,能正常的显示波形了。三角波的输出情况如图1所示,但调动采样频率过小的就会出现一小个一个的现象,这种现象是因为在DAC0832产生的模拟信号的精度不够高,采取DAC0832的精度8位的,电流稳定是1us。在PROTUES上仿真的结果如图2显示,两者通过比较得出的三角波差别不大。

图1

图2

5.1.2

触摸按键K0来切换波形,第二个波形就是方波,通过示波器观察如图3显示,但是在采样频率过低的时候波形会失真,所以只能通过在中频的时候查看。由于方波的产生是通过定时器计时,再个P0取反,所以产生的方波频率比其他波形的波形形态要好,但是失真的这情况就解决不到。图4个仿真的波形图。两者比较差别不大,产生的方波没问题。

图3

图4

5.1.3

锯齿波的产生仿真如图6所示,实际的示波器观察的图形如图5所示。实际电路产生的锯齿波的频率过低,所以在示波器上查看的效果没有在仿真软件上效果那么好。

图5

图6

5.14

梯形波的实际波形如图7所示,仿真如图8所示。梯形波的的效果也不是很理想,跟锯齿波的原因一样,都是频率过低而导致产生的波形在示波器上观看的效果不好。

图7

图8

5.1.5

正弦波的是通过4个ROM值表,而且是在matlab上通过均匀采样得到的值,再写入到程序中,所以实际产生的波形如图9所示,仿真波形如图10所示。对比两个图,两者相差不到,图9的波形很均匀没有什么失真的现在,效果很好,对比锯齿波和梯形波的效果要好很。

图9

图10

5.2 函数发生器与STC12A5C60S2数字示波器相接

5.3 波形的频率

三角波22316269100125161125227
方波921922633845005307697817931.4k
梯形波//3.2//////3.4
锯齿波//////////
正弦波5.81117232935404651
单位:HZ

5.4 数据分析

波形的频率都比较低,只有方波是1.4KHZ,而且梯形波与锯齿波的频率都低于5K,低于5KHZ是示波器就查看不到频率了,产生的原因是

5.5 本章小结

整体的数据都满意,当我尝试产生34KHZ的方波时,需要用到定时器的工作方式2,工作方式2是8位的,当满256就会溢出这样就可以产生更高频率的波形了,当是这种工作方式有个特点就是不用再中断程序中重新给定时器幅值,由于它这样的局限性,不能为我后期波形的频率调试所用,所用我没用这个方案,而是采取了定时器的工作方式1,它是16位的定时器,进入中断要重新幅值,这样在频率的子程序重新给定时器幅值,就可以是波形的频率变化。

基于DCA0832的函数发生器,产生的频率不够高,在示波器上观察时,有些波形会失真,梯形波,锯齿波产生的频率又过低,导致查看时,会出现波形有时看不到的现象。把这个函数发生器接到自己做的数字示波器上,能查看的波形只有三角波、方波和正弦波,这个有点不好。

我通过查阅相关的资料,还有别人用单片机做的函数发生器,都是在低频阶段产生波形的,所以我应该多想想,多试试,或许能找的好方案。

结    论

附件:波形发生器设计程序

#include

#define  uchar unsigned char

#define  uint  unsigned int

#define  Fosc  24000000/12000000 

#define DAdata  P0

sbit DA_S1= P2^0; 

sbit DA_S2= P2^1;  

sbit key=   P3^2;

uchar wavecount; 

uchar THtemp,TLtemp;

uchar judge=1;      //在方波输出函数中用于简单判别作用

uchar waveform;      

uchar code freq_unit[5]={10,50,200,200,200}; //五种波的频率单位

uchar idata wavefreq[5]={1,1,1,1,1};      

uchar code  lcd_hang1[]={"Sine Wave       " "Triangle Wave   " "Square Wave     ""juchibo Wave    ""tixingbo Wave   "  "Select Wave:    " "press No.1 key! "};

uchar idata lcd_hang2[16]={"f=    Hz        "};

uchar code waveTH[]={

    0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

    0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

    0xec,0xf6,0xf9,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe};

uchar code waveTL[]={

    0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde,    //梯形波频率调整中间值

    0x88,0x50,0x90,0x32,0x34,0xbe,0x4a,0xa3,0xe5,0x2c

    0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde,    //锯齿波频率调整中间值

    0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde  

    0x06,0x8a,0x10,0x4e,0x78,0x93,0xa8,0xb3,0xbe,0xc6, //正弦波频率调整中间值

    0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde,    //三角波频率调整中间值

    0x88,0x50,0x90,0x32,0x34,0xbe,0x4a,0xa3,0xe5,0x2c}; 

uchar code triangle_tab[]={     //每隔数字8,采取一次

    0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,

    0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xff,

    0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80,

    0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08,0x00};

uchar code juchibo_tab[]={     //每隔数字8,采取一次

    0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,

    0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xff,

    0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,

    0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xff};

uchar code tixingbo_tab[]={     //每隔数字8,采取一次

    0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,

    0x80,0x88,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,

    0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x88,0x80,

    0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08,0x00};

    

uchar code sine_tab[256]={

    //输出电压从0到最大值(正弦波1/4部分)

    0x80,0x83,0x86,0x,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,

    0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,

    0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,

    //输出电压从最大值到0(正弦波1/4部分)

    0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,

    0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,

    0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99 ,0x96,0x93,0x90,0x8d,0x,0x86,0x83,0x80,

    //输出电压从0到最小值(正弦波1/4部分)

    0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,

    0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16 ,0x15,0x13,

    0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,

    //输出电压从最小值到0(正弦波1/4部分)

    0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,

    0x11,0x13,0x15 ,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,

    0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66 ,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80}; 

void delay(uchar z)      

{

    uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

void triangle_out()    //三角波输出

{    

    DAdata=triangle_tab[wavecount++];

if(wavecount>) wavecount=0;

    DA_S1=0;  

    DA_S1=1; 

}

void sine_out()     //正弦波输出

{    

    DAdata=sine_tab[wavecount++];

    DA_S1=0;  

    DA_S1=1; 

}

void square_out()  //方波输出

{    

    judge=~judge;

    if(judge==1) DAdata=0xff;

    else  DAdata=0x00;

    DA_S1=0;  

    DA_S1=1;  

    

}

void juchibo_out()    //锯齿波输出

{    

    DAdata=juchibo_tab[wavecount++];

if(wavecount>) wavecount=0;

    DA_S1=0;  

    DA_S1=1;  

}

void tixingbo_out()    //梯形波输出

{    

    DAdata=tixingbo_tab[wavecount++];

if(wavecount>) wavecount=0;

    DA_S1=0;  

    DA_S1=1;  

}

#define lcd_ports P1

sbit rs=P2^2;

sbit rw=P2^3;

sbit lcden=P2^4;

void write_com(uchar com)

{

    rs=0;    

    lcden=0;

    lcd_ports=com;

    delay(5);

    lcden=1;

    delay(5);

    lcden=0;    

}

void write_date(uchar date)

{

    rs=1;    

    lcden=0;

    lcd_ports=date;

    delay(5);

    lcden=1;

    delay(5);

    lcden=0;    

}

void disp_lcd(uchar addr,uchar *temp1)

{

    uchar num;

    write_com(addr);

    delay(1);   

for(num=0;num<16;num++)

    {

        write_date(temp1[num]);

        delay(1);

    }

}

void init_lcd()

{

    

    lcden=0;  

    rw=0; 

    write_com(0x38);  

    write_com(0x0c);  

    write_com(0x06);  

    write_com(0x01);  

    write_com(0x80);  

    disp_lcd(0x80,&lcd_hang1[5*16]);  

    disp_lcd(0xc0,&lcd_hang1[6*16]);          

}

void main()

{

    uchar i=0;

    DA_S2=0;   

    DAdata=0;

    DA_S1=1;    

    init_lcd();

    waveform=0;    

    TMOD=0x01;  

    IT0=1;      

    ET0=1;      

    EX0=1; 

    EA=1;

    while(1)

    {

    }

}     

     

void timer0() interrupt 1

{

    TH0=THtemp;

    TL0=TLtemp;

    if(waveform==0)      sine_out();

    else if(waveform==1) triangle_out();

    else if(waveform==2) square_out();

    else if(waveform==3) juchibo_out();

    else if(waveform==4) tixingbo_out();

}

void key_int0() interrupt 0

{

    uchar keytemp;

    uint total_freq; 

    EA=0; TR0=0;     

    delay(5);       

    if(key==0)       

    {

        keytemp=P3&0xf0; 

        switch(keytemp)

        {

            case 0xe0:    //选择波形

                 waveform++;

                 if(waveform>2) waveform=0;

                 break;

            case 0xd0:  //频率按规定单位依次增加

                 wavefreq[waveform]++;

                 if(wavefreq[waveform]>10) wavefreq[waveform]=1; 

                 break;                                            

            case 0xb0:  //频率按规定单位依次衰减

                 wavefreq[waveform]--;

                 if(wavefreq[waveform]<1) wavefreq[waveform]=10; 

                 break;

            case 0x70:    //TTL输出

                 DA_S2=1; 

                 break;

        }

        

        THtemp=waveTH[waveform*10+(wavefreq[waveform]-1)]; 

        TLtemp=waveTL[waveform*10+(wavefreq[waveform]-1)];

    

        total_freq= wavefreq[waveform] * freq_unit[waveform]; 

        lcd_hang2[5]=total_freq%10+0x30;                 //在液晶中显示个位,(0x30 在液晶显示中表示数字0)

        total_freq/=10; lcd_hang2[4]=total_freq%10+0x30; //在液晶中显示时十位

        total_freq/=10; lcd_hang2[3]=total_freq%10+0x30; //在液晶中显示时百位

        total_freq/=10; lcd_hang2[2]=total_freq%10+0x30; //在液晶中显示时千位

        disp_lcd(0x80,&lcd_hang1[waveform*16]);  //在第一行显示

        disp_lcd(0xc0,lcd_hang2);  //在第二行显示

    }

    EA=1;

    TR0=1;    

}

文档

基于DAC0832的函数发生器

摘要本系统设计以STCC52RC单片机和DAC0832数模转换芯片为核心的函数发生器。这个设计的组成模块分别为1X4键盘、STCC52RC单片机、DAC0832数模转换芯片、信号放大模块和显示模块。1X4键盘是用来更换波形和频率的变化所需要的。单片机控制的D/A转换芯片与显示模块是本函数发生器的执行单位,实现了数字信号转换为模拟信号。LCD1602与STC12C5A60S2数字示波器为显示模块的组成部分,LCD1602作为函数发生器信号选择显示,STC12C5A60S2数字示波器作为检
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top