在信号发生器中怎么接a功能a d转换器的功能 让其具有数字显示功能

甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S
您当前的位置:
> 甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S
甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S
发货地址:广东东莞
信息编号:
产品价格:1000.00 元/台
商家相关产品:
商家产品分类
“甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S”详细信息
产品规格:
产品数量:
包装说明:
价格说明:
查看人数:
本页链接:
http://info.b2b168.com/s168-.html
甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S
长期供应/收回/维修/租凭信号发生器ESGD3000A史S
Agilent ESG-D4000A系列数字和模拟信号发生器
频率:250KHZ-4000MHZ
Agilent ESG-D系列射频信号发生器除具有广泛的特性和优良的模拟性能之外,还提供多种数字
调制功能,而且在价格方面亦能被用户所接受。它们提供了极好的调制精度和稳定度,以及空前
的电平精度。
Agilent ESG-D系列特别适于满足当前数字接收机测试、元器件测试和本地振荡器应用日益提高
专门定制的调制和DECT、EDGE、GSM、NADC、PDC、PHS、TETRA标准(选件UN8) 内部生成通用标
准的信号来对接收机进行测试。改变调制类型、数据、码元速率、滤波器型式和滤波因数,以生
成供元器件和系统容限测试用的定制信号。通过变换I/Q值和构成独特的FIR滤波器,可形成定制
信号。很容易配置时隙来模拟不同类型的通信业务量、控制信道或同步信道(或突发信号)。可
产生具有内部突发功能的移动站或基站传输。还降低了对具有综合数据生成功能的外部设备的需
内部双任意波形发生器(选件UND) 能重现几乎任何以数学形式生成的波形。可下载长波形或多
个波形(达1M取样),以放置或贮存到非易失RAM中供随后使用。14比特的数模转换器(DAC)分
辩率扩大了动态范围和改善了噪声性能。在对I/Q生成进行优化后,双任意波形发生器选件将使
装置大为简化。
W-CDMA和Cdma2000 能产生符合正在拟定的国际标准的正确编码信号。模拟用于基站和移动接收
机测试的全编码信道或部分编码统计修正的多信道信号,可以对用于正在拟定的国际3G标准的
有源元件进行精确的大容易测试。
多信道和多载波CDMA
Agilent ESG-D系列提供CDMA(选件UN5)测量专用卡。用多个信道产生多载波CDMA信号,每个载
波用于基站和移动站的系统或元件测试。通过选择预定的多载波CDMA配置或明确确定每个信道对
每个载波的特性,可以为某些特殊的需要,如互补累积分布函数(CCDF)专门制定某种测试。
内部误码率分析仪(选件UN7) 为测量灵敏度和选择性而进行误码率分析。选件UN7提供用于PN9
和PN15比特序列的分析功能,并指出用户规定的测试极限的合格或不合格条件。
宽带I和Q调制 利用模拟I和Q输入,产生复杂的调制格式,以满足射频数字通信系统开发研究和测
试的需要。机内正交调制器处理I和Q输入信号,以在10MHz(1dB)带宽范围提供极高的调制精度
和稳定度。
极高的电平精度
Agilent ESG-D系列射频信号发生器能在宽的功率范围(+13dBm~-136dBm,利用选件UNB时为
+17dBm~-136dBm)以极高的电平精度进行精确、有效的灵敏度测试。内部调制格式的电平精度
优于±1.1dB(典型值为+0.6dB),从而保证甚至对灵敏的数字接收机也能进行精密测量。
我们的优势:
品种齐全,货源充足,存库雄厚,服务快捷,维修能力强。
欢迎来电!上门看货!您的满意是我们的追求!
(本公司大量供应二手进口仪器:如网络分析仪,频谱分析仪,音频分析仪器,视频分析仪器,高频信号源,
无线电综合测试仪等高频仪器,公司长期专业销售、租赁、维修、计量、回收高频二手仪器!! )
凡本公司所销售的产品可享受一年保修期
欢迎来到东莞市银通电子有限公司网站,我公司位于素有“龙舟之乡、中国民间艺术之乡、举重之乡、粤剧之乡”之美誉,号为“世界工厂”的东莞市。 具体地址是东莞市塘厦镇迎宾大道塘富路144#,联系人是史小姐。
联系电话是9,联系手机是,主要经营东莞市银通电子有限公司是一家从事电子仪器的开发,生产,销售与一体的高科技企业。
是一家从事仪器仪表销售、租赁、维修、计量、回收的专业公司。主要致力于包括,阳光等世界知名品牌的网络分析仪、频谱分析仪、综合测试仪、数字通讯测试仪、高频信号源、高频示波器、调制度仪、电声测试仪,音频分析仪、等二手高频通讯测试仪器仪表的销售及租赁业务.其中二手仪器销售业务
本公司..。
单位注册资金未知。
我要给“甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S”留言
“甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S”联系方式
东莞市银通电子有限公司
(网络销售)
地址:东莞市塘厦镇迎宾大道塘富路144#
邮编:523710
网址:http://sge187.cn.b2b168.com/
“甩卖!^-^!ESG-D4000A信号发生器ESGD4000A/史S”相关产品,你也可查看该供应商更多
粤ICP备号 - Copyright (C) 2004 - .com All Rights Reserved文档分类:
微机原理课程设计_信号发生器的设计.doc
下载后只包含 1 个 DOC 格式的文档,没有任何的图纸或源代码,
下载前请先预览,预览内容跟原文是一样的,在线预览图片经过高度压缩,下载原文更清晰。
您的浏览器不支持进度条
下载文档到电脑,查找使用更方便
还剩?页未读,继续阅读
该用户其他文档
下载所得到的文件列表微机原理课程设计_信号发生器的设计.doc
文档介绍:
1 微机原理课程设计信号发生器的设计 2 时间: 2006 年7月 13日第一章课程设计的目的意义 1.1课程设计的目的微机应用系统设计与综合实验是对所学课程内容全面、系统的总结、巩固和提高的一项课程实践活动。根据汇编语言的特点,选择相应的题目,在老师的指导下,由学生独立完成。课程设计要求同学们熟悉汇编语言的编程, BIOS 中断调用、系统功能调用、磁盘数据的查询、存取等相关知识。通过课程设计,一方面提高运用汇编语言编程解决实际问题的能力,另一方面使同学们更深入的了解计算机系统内部的有关知识,为以后的学习和系统开发奠定良好的基础。 1.2设计的意义通过课程设计要进一步锻炼同学们在微型计算机应用方面的实际工作能力。计算机科学在应用上得到飞速发展,因此,学习这方面的知识必须紧密联系实际:掌握这方面的知识更要强调解决实际问题的能力。同学们要着重学会面对一个实际问题,如何去自己收集资料,如何自己去学习新的知识,如何自己去制定解决问题的方案并通过实践不断地去分析和解决前进道路上的一切问题,最终到达胜利的彼岸。第二章设计任务 2.1课程设计的题目信号发生器软硬件设计: 以8088CPU 为核心设计一个信号发生器,系统可产生正弦波和三角波信号。 2.2设计的要求该设计由一个人选做并独自完成,要求画出电路原理图,说明工作原理,编写程序及程序流程图。 3 2.3设计的时间、地点时间: 2006 年7月3日?-7月14日地点: 11112 第三章总体设计方案 3.1对信号发生器的认识在我们日常生活中,以及一些科学研究中,锯齿波和正弦波、矩形波、三角波是常用的基本测试信号。此外,如在示波器、电视机等仪器中,为了使电子按照一定规律运动,以利用荧光屏显示图像,常用到锯齿波产生器作为时基电路。例如,要在示波器荧光屏上不失真地观察到被测信号波形,要求在水平偏转板加上随时间作线性变化的电压——锯齿波电压,使电子束沿水平方向匀速搜索荧光屏。而电视机中显像管荧光屏上的光点,是靠磁场变化进行偏转的,所以需要要用锯齿波电流来控制, 对于三角波,方波同样有这不可忽视的作用而函数发生器是指一般能自动产生方波正弦波三角波以及锯齿波阶梯波等电压波形的电路或仪器。因此信号发生器是我们在学习,科学研究等方面不可缺少的工具。此外,信号发生器在教学、试验、测控等各个领域有十分广泛的应用,其输出信号的频率范围覆盖了各个频段,从甚低频到甚高频, 操作方式也从手动旋钮到程控,产生的波形从传统的正(余)弦波和脉冲波形,发展到现在能产生各种任意波形。以前的信号发生器往往独占一个机箱,而现在的一些应用中,它只是一块插在计算机中的扩展卡,还有一些信号发生器设计成一个独立的小模块,通过 RS-232C 或RS-422 ,RS-485 等串行总线和计算机连接。今天我们要设计一种能产生正弦波和三角波的信号发生器。 3.2总体设计思路该设计包括硬件设计和软件设计两部分。 1.硬件是基于 PC 机的设计,设计要求以 8088CPU 为核心,通常采用 8284 时钟产生器为 CPU 提供时钟信号。由于计算机产生的是数字信号,而信号发生器产生的是模拟量,所以必须把数字量转化成模拟量,因此设计中用到的一个主要硬件便是 D/A 转换器。信号发生器产生的信号又要经过示波器显示才能让我们知道产生的是什么波形,所以经 D/A 转换器转换后的电量要经运算放大电路放大后才能在示波器上显 4 示连续的波形, 因此运算放大电路便成为连接 D/A 转换器和示波器的桥梁。 D/A 转换器的端口地址由片选端 CS 决定,因此,还需要译码器和一些逻辑门将 D/A 转换器的片选段和 8088CPU 连接起来。 2.至于 PC 机何时要它产生三角波,何时产生正弦波,何时退出,这就属于软件方面的设计了,通过编程产生三角波和正弦波,并控制波形的幅值和频率。三角波要分两段来产生,但因它的上升斜坡和下降斜坡都是线性关系,所以只要由数字量的增减来控制就可以了,产生上升斜坡时让输出值从零开始逐渐递增,其上升的最大值是从键盘输入的幅值,其频率是由输出点之间的延时来控制的;相反,产生下降斜坡时,让输出值从最大幅值逐渐递减到零。而正弦波是三角函数关系,通常可以用以下两种方法产生:(1)查表法:该方法的优点是速度快,但在精度高的情况下要求的存储器容量也要增大。此种方法应用在对精度要求不高的场合。(2)泰勒级数展开法:在某些时候这是一种比查表法更为有效的方法。与查表法相比,这种方法需要的存储单元很少,而且精度高。其泰勒级数展开式如下: sin(x)=x(1-(1/6)*x^2*(1-(1/20)*x^2*(1-(1/42)*x^2*(1-(1/72)*x^2)))) 由于时间的原因,本实验中采用查表法,造一张正弦数字量表,即查函数表得到的值转换成十六进制数填表。 D/A 转换取值范围为一个周期,采样点越多,精度越高,本实验中采样点为 256 点/ 周期。正弦数字量表中的值为参考值,对于不同幅值的正弦波可以通过把表中的每个值乘以相同的倍数得到,其频率由改变输出点之间的延时来实现。 3.原理框图信号发生器的原理框图如图 3.1 所示 5 时钟发生器 8088 CPU D/A 转换器运算放大电路键盘译码器示波器图3.1 信号发生器原理框图 3.3总体设计流程图 1.总体设计流程图如图 3.2 所示 2.关于流程图的说明: 程序从初始化开始,首先让指针指向提示信息一,即在屏幕上显示: PLEASE ENTER 1TOFORM SJB PLEASE ENTER 2TOFORM ZXB PLEASE ENTER 3TOEXIT! 当有键按下后,如果键是 1 ,则转向执行产生三角波的程序;如果键不是 1 ,则看键是否为 2。如果键是 2,则转向执行产生正弦波的程序;如果键也不是 2,则看是否为 3。如果是 3,则退出;如果也不是 3,则让指针指向信息 2,即显示信息提示所输入的键为无效键,并回到显示提示信息 1的地方,重新执行上述过程。产生三角波的过程:首先调用 AMPLITUDE 子程序提示输入幅值,并把值转换为二进制值,然后调用 CHANGE 子程序判断输入的值是否为规定范围内的值,并把满足条件的值转换为十六进制的值;接下来提示输入频率的过程与输入幅值的过程类似。在 6 显示提示等待有键按下键是1? 调用AMPLITUDE子程序输入幅值调用CHANGE子程序转化成十六进制调用FREQUENCY子程序输入频率调用CHANGE子程序转化成十六进制将AL置零将AL从端口输出调用DELAY子程序延时 AL加1 AL等于幅值? Al从端口输出 Y N调用DELAY子程序延时 Al减1 Al等于0? Y N有键按下? N 上升斜坡下降斜坡产生三角波 YN键是2? 调用AMPLITUDE子程序输入幅值调用CHANGE子程序转化成十六进制调用FREQUENCY子程序输入频率调用CHANGE子程序转化成十六进制 CX计数,BX指TABLE表首址 AL清零查表转换按相应的幅值输出调用DELAY子程序延时 BX指向表中下
内容来自淘豆网www.taodocs.com转载请标明出处.
文件大小:0 KB
下载次数:基于FPGA的视频信号发生器设计与应用研究-控制器/处理器-与非网
目前,对视频信号采集、记录和处理系统(、图像记录仪和电视跟踪系统等)的研究测试已经十分广泛。在对这些系统进行测试的过程中,需要测试者提供符合该系统输入制式要求的视频信号。针对多种被测系统及被测指标,测试者应该提供不同种类和制式的视频信号。以往对这些系统进行测试时,人们经常利用探测器对靶板进行成像,将产生的视频信号送入被测系统。该测试方法给系统评估引入两方面的误差:一是靶板的制作误差,二是探测器本身的成像质量偏差。针对这些误差,国内外逐渐使用能够提供模拟图像的来取代传统的测试装置[1-3].现场可编程门阵列()具有高集成度、高可靠性以及开发工具智能化等特点,目前逐步成为复杂数字电路设计的理想首选[ 4].考虑到视频信号时序要求严格以及硬件小型化的要求,选用FPGA来设计视频信号发生器,与其他设计方法相比,极大地缩短了开发周期,提高了测试精度。
系统由USB通信模块、FPGA控制模块、视频D/A模块和输出接口模块组成。硬件组成如图1所示。
1. 1工作原理
上位机经过USB总线与FPGA进行通信,将模拟目标或靶板的信息以及其他控制信号传送给FPGA.FPGA对接收到的数据进行判断和计算,最后输出具有时序关系的数字信号。如果系统需要输出模拟视频信号,那么将数字信号送入视频D/A转换电路,输出与被测系统制式相符的视频信号;如果被测系统接收数字信号,那么将数字信号进行调理后,直接送入被测系统。
1. 2与上位机通信方式的选择
以前我们开发的视频信号发生器选择了串口通信的方式与上位机进行数据传输,该通信方式具有开发简单,成本低的特点。但是在使用过程中发现了以下问题:一是不支持热插拔,接上视频信号发生器后,主机需要重新启动;二是需要为视频信号发生器单独提供电源;三是数据传输慢,不利于系统的扩展。
针对以上问题,决定采用USB通信的方式。USB接口具有热插拔、传输速度快以及便携等特点[5] ,能够完全满足本系统的设计要求。当本系统接入PC的USB接口时, PC将固件自动下载到USB接口芯片中,测试者只需要操作PC机上的应用程序界面,就可以完成相关的测试工作。此外, USB接口提供的+5V电源,它的电流可以达到几百mA,完全可以驱动系统进行正常工作(软件仿真得到FPGA模块在生成某种视频信号时的功耗为100 mW左右),省去了系统供电电源的设计工作,这样缩小了系统体积,提高了系统的便携性能。
1. 3 FPGA控制模块FPGA控制模块是整个系统的核心。
以生成标准CCIR制式视频信号为例来介绍该模块的设计方法。根据CCIR制式的电视信号标准,它采用隔行扫描的方式,每场312.5行,行频15 625 Hz,场频50 H z,水平有效像素点768,垂直有效像素点575.由于采用了隔行扫描的方式,视频信号中就必须包含前后均衡脉冲。再加上场同步中的开槽脉冲,这些脉冲信号的引入会提高输出视频图像的质量,因此模拟该类信号是该模块设计的关键。
由于CC IR制式视频信号属于模拟信号,所以FPGA输出的数据以及控制信号需要进入D /A转换电路。这里选用了AD公司的3路10位视频D/A芯片,该芯片的输入端是复合同步信号、复合消隐信号、时钟信号、3路(R、G、B)图像数据信号以及其他控制信号,最后输出3路模拟视频信号。
因此, FPGA控制模块需要为视频D/A转换模块提供以上所需的输入信号。本文采用了模块化的设计方法,利用Verilog硬件描述语言生成各种子模块,再将这些子模块进行顶层的连接,最后输出图像数据及控制信号。模块的总体结构如图2所示。
在设计各子模块的过程中,充分利用了FPGA设计软件时序仿真的功能,这给调试以及选取最优模块带来极大的方便。图3是利用M odelSmi SE 6. 0软件仿真出的开槽脉冲、均衡脉冲、行同步、行消隐和场消隐子模块时序图。
图中, kcmc是开槽脉冲模块,其中高电平时间是4.7&s,低电平时间为27.3&s; jhmc代表前后均衡脉冲模块,高电平29.65&s,低电平2.35&s;hsyn代表了行同步脉冲模块,周期64&s,同步脉冲宽度4.7&s,前肩1.5&s,后肩5.8&s; hblnk是行消隐信号模块,消隐脉冲宽度12&s.在本系统中,利用FPGA的下载配置软件生成系统的配置文件(MCS格式),然后经JTAG口将配置文件下载到FPGA控制模块的PROM中。当系统每次加电后,PROM将其存储的文件配置到FPGA中, FPGA开始正常工作,实现相应的功能。针对这个特点,可以根据测试需要随时更新配置文件,完成不同种类被测系统的测试工作,使测试工作更具有灵活性。
1. 4视频D/A转换模块
将系统输出的标准和非标准模拟视频信号进行比较,发现它们有类似的地方,即都包含同步信号,而且对同步信号电平有特定的要求。标准视频信号中要求同步电平比消隐电平低0. 3 V,某型装备输出的非标准视频信号要求同步电平严格控制在- 0. 3 V.同步电平的这些特性就要求设计者必须合理选择视频D /A转换芯片。
在本系统中选取了AD公司的三路10位视频D/A芯片。只要对该芯片的输入端(复合同步、消隐信号、时钟信号,数据信号等)进行编程,系统就可以输出不同制式的模拟视频信号。表1是本系统设计采用的视频输出真值表[6].
根据该真值表,利用FPGA严格控制它们的时序关系,就可以产生多种制式的模拟视频信号,该方法增强了视频信号发生器的扩展性和通用性。视频D /A转换电路板及同轴电缆输出接口实物如图4所示。
2系统在电视跟踪性能检测中的应用研究
2.1 电视跟踪性能指标和检测方法
电视跟踪箱是电视跟踪系统中实现跟踪和搜索的关键部分。传统的电视跟踪箱跟踪性能测试采用的是室内标志法和机械靶标法等,这些测试方法中提供的模拟目标具有精度低和可控性差的缺点[7].后来出现了基于ISA总线的模拟目标卡,但是该卡使用时必须插在PC的插槽上,同时该测试仪器的体积较大,而且扩展性不好。
可以利用基于FPGA的视频信号发生器完成电视跟踪性能的检测。
最小跟踪目标、最小跟踪对比度、跟踪速度、目标捕获概率等是评价电视跟踪箱跟踪性能的重要指标[ 8].针对这些指标,要求本视频信号发生器输出的模拟目标,在速度、运动方式、对比度、视场中位置和大小上具有可控的功能。
以最小跟踪目标测试来说明该功能的实现方法。最小跟踪目标测试要求模拟目标是运动目标,测试过程中,测试者通过改变模拟目标的大小来观察波门的跟踪或搜索状态,从而判断出最小跟踪目标大小。因此,需要在FPGA内部通过一定的算法来满足测试系统对模拟目标提出的要求。图5是本项测试中水平往返运动目标生成的算法流程图。
2.2 测试结果分析运用
该视频信号发生器对某型电视跟踪系统电视跟踪箱进行跟踪性能测试,测试时将视频信号发生器与被测电视跟踪箱连接,然后设定被测装备的某些工作参数,最后获得了该装备的部分跟踪性能参数。测试结果如表2所示。从跟踪性能测试结果中可以看出,最小跟踪目标在3 @ 3~ 4 @ 4像素之间,最小跟踪对比度在3% ~ 4%之间,水平最大跟踪速度在4. 22~ 4. 24视场/秒之间,捕获概率始终为100% ,它们的变化幅度始终都控制在设计要求的范围内。
同时,使用一台标定后的某型电视跟踪检测仪对被测电视跟踪箱进行测试,得到的测试结果基本与表2中的相吻合,从而验证了本视频信号发生器的工作可靠性。
图6和图7是在测试前将本视频信号发生器接入某图像采集卡获取的模拟目标图像。
基于FPGA的视频信号发生器可以满足多种被测视频输入系统对视频信号制式的要求。它采用USB技术完成与上位机的通信,解决了工作电源的问题,提高了该系统的通用性和扩展性。将该视频信号发生器应用在某型电视跟踪系统电视跟踪箱的跟踪性能测试中,获得了该装备的部分电视跟踪性能参数,通过分析实验数据,证明了该系统具有测试精度高、工作稳定性好的特点。可以说该视频信号发生器能够为准确评估装备的战斗性能提供必要的技术保障。今后,可以对该系统进行扩展,将它应用在更多的测试领域中,所以其应用前景十分广泛。
关注与非网微信 ( ee-focus )
限量版产业观察、行业动态、技术大餐每日推荐
享受快时代的精品慢阅读
致力于在功耗、安全、可靠性和性能方面提供差异化的领先半导体技术方案供应商美高森美公司(Microsemi Corporation,纽约纳斯达克交易所代号:MSCC)宣布其成本优化最低功耗中等规模PolarFire(R)可编程逻辑器件(FPGA)产品荣获《今日电子》(EPC) 杂志和21ic.com 网站的 “2017年度产品奖”。
发表于: 16:43:06
中国广州,日,由全球电子产业媒体集团AspenCore旗下《电子工程专辑》、《EDN电子技术设计》和《国际电子商情》共同举办的“2018年度中国IC设计奖”颁奖晚宴于上海龙之梦万丽酒店隆重拉开帷幕。
发表于: 16:34:25
先声明几件事,我在大学做科研工作,这次流片主要工作是在13年,做的是可自我修复软硬错误的FPGA芯片,TSMC 65nm制程,最终结果是成功的。
发表于: 15:24:01
Zynq这个词很容易让人联想到zinc,也就是电池、日光屏、合金制品和药品中最常见的化学元素锌。锌与其他金属的合金可实现增强型功能,根据合金的不同对象表现为不同的色彩。锌最常见的用途就是电镀。那么这个名称与电镀之间有什么联系?
发表于: 14:01:49
有鉴于大陆集成电路设计产业进入快速发展时期,由市场到核“芯”突破这一关卡不断力求超越,全国包括北京、上海、深圳、南京、 杭州、西安、厦门等七个城市获批“芯火”双创基地(平台)建设专案。
发表于: 10:16:05
随着3D大型游戏的普及,游戏玩家在追求场景逼真的同时,也同样需要电脑提升反应速度,从而进一步提升游戏体验,而对于视频场景制作方来说,只有更快的处理器才能满足快速实现场景制作的需求。
发表于: 17:58:38
根据集邦咨询半导体研究中心(DRAMeXchange)调查,以标准型内存主流产品DDR4 4GB来看,3月均价维持在33美元,高价约34美元,整体而言,第一季标准型内存价格较去年第四季上涨约5%;第二季受到台湾美光(原瑞晶厂)氮气事件影响,导致DRAM市场供给吃紧的情况延续,预估第二季标准型内存合约价将再上扬约3%。
发表于: 16:49:17
意法半导体的X-CUBE-AVS软件包让亚马逊的Alexa语音服务(AVS)能够运行在STM32*微控制器上,使具有云智能功能(自动语音识别和自然语言理解)的高级会话用户界面出现在简单的物联网设备上,例如,智能家电、家庭自动化设备和办公设备。
发表于: 16:31:35
英特尔在北京举办全球发布会,隆重推出了其首款面向笔记本电脑的英特尔(R) 酷睿(TM) i9 处理器。在相继亮相的一系列全新高性能移动产品中,功能强大的第八代智能英特尔酷睿i9处理器备受瞩目,它是英特尔史上超高性能的笔记本电脑处理器,能够随时随地为用户提供极致的游戏和内容创作体验。
发表于: 16:29:31
GPU是替代不了CPU的,同样,CPU也替代不了GPU。如果形象点理解,GPU就像一群蚂蚁,这些蚂蚁都做着同样的事,而CPU就像一只猴子,这只猴子做着各种不同的事。
发表于: 16:23:44
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号查看: 10526|回复: 8
第17章 A/D和D/A的学习
本教材现以连载的方式由网络发布,并将于2014年由清华大学出版社出版最终完整版,版权归作者和清华大学出版社所有。本着开源、分享的理念,本教材可以自由传播及学习使用,但是务必请注明出处来自金沙滩工作室
从我们学到的知识了解到,我们的单片机是一个典型的数字系统。数字系统只能对输入的数字信号进行处理,其输出信号也是数字信号。但是在工业检测系统和日常生活中的许多物理量都是模拟量,比如温度、长度、压力、速度等等,这些模拟量可以通过传感器变成与之对应的电压、电流等电模拟量。为了实现数字系统对这些电模拟量的检测、运算和控制,就需要一个模拟量和数字量之间相互转换的过程。这节课我们就要学习这个相互转换过程。
17.1 A/D和D/A的基本概念
A/D是模拟量到数字量的转换,依靠的是模数转换器(Analog to Digital Converter),简称ADC;D/A是数字量到模拟量的转换,依靠的是数模转换器(Digital to Analog Converter),简称DAC。他们的道理是完全一样的,只是转换方向不同,因此我们讲解过程主要以A/D为例来讲解。很多同学学到A/D这部分的时候,感觉是个难点,概念掌握不清楚。我个人认为主要原因不在于技术问题,而是不太会感悟生活。我们生活中有很多很多A/D的例子,只是没有在单片机领域里应用而已,下面我带着大家一起感悟一下A/D的概念。什么是模拟量?就是指变量在一定范围内连续变化的量,也就是在一定范围内可以取任意值。比如我们米尺,从0到1米之间,可以是任意值。什么是任意值,也就是可以是1cm,也可以是1.001cm,当然也可以10.000......后边有无限个小数。总之,任何两个数字之间都有无限个中间值,所以称之为连续变化的量,也就是模拟量。而我们用的米尺上被我们人为的做上了刻度符号,每两个刻度之间的间隔是1mm,这个刻度实际上就是我们对模拟量的数字化,由于有一定的间隔,不是连续的,所以在专业领域里我们称之为离散的。我们的ADC就是起到把连续的信号用离散的数字表达出来的作用。那么我们就可以使用米尺这个“ADC”来测量连续的长度或者高度这些模拟量。如图17-1一个简单的米尺刻度示意图。
ps5b153.jpg (11.1 KB, 下载次数: 94)
23:50 上传
图17-1 米尺刻度示意图我们往杯子里倒水,水位会随着倒入的水量的多少而变化。现在就用这个米尺来测量我们杯子里的水位的高度。水位变化是连续的,而我们只能通过尺子上的刻度来读取水位的高度,获取我们想得到的水位的数字量信息。这个过程,就可以简单理解为我们电路中的ADC采样。
17.2 A/D的主要指标
我们在选取和使用A/D的时候,依靠什么指标来判断很重要。由于AD的种类很多,分为积分型、逐次逼近型、并行/串行比较型、Σ-Δ型等多种类型。同时指标也比较多,并且有的指标还有轻微差别,具体可上查询.在这里我是以同学们便于理解的方法去讲解,如果和某一确定类型A/D概念和原理有差别,也不会影响实际应用。1、ADC的位数。一个n位的ADC表示这个ADC共有2的n次方个刻度。8位的ADC,输出的是从0到255一共256个数字量,也就是2的8次方个数据刻度。2、基准源基准源,也叫基准电压,是ADC的一个重要指标,要想把输入ADC的信号测量准确,那么基准源首先要准,基准源的偏差会直接导致转换结果的偏差。比如一根米尺,总长度本应该是1米,假定这根米尺被火烤了一下,实际变成了1.2米,再用这根米尺测物体长度的话自然就有了较大的偏差。假如我们的基准源应该是5.10V,但是实际上提供的却是4.5V,这样误把4.5V当成了5.10V来处理的话,偏差也会比较大。3、分辨率分辨率是数字量变化一个最小刻度时,模拟信号的变化量,定义为满刻度量程与2n-1的比值。5.10V的电压系统,使用8位的ADC进行测量,那么相当于0到255一共256个刻度,把5.10V平均分成了255份,那么分辨率就是5.10/255 = 0.02V。4、INL(积分非线性度)和DNL(差分非线性度)初学者最容易混淆的两个概念就是“分辨率”和“精度”,认为分辨率越高,则精度越高,而实际上,两者之间是没有必然联系的。分辨率是用来描述刻度划分的,而精度是用来描述准确程度的。同样一根米尺,刻度数相同,分辨率就相当,但是精度却可以相差很大,如图17-2所示。
ps5b154.jpg (10.9 KB, 下载次数: 115)
23:50 上传
图17-2 米尺精度对比图17-2表示的精度一目了然,不需多说。和ADC精度关系重大的两个指标是INL(Integral NonLiner)和DNL(Differencial NonLiner)。INL指的是ADC器件在所有的数值上对应的模拟值,和真实值之间误差最大的那一个点的误差值,是ADC最重要的一个精度指标,单位是LSB。LSB(Least Significant Bit)是最低有效位的意思,那么它实际上对应的就是ADC的分辨率。一个基准为5.10V的8位ADC,它的分辨率就是0.02V,用它去测量一个电压信号,得到的结果是100,就表示它测到的电压值是100*0.02V=2V,假定它的INL是1LSB,就表示这个电压信号真实的准确值是在1.98V~2.02V之间的,按理想情况对应得到的数字应该是99~101,测量误差是一个最低有效位,即1LSB。DNL表示的是ADC相邻两个刻度之间最大的差异,单位是LSB。一把分辨率是1毫米的尺子,相邻的刻度之间并不都刚好是1毫米,而总是会存在或大或小的误差。同理,一个ADC的两个刻度线之间也不总是准确的等于分辨率,也是存在误差,这个误差就是DNL。一个基准为5.10V的8位ADC,假定它的DNL是0.5LSB,那么当它的转换结果从100增加到101时,理想情况下实际电压应该增加0.02V,但DNL为0.5LSB的情况下实际电压的增加值是在0.01~0.03之间。值得一提的是DNL并非一定小于1LSB,很多时候它会等于或大于1LSB,这就相当于是一定程度上的刻度紊乱,当实际电压保持不变时,ADC得出的结果可能会在几个数值之间跳动,很大程度上就是由于这个原因(但并不完全是,因为还有无时无处不在的干扰的影响)。5、转换速率转换速率,是指ADC每秒能进行采样转换的最大次数,单位是sps(或s/s、sa/s,即samples per second),它与ADC完成一次从模拟到数字的转换所需要的时间互为倒数关系。ADC的种类比较多,其中积分型的ADC转换时间是毫秒级的,属于低速ADC;逐次逼近型ADC转换时间是微妙级的,属于中速ADC;并行/串行的ADC的转换时间可达到纳秒级,属于高速ADC。ADC的这几个主要指标大家先熟悉一下,对于其他的,作为一个入门级别的选手来说,先不着急深入理解。以后使用过程中遇到了,再查找相关资料深入学习,当前重点是在头脑中建立一个ADC的基本概念。
17.3 PCF8591的硬件接口
PCF8591是一个单电源低功耗的8位CMOS数据采集器件,具有4路模拟输入,1路模拟输出和一个串行I2C总线接口用来与MCU通信。3个地址引脚A0、A1、A2用于编程硬件地址,允许最多8个器件连接到I2C总线而不需要额外的片选电路。器件的地址、控制以及数据都是通过I2C总线来传输,我们先看一下PCF8591的原理图,如图17-3所示。
ps5b155.jpg (44.33 KB, 下载次数: 118)
23:50 上传
图17-3 PCF8591原理图其中引脚1、2、3、4是4路模拟输入,引脚5、6、7是I2C总线的硬件地址,8脚是数字GND,9脚和10脚是I2C总线的SDA和SCL。12脚是时钟选择引脚,如果接高电平表示用外部时钟输入,接低电平则用内部时钟,我们这套电路用的是内部时钟,因此12脚直接接GND,同时11脚悬空。13脚是模拟GND,在实际开发中,如果有比较复杂的模拟电路,那么模拟GND部分在布局布线上要特别处理,而且和数字GND的连接也有多种方式,这里大家先了解即可。在我们板子上没有复杂的模拟部分电路,所以我们把模拟的GND和数字GND接到一起即可。14脚是基准源,15脚是DAC的模拟输出,16脚是供电电源VCC。 PCF8591的ADC是逐次逼近型的,转换速率算是中速,但是他的速度瓶颈在I2C通信上。由于I2C通信速度较慢,所以最终的PCF8591的转换速度,直接取决于I2C的通信速率。由于I2C速度的限制,所以PCF8591的算是个低速的AD和DA集成,主要应用在一些转换速度要求不高,希望成本较低的场合,比如电池供电设备,测量电池的供电电压,电压低于某一个值,报警提示更换电池等类似场合。Vref基准电压的提供,方法一是采用简易的原则,直接接到VCC上去。但是由于VCC会受到整个线路的用电功耗情况影响,一来不是准确的5V,实测大多在4.8V左右,二来随着整个系统负载情况的变化会产生波动,所以只能用在简易的、对精度要求不高的场合。方法二是使用专门的基准电压器件,比如TL431,它可以提供一个精度很高的2.5V的电压基准,这是我们通常采用的方法。如图17-4所示。
ps5b156.jpg (50.86 KB, 下载次数: 102)
23:50 上传
图17-4 PCF8591电路图图中J17是双排插针,大家可以根据自己的需求选择跳线帽短接还是使用杜邦线接其他外接电路,都是可以的。在这个地方,我们直接把J17的3脚和4脚用跳线帽短路起来,那么现在Vref的基准源就是2.5V了。分别把5和6、7和8、9和10、11和12用跳线帽短接起来的话,那么我们的AIN0实测的就是滑动变阻器的分压值,AIN1和AIN2测的是GND的值,AIN3测的是+5V的值。这里需要注意的是,AIN3虽然测的是+5V的值,但是对于AD来说,只要输入信号超过Vref基准源,它得到的始终都是最大值,即255,也就是说它实际上无法测量超过其Vref的电压信号。需要注意的是,所有输入信号的电压值都不能超过VCC,即+5V,否则可能会损坏ADC芯片。
17.4 PCF8591的软件编程
PCF8591的通信接口是I2C,那么编程肯定是符合这个协议的。单片机对PCF8591进行初始化,一共发送三个字节即可。第一个字节,和EEPROM类似,第一个字节是地址字节,其中7位代表地址,1位代表读写方向。地址高4位固定是1001,低三位是A2,A1,A0,这三位我们电路上都接了GND,因此也就是000,如图17-5所示。
ps5b157.jpg (11.65 KB, 下载次数: 102)
23:50 上传
图17-5 PCF8591地址字节发送到PCF8591的第二个字节将被存储在控制寄存器,用于控制PCF8591的功能。其中第3位和第7位是固定的0,另外6位各自有各自的作用,如图17-6所示,我逐一介绍。
ps5b158.jpg (4.17 KB, 下载次数: 125)
23:50 上传
图17-6 PCF8591控制字节控制字节的第6位是DA使能位,这一位置1表示DA输出引脚使能,会产生模拟电压输出功能。第4位和第5位可以实现把PCF8591的4路模拟输入配置成单端模式和差分模式,单端模式和差分模式的区别,我们17.4章节有介绍,这里大家只需要知道这两位是配置AD输入方式的控制位即可,如图17-7所示。
ps5b159.jpg (23.12 KB, 下载次数: 109)
23:50 上传
图17-7 PCF8591模拟输入配置方式
控制字节的第2位是自动增量控制位,自动增量的意思就是,比如我们一共有4个通道,当我们全部使用的时候,读完了通道0,下一次再读,会自动进入通道1进行读取,不需要我们指定下一个通道,由于A/D每次读到的数据,都是上一次的转换结果,所以同学们在使用自动增量功能的时候,要特别注意,当前读到的是上一个通道的值。为了保持程序的通用性,我们的代码没有使用这个功能,直接做了一个通用的程序。控制字节的第0位和第1位就是通道选择位了,00、01、10、11代表了从0到3的一共4个通道选择。发送给PCF8591的第三个字节D/A数据寄存器,表示D/A模拟输出的电压值。D/A模拟我们一会介绍,大家知道这个字节的作用即可。我们如果仅仅使用A/D功能的话,就可以不发送第三个字节。下面我们用一个程序,把AIN0、AIN1、AIN3测到的电压值显示在液晶上,同时大家可以转动电位器,会发现AIN0的值发生变化。/***********************lcd1602.c文件程序源代码*************************/#include &reg52.h&
#define LCD1602_DB& &P0
sbit LCD1602_RS = P1^0;sbit LCD1602_RW = P1^1;sbit LCD1602_E&&= P1^5;
void LcdWaitReady()&&//等待液晶准备好{& &
& & LCD1602_DB = 0xFF;& & LCD1602_RS = 0;& & LCD1602_RW = 1;& & do& & {& && &&&LCD1602_E = 1;& && &&&sta = LCD1602_DB; //读取状态字& && &&&LCD1602_E = 0;& & } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止}void LcdWriteCmd(unsigned char cmd)&&//写入命令函数{& & LcdWaitReady();& & LCD1602_RS = 0;& & LCD1602_RW = 0;& & LCD1602_DB =& & LCD1602_E&&= 1;& & LCD1602_E&&= 0;}void LcdWriteDat(unsigned char dat)&&//写入数据函数{& & LcdWaitReady();& & LCD1602_RS = 1;& & LCD1602_RW = 0;& & LCD1602_DB =& & LCD1602_E&&= 1;& & LCD1602_E&&= 0;}void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str)&&//显示字符串,屏幕起始坐标(x,y),字符串指针str{& &
& & //由输入的显示坐标计算显示RAM的地址& & if (y == 0)& && &&&addr = 0x00 + //第一行字符地址从0x00起始& & else& && &&&addr = 0x40 + //第二行字符地址从0x40起始
& & //由起始显示RAM地址连续写入字符串& & LcdWriteCmd(addr | 0x80); //写入起始地址& & while (*str != '\0')& && &//连续写入字符串数据,直到检测到结束符& & {& && &&&LcdWriteDat(*str);& && &&&str++;& & }}void LcdInit()&&//液晶初始化函数{& & LcdWriteCmd(0x38);&&//16*2显示,5*7点阵,8位数据接口& & LcdWriteCmd(0x0C);&&//显示器开,光标关闭& & LcdWriteCmd(0x06);&&//文字不动,地址自动+1& & LcdWriteCmd(0x01);&&//清屏}/***********************I2C.c文件程序源代码*************************/#include &reg52.h&#include &intrins.h&
#define I2CDelay()&&{_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;sbit I2C_SDA = P3^6;
void I2CStart()&&//产生总线起始信号{& & I2C_SDA = 1; //首先确保SDA、SCL都是高电平& & I2C_SCL = 1;& & I2CDelay();& & I2C_SDA = 0; //先拉低SDA& & I2CDelay();& & I2C_SCL = 0; //再拉低SCL}void I2CStop()& &//产生总线停止信号{& & I2C_SCL = 0; //首先确保SDA、SCL都是低电平& & I2C_SDA = 0;& & I2CDelay();& & I2C_SCL = 1; //先拉高SCL& & I2CDelay();& & I2C_SDA = 1; //再拉高SDA& & I2CDelay();}bit I2CWrite(unsigned char dat) //I2C总线写操作,待写入字节dat,返回值为应答状态{& &&&//用于暂存应答位的值& &&&//用于探测字节内某一位值的掩码变量
& & for (mask=0x80; mask!=0; mask&&=1) //从高位到低位依次进行& & {& && &&&if ((mask&dat) == 0)&&//该位的值输出到SDA上& && && && &I2C_SDA = 0;& && &&&else& && && && &I2C_SDA = 1;& && &&&I2CDelay();& && &&&I2C_SCL = 1;& && && & //拉高SCL& && &&&I2CDelay();& && &&&I2C_SCL = 0;& && && & //再拉低SCL,完成一个位周期& & }& & I2C_SDA = 1;& &//8位数据发送完后,主机释放SDA,以检测从机应答& & I2CDelay();& & I2C_SCL = 1;& &//拉高SCL& & ack = I2C_SDA; //读取此时的SDA值,即为从机的应答值& & I2CDelay();& & I2C_SCL = 0;& &//再拉低SCL完成应答位,并保持住总线
& & return (~ack); //应答值取反以符合通常的逻辑:0=不存在或忙或写入失败,1=存在且空闲或写入成功}unsigned char I2CReadNAK() //I2C总线读操作,并发送非应答信号,返回值为读到的字节{& && &
& & I2C_SDA = 1;&&//首先确保主机释放SDA& & for (mask=0x80; mask!=0; mask&&=1) //从高位到低位依次进行& & {& && &&&I2CDelay();& && &&&I2C_SCL = 1;& && &//拉高SCL& && &&&if(I2C_SDA == 0)&&//读取SDA的值& && && && &dat &= ~ //为0时,dat中对应位清零& && &&&else& && && && &dat |=&&//为1时,dat中对应位置1& && &&&I2CDelay();& && &&&I2C_SCL = 0;& && &//再拉低SCL,以使从机发送出下一位& & }& & I2C_SDA = 1;& &//8位数据发送完后,拉高SDA,发送非应答信号& & I2CDelay();& & I2C_SCL = 1;& &//拉高SCL& & I2CDelay();& & I2C_SCL = 0;& &//再拉低SCL完成非应答位,并保持住总线
& &}unsigned char I2CReadACK() //I2C总线读操作,并发送应答信号,返回值为读到的字节{& && &
& & I2C_SDA = 1;&&//首先确保主机释放SDA& & for (mask=0x80; mask!=0; mask&&=1) //从高位到低位依次进行& & {& && &&&I2CDelay();& && &&&I2C_SCL = 1;& && &//拉高SCL& && &&&if(I2C_SDA == 0)&&//读取SDA的值& && && && &dat &= ~ //为0时,dat中对应位清零& && &&&else& && && && &dat |=&&//为1时,dat中对应位置1& && &&&I2CDelay();& && &&&I2C_SCL = 0;& && &//再拉低SCL,以使从机发送出下一位& & }& & I2C_SDA = 0;& &//8位数据发送完后,拉低SDA,发送应答信号& & I2CDelay();& & I2C_SCL = 1;& &//拉高SCL& & I2CDelay();& & I2C_SCL = 0;& &//再拉低SCL完成应答位,并保持住总线
& &}/***********************main.c文件程序源代码*************************/#include &reg52.h&
bit flag300ms = 1;& && & //300ms定时标志unsigned char T0RH = 0;&&//T0重载值的高字节unsigned char T0RL = 0;&&//T0重载值的低字节
unsigned char GetADCValue(unsigned char chn);void ValueToString(unsigned char *str, unsigned char val);void ConfigTimer0(unsigned int ms);extern void LcdInit();extern void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str);extern void I2CStart();extern void I2CStop();extern unsigned char I2CReadACK();extern unsigned char I2CReadNAK();extern bit I2CWrite(unsigned char dat);
void main (){& && & unsigned char str[10];
& & EA = 1;& && && &&&//开总中断& & ConfigTimer0(10); //配置T0定时10ms& & LcdInit();& && &&&//初始化液晶& & & & LcdShowStr(0, 0, &AIN0&&AIN1&&AIN3&);&&//显示通道指示
& & while(1)& & {& && &&&if (flag300ms)& && &&&{& && && && &flag300ms = 0;& && && && &//显示通道0的电压& && && && &val = GetADCValue(0);& &&&//获取ADC通道0的转换值& && && && &ValueToString(str, val);&&//转为字符串格式的电压值& && && && &LcdShowStr(0, 1, str);& & //显示到液晶上& && && && &//显示通道1的电压& && && && &val = GetADCValue(1);& && && && &ValueToString(str, val);& && && && &LcdShowStr(6, 1, str);& && && && &//显示通道3的电压& && && && &val = GetADCValue(3);& && && && &ValueToString(str, val);& && && && &LcdShowStr(12, 1, str);& && &&&}& & }}
unsigned char GetADCValue(unsigned char chn)&&//读取当前的ADC转换值,chn为ADC通道号0-3{& &
& && && && && && &&&I2CStart();& && && && &if (!I2CWrite(0x48&&1))& &//寻址PCF8591,如未应答,则停止操作并返回0& & {& && && && && & I2CStop();& && && && && && && && &return 0;& && && && &}& & I2CWrite(0x40|chn);& && & //写入控制字节,选择转换通道& & I2CStart();& & I2CWrite((0x48&&1)|0x01); //寻址PCF8591,指定后续为读操作& & & && && && &I2CReadACK();& && && && & //先空读一个字节,提供采样转换时间& && && && &val = I2CReadNAK();& && & //读取刚刚转换完的值& && && && &I2CStop();
& &}void ValueToString(unsigned char *str, unsigned char val)&&//ADC转换值转为实际电压值的字符串形式{& & val = (val*25) / 255;& & //电压值=转换结果*2.5V/255,式中的25隐含了一位十进制小数& & str[0] = (val/10) + '0'; //整数位字符& & str[1] = '.';& && && && &//小数点& & str[2] = (val%10) + '0'; //小数位字符& & str[3] = 'V';& && && && &//电压单位& & str[4] = '\0';& && && &&&//结束符}
void ConfigTimer0(unsigned int ms)&&//T0配置函数{& &
/ 12;& && &//定时器计数频率& & tmp = (tmp * ms) / 1000;&&//计算所需的计数值& & tmp = 65536 -& && &&&//计算定时器重载值& & tmp = tmp + 12;& && && &&&//修正中断响应延时造成的误差
& & T0RH = (unsigned char)(tmp && 8);&&//定时器重载值拆分为高低字节& & T0RL = (unsigned char)& & TMOD &= 0xF0;& &//清零T0的控制位& & TMOD |= 0x01;& &//配置T0为模式1& & TH0 = T0RH;& &&&//加载T0重载值& & TL0 = T0RL;& & ET0 = 1;& && &&&//使能T0中断& & TR0 = 1;& && &&&//启动T0}void InterruptTimer0() interrupt 1&&//T0中断服务函数{& & static unsigned char tmr300ms = 0;
& & TH0 = T0RH;&&//定时器重新加载重载值& & TL0 = T0RL;& & tmr300ms++;& & if (tmr300ms &= 30)&&//定时300ms& & {& && &&&tmr300ms = 0;& && &&&flag300ms = 1;& & }}& & 细心阅读程序的同学会发现,我们程序在进行A/D读取数据的时候,共使用了两条程序去读了2个字节。I2CReadACK();& && &&&val = I2CReadNAK();PCF8591的转换时钟是I2C的SCL,而A/D的特点是每次读到的都是上一次的转换结果,因此我们这里第一条语句的作用是产生一个整体的SCL时钟提供给PCF8591进行A/D转换,第二次是读取当前的转换结果。如果我们只使用第二条语句的话,每次读到的都是上一次的转换结果。
17.5 A/D差分输入信号
细心的同学在阅读PCF8591手册的时候,会发现控制字的第4位和第5位是用于控制PCF8591的模拟输入引脚是单端输入还是差分输入。差分输入是模拟电路常用的一个技巧,这里我们简单介绍一些相关内容。从严格意义上来讲,所有的信号都是差分信号,因为所有的电压只能是相对于另外一个电压而言。但是大多数系统,我们都是把系统的GND作为基准点。而对于A/D来说的差分输入,通常情况下是除了GND以外,另外两路幅度相同,极性相反的差分输入信号,其实理解起来很简单,就如同我们的跷跷板一样。如图17-8所示。
ps5b120.jpg (18.6 KB, 下载次数: 106)
23:52 上传
图17-8 差分输入原理差分输入的话,就不是单个输入,而是由2个输入端构成的一组差分输入。我们的PCF8591一共是4个模拟输入端,可以配置成4种模式,最典型的是4个输入端构造成的两路差分模式,如图17-9所示。
ps5b121.jpg (8.56 KB, 下载次数: 97)
23:52 上传
图17-9 PCF8591差分输入模式当控制字的第4位和第5位都是1的时候,那么4路模拟被配置成2路差分模式输入channel 0和channel 1。我们以channel 0为例,其中AIN0是正向输入端,AIN1是反向输入端,他们之间的信号输入是幅度相同,极性相反的信号,通过减法器后,得到的是两个输入通道的差值,如图17-10所示。
ps5b122.jpg (48.66 KB, 下载次数: 94)
23:52 上传
图17-10 差分输入信号通常情况下,差分输入的中线是基准电压的一半,我们的基准电压是2.5V,假如1.25V作为中线,V+是AIN0的输入波形,V-是AIN1的输入波形,Signal Value就是经过减法器后的波形。很多A/D都采用差分的方式输入,因为差分输入方式比单端输入来说,有很强的抗干扰能力。1、单端输入信号时,如果一线上发生干扰变化,比如幅度增大5mv,GND不变,测到的数据会有偏差;而差分信号输入时,当外界存在干扰信号时,几乎同时被耦合到两条线上,幅度增大5mv会同时增大5mv,而接收端关心的只是两个信号的差值,所以外界的这种共模噪声可以被完全抵消掉。2、由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,有效的抑制释放到外界的电磁能量。在我们的KST-51开发板上,我们没有做差分信号输入的实验环境,由于这个内容在A/D部分比较重要,所以大家还是要学习一下的。
17.6 D/A输出
D/A是和A/D刚好反方向,一个8位的D/A,从0到255,代表了0到2.55V的话,那么我们用单片机给第三个字节发送100,D/A引脚就会输出一个1V的电压,发送200就输出一个2V的电压,很简单,我们用一个简单的程序实现出来,并且通过上、下按键可以增大输出幅度值,每次增加或减小0.1V。如果有万用表的话,可以直接测试一下板子上AOUT点的输出电压,观察它的变化。由于PCF8591的偏置误差最大是50mv(由数据手册提供),所以我们用万用表测到的电压值和理论值之间的误差就应该在50mV以内。/***********************I2C.c文件程序源代码*************************/& && && && && && && && &&&略/***********************keyboard.c文件程序源代码*************************/#include &reg52.h&
sbit KEY_IN_1&&= P2^4;&&//矩阵按键的扫描输入引脚1sbit KEY_IN_2&&= P2^5;&&//矩阵按键的扫描输入引脚2sbit KEY_IN_3&&= P2^6;&&//矩阵按键的扫描输入引脚3sbit KEY_IN_4&&= P2^7;&&//矩阵按键的扫描输入引脚4sbit KEY_OUT_1 = P2^3;&&//矩阵按键的扫描输出引脚1sbit KEY_OUT_2 = P2^2;&&//矩阵按键的扫描输出引脚2sbit KEY_OUT_3 = P2^1;&&//矩阵按键的扫描输出引脚3sbit KEY_OUT_4 = P2^0;&&//矩阵按键的扫描输出引脚4
const unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到PC标准键盘键码的映射表& & { '1',&&'2',&&'3', 0x26 }, //数字键1、数字键2、数字键3、向上键& & { '4',&&'5',&&'6', 0x25 }, //数字键4、数字键5、数字键6、向左键& & { '7',&&'8',&&'9', 0x28 }, //数字键7、数字键8、数字键9、向下键& & { '0', 0x1B, 0x0D, 0x27 }&&//数字键0、ESC键、&&回车键、 向右键};unsigned char pdata KeySta[4][4] = {&&//全部矩阵按键的当前状态& & {1, 1, 1, 1},& & {1, 1, 1, 1},& & {1, 1, 1, 1},& & {1, 1, 1, 1}};
extern void KeyAction(unsigned char keycode);
void KeyDriver()&&//按键动作驱动函数{& & unsigned char i,& & static unsigned char pdata backup[4][4] = {&&//按键值备份,保存前一次的值& && &&&{1, 1, 1, 1},& && &&&{1, 1, 1, 1},& && &&&{1, 1, 1, 1},& && &&&{1, 1, 1, 1}& & };
& & for (i=0; i&4; i++)&&//循环扫描4*4的矩阵按键& & {& && &&&for (j=0; j&4; j++)& && &&&{& && && && &if (backup[ i][j] != KeySta[ i][j])&&//检测按键动作& && && && &{& && && && && & if (backup[ i][j] != 0)&&//按键按下时执行动作& && && && && & {& && && && && && &&&KeyAction(KeyCodeMap[ i][j]);&&//调用按键动作函数& && && && && & }& && && && && & backup[ i][j] = KeySta[ i][j];& && && && &}& && &&&}& & }}void KeyScan()&&//按键扫描函数{& && & static unsigned char keyout = 0;&&//矩阵按键扫描输出计数器& & static unsigned char keybuf[4][4] = {&&//按键扫描缓冲区,保存一段时间内的扫描值& && &&&{0xFF, 0xFF, 0xFF, 0xFF},& && &&&{0xFF, 0xFF, 0xFF, 0xFF},& && &&&{0xFF, 0xFF, 0xFF, 0xFF},& && &&&{0xFF, 0xFF, 0xFF, 0xFF}& & };
& & //将一行的4个按键值移入缓冲区& & keybuf[keyout][0] = (keybuf[keyout][0] && 1) | KEY_IN_1;& & keybuf[keyout][1] = (keybuf[keyout][1] && 1) | KEY_IN_2;& & keybuf[keyout][2] = (keybuf[keyout][2] && 1) | KEY_IN_3;& & keybuf[keyout][3] = (keybuf[keyout][3] && 1) | KEY_IN_4;
& & //消抖后更新按键状态& & for (i=0; i&4; i++)&&//每行4个按键,所以循环4次& & {& && &&&if ((keybuf[keyout][ i] & 0x0F) == 0x00)& && &&&{& &//连续4次扫描值为0,即16ms(4*4ms)内都只检测到按下状态时,可认为按键已按下& && && && &KeySta[keyout][ i] = 0;& && &&&}& && &&&else if ((keybuf[keyout][ i] & 0x0F) == 0x0F)& && &&&{& &//连续4次扫描值为1,即16ms(4*4ms)内都只检测到弹起状态时,可认为按键已弹起& && && && &KeySta[keyout][ i] = 1;& && &&&}& & }
& & //执行下一次的扫描输出& & keyout++;& & keyout &= 0x03;& & switch (keyout)& & {& && &&&case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0;& && &&&case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0;& && &&&case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0;& && &&&case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0;& && &&&default:& & }}/***********************main.c文件程序源代码*************************/#include &reg52.h&
unsigned char T0RH = 0;&&//T0重载值的高字节unsigned char T0RL = 0;&&//T0重载值的低字节
void ConfigTimer0(unsigned int ms);extern void KeyScan();extern void KeyDriver();extern void I2CStart();extern void I2CStop();extern bit I2CWrite(unsigned char dat);
void main (){& & & & EA = 1;& && && &&&//开总中断& & ConfigTimer0(1);&&//配置T0定时1ms
& & while(1)& & {& && &&&KeyDriver();& & }}
void SetDACOut(unsigned char val)&&//设置DAC输出值{& && && && &I2CStart();& && && && &if (!I2CWrite(0x48&&1)) //寻址PCF8591,如未应答,则停止操作并返回& & {& && && && && & I2CStop();& && && && && && && && && && && && &}& & I2CWrite(0x40);& && && &//写入控制字节& & I2CWrite(val);& && && & //写如DA值&&& && && && &I2CStop();}void KeyAction(unsigned char keycode)&&//按键动作函数,根据键码执行相应动作{& & static unsigned char volt = 0;&&//输出电压值,隐含了一位十进制小数位
& & if (keycode == 0x26)&&//向上键,增加0.1V电压值& & {& && &&&if (volt & 25)& && &&&{& && && && &volt++;& && && && &SetDACOut(volt*255/25); //转换为AD输出值& && &&&}& & }& & else if (keycode == 0x28)&&//向下键,减小0.1V电压值& & {& && &&&if (volt & 0)& && &&&{& && && && &volt--;& && && && &SetDACOut(volt*255/25); //转换为AD输出值& && &&&}& & }}void ConfigTimer0(unsigned int ms)&&//T0配置函数{& &
/ 12;& && &//定时器计数频率& & tmp = (tmp * ms) / 1000;&&//计算所需的计数值& & tmp = 65536 -& && &&&//计算定时器重载值& & tmp = tmp + 34;& && && &&&//修正中断响应延时造成的误差
& & T0RH = (unsigned char)(tmp && 8);&&//定时器重载值拆分为高低字节& & T0RL = (unsigned char)& & TMOD &= 0xF0;& &//清零T0的控制位& & TMOD |= 0x01;& &//配置T0为模式1& & TH0 = T0RH;& &&&//加载T0重载值& & TL0 = T0RL;& & ET0 = 1;& && &&&//使能T0中断& & TR0 = 1;& && &&&//启动T0}void InterruptTimer0() interrupt 1&&//T0中断服务函数{& & TH0 = T0RH;&&//定时器重新加载重载值& & TL0 = T0RL;& & KeyScan();}
17.7 PCF8591信号发生器
有了D/A这个武器,我们就不仅仅可以输出方波信号了,可以输出任意波形了,比如正弦波、三角波、锯齿波等等。以正弦波为例,首先我们要建立一个正弦波的波表。这些不需要大家去逐一计算,可以通过搜索找到正弦波数据表,然后可以根据时间参数自己选取其中一定量数据作为我们程序的正弦波表,我们的程序代码选取了32个点。/***********************I2C.c文件程序源代码*************************/& && && && && && && && &&&略/***********************keyboard.c文件程序源代码********************/& && && && && && && && &&&略/***********************main.c文件程序源代码************************/#include &reg52.h&
unsigned char T0RH = 0;&&//T0重载值的高字节unsigned char T0RL = 0;&&//T0重载值的低字节unsigned char T1RH = 1;&&//T1重载值的高字节unsigned char T1RL = 1;&&//T1重载值的低字节
unsigned char code SinWave[] = {&&//正弦波波表127, 152, 176, 198, 217, 233, 245, 252, 255, 252, 245, 233, 217, 198, 176, 152,127, 102,&&78,&&56,&&37,&&21,& &9,& &2,& &0,& &2,& &9,&&21,&&37,&&56,&&78, 102,& & };unsigned char code TriWave[] = {&&//三角波波表& & 0,&&16,&&32,&&48,&&64,&&80,&&96, 112, 128, 144, 160, 176, 192, 208, 224, 240,255, 240, 224, 208, 192, 176, 160, 144, 128, 112,&&96,&&80,&&64,&&48,&&32,&&16,& & };unsigned char code SawWave[] = {&&//锯齿波表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,& & };unsigned char code *pW&&//波表指针
void SetWaveFreq(unsigned char freq);void ConfigTimer0(unsigned int ms);extern void KeyScan();extern void KeyDriver();extern void I2CStart();extern void I2CStop();extern bit I2CWrite(unsigned char dat);
void main (){& & & & EA = 1;& && && &&&//开总中断& & ConfigTimer0(1);&&//配置T0定时1ms& & pWave = SinW&&//默认正弦波& & SetWaveFreq(10);&&//默认频率10Hz
& & while(1)& & {& && &&&KeyDriver();& & }}
void KeyAction(unsigned char keycode)&&//按键动作函数,根据键码执行相应动作{& & static unsigned char wave = 0;
& & if (keycode == 0x26)&&//向上键,切换波形& & {& && &&&if (wave == 0)& && &&&{& && && && &wave = 1;& && && && &pWave = TriW& && &&&}& && &&&else if (wave == 1)& && &&&{& && && && &wave = 2;& && && && &pWave = SawW& && &&&}& && &&&else& && &&&{& && && && &wave = 0;& && && && &pWave = SinW& && &&&}& & }}void SetDACOut(unsigned char val)&&//设置DAC输出值{& && && && &I2CStart();& && && && &if (!I2CWrite(0x48&&1)) //寻址PCF8591,如未应答,则停止操作并返回& & {& && && && && & I2CStop();& && && && && && && && && && && && &}& & I2CWrite(0x40);&&//写入控制字节& & I2CWrite(val);& &//写如DA值&&& && && && &I2CStop();}void SetWaveFreq(unsigned char freq) //设置输出波形的频率{& &
& & tmp = () / (freq*32); //定时器计数频率,是波形频率的32倍& & tmp = 65536 -& && && && && &//计算定时器重载值& & tmp = tmp + 36;& && && && && && &//修正中断响应延时造成的误差
& & T1RH = (unsigned char)(tmp && 8);&&//定时器重载值拆分为高低字节& & T1RL = (unsigned char)& & TMOD &= 0x0F;& &//清零T1的控制位& & TMOD |= 0x10;& &//配置T1为模式1& & TH1 = T1RH;& &&&//加载T1重载值& & TL1 = T1RL;& & ET1 = 1;& && &&&//使能T1中断& & PT1 = 1;& && &&&//设置为高优先级& & TR1 = 1;& && &&&//启动T1}void ConfigTimer0(unsigned int ms)&&//T0配置函数{& &
/ 12;& && &//定时器计数频率& & tmp = (tmp * ms) / 1000;&&//计算所需的计数值& & tmp = 65536 -& && &&&//计算定时器重载值& & tmp = tmp + 34;& && && &&&//修正中断响应延时造成的误差
& & T0RH = (unsigned char)(tmp && 8);&&//定时器重载值拆分为高低字节& & T0RL = (unsigned char)& & TMOD &= 0xF0;& &//清零T0的控制位& & TMOD |= 0x01;& &//配置T0为模式1& & TH0 = T0RH;& &&&//加载T0重载值& & TL0 = T0RL;& & ET0 = 1;& && &&&//使能T0中断& & TR0 = 1;& && &&&//启动T0}void InterruptTimer0() interrupt 1&&//T0中断服务函数{& & TH0 = T0RH;&&//定时器重新加载重载值& & TL0 = T0RL;& & KeyScan();}void InterruptTimer1() interrupt 3&&//T1中断服务函数{& & static unsigned char i = 0;
& & TH1 = T1RH;&&//定时器重新加载重载值& & TL1 = T1RL;& & //循环输出波表中的数据& & SetDACOut(pWave[ i]);& & i++;& & if (i &= 32)& & {& && &&&i = 0;& & }}这个程序可以通过“向上”按键来实现波形输出切换,但是我们的D/A输出没有办法接到显示界面,所以我们用示波器抓出来波形给大家看一下,如图17-11、图17-12、图17-13所示。
ps5b123.jpg (33.02 KB, 下载次数: 121)
23:52 上传
图17-11 D/A输出正弦波形
ps5b124.jpg (32.7 KB, 下载次数: 122)
23:52 上传
图17-12 D/A输出三角波形
ps5b125.jpg (30.69 KB, 下载次数: 96)
23:52 上传
图17-13 D/A输出锯齿波形这几张图可以直接说明我们实现的波形发生器的程序。细心的同学会发现我们波形上有很多小锯齿,没有平滑的连起来。这是因为我们DA最多只能输出0~Vref之间的256个离散的电压值,而不是连续的任意值,所以每个离散值都会持续一定的时间,然后跳变到下一个离散值,于是就呈现出了波形上的这种锯齿。在实际开发中,我们只需要在DA后级加一级低通滤波电路,就可以让带锯齿的波形变得平滑起来。
1、掌握A/D和D/A的基本概念和性能指标。2、将AD采集到的数值显示到数码管上。[size=12.0000pt]3、将信号发生器的程序改装,可以通过按键实现频率的调整。
好文章,学习了。谢谢!
讲的不错,保存吧!
你的帖子都自己写的哈,很不错,今天才发现这个论坛。
老师 您好,不太明白您讲的差分输入情况下的ADC,比如说一个10位的ADC,参考电压是2.5V,对于单端输入时,输入2.5V,对应采集到的数字量是1023,于是有计算公式:Vin=ADC_Value*2.5/1023.若是同样的ADC,改成差分输入形式,对应关系是怎么样的呢?请您不吝赐教!
讲的不错,保存吧!
怎么收藏?
老师怎么接呢?
此 键盘程序有问题&&通过pdata定义的数据 我们好像是访问不了的 键盘运行不起来
Powered by}

我要回帖

更多关于 多功能信号发生器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信