首页 理论教育 如何编写示波器应用程序?

如何编写示波器应用程序?

时间:2023-06-23 理论教育 版权反馈
【摘要】:本节应用程序将被修改成为一个DSK音频输入数据的示波器显示。为起到一个基本的示波器作用,获得的音频数据首先要存储在DSK的一个缓存里。注意,这样的执行为的是容易理解,并不是一种高性能的应用程序。第一步是定义DSP应用程序所需的变量。然后,hpi.h中的HPI_Block声明需要被修改为包含两个新的成员变量,它们位于应用程序中专门的数据区里。

如何编写示波器应用程序?

基本的Windows控制程序(DSK6_CONRTOL)确定为一个修改和扩展的起点。本节应用程序将被修改成为一个DSK音频输入数据的示波器显示。下面的修改列表是DSK6_CONTROL工程的一个完全的复制。这节所有显示的路径名和此工程的最高级目录相关。包含所有更改的一个完整版本在DSK6_CONTROL_OSCOPE中是有效的。

为起到一个基本的示波器作用,获得的音频数据首先要存储在DSK的一个缓存里。当前的下标值(等于缓存中的采样值数)存储在HPI_Block成员变量中。当这个下标值跟缓存长度相等时,则缓存已满,主机可以读取数据。读完之后,主机会清下标值为0以使DSP能存储新的数据到缓冲区。这些数据必须接着在主应用程序对话框中被提取。注意,这样的执行为的是容易理解,并不是一种高性能的应用程序。因此,没有乒乓存储或者高速的图形化机制用得广泛。

DSP代码修改

在CCS中打开DSP工程(.\DSP\TalkThru\talkthru.pjt)。第一步是定义DSP应用程序所需的变量。首先,数据缓存必须声明和分配———它可以在多个地方完成,这里选择hpi.h文件。缓存长度是任意的———这里选择512采样对的长度。在HPI_Block实例上面增加对缓存的声明。

978-7-111-33881-9-Part03-88.jpg

然后,hpi.h中的HPI_Block声明需要被修改为包含两个新的成员变量,它们位于应用程序中专门的数据区里。其中一个变量存储缓存地址,另一个则用来存储当前缓存的索引值。尽管增益成员变量没有用到,但会留在某个地方。

978-7-111-33881-9-Part03-89.jpg

现在,在hpi.c中,在HPI_Block分配表上面分配缓存区。

978-7-111-33881-9-Part03-90.jpg

增加对新的成员变量的初始化。Index变量设为0表明缓存区里没有数据存储。缓存地址变量设成缓存的地址———主机会读取这个值来得到缓存的地址。

978-7-111-33881-9-Part03-91.jpg

现在,中断服务程序必须更改来存储缓存中输入数据。下面的代码要写到两个接收ISR中(McBSP1_Rx_ISR()和McBSP1_Rx_ISR())。软件会核对缓存index值来确定缓存里是否还有空间。如果还有空间可用,则输入数据存储到缓存里,同时index值增加。否则,数据不会存储而index也不会改变。

978-7-111-33881-9-Part03-92.jpg

建立本工程的一个release版本。

主机代码修改

在Visual C++中打开主机工程(C6X_CONTROL.dsw)。主机工程的修改会更复杂一些。像前面那样主机应用程序需要下载程序并运行,但另一方面它需要周期性地检查DSP来判断缓存是否存储。最好的解决方法是保持一个紧凑的循环,读取HPI_Block.Index变量直到它达到BUFFER_LENGTH值。然而在Windows环境中,保留一个紧凑的循环会阻止其他任何一个绘图化机制下的接收信息请求。如果某个地方出错,就会有效地锁住显示。其中一个解决方法是使用一个Windows定时器来周期性地检查DSP的状态。这里还有很多高级的解决方法(如多线程),但为了更容易理解采用定时器解决方法。

在C6X_ControllDlg.h文件中,我们需要添加一个缓存来存储从DSK读取的数据。也像在DSP工程里一样,我们将定义缓存区长度,同时定义一个值用来激活和识别定时器信息。直接在CC6X_CONTROLDlg类声明的上面放置以下代码。

978-7-111-33881-9-Part03-93.jpg

然后,直接在DskIsRunning变量声明下面增加一个缓存变量到CC6X_CON-TROLDlg类的声明里。

978-7-111-33881-9-Part03-94.jpg

在C6X_ControlDlg.cpp文件里,为HPI_Block的偏移量添加以下声明。将HPI_Block成员变量的偏移值计算都放在一个地方来避免错误是较好的编程习惯。这些应该放在文件最上面最后一行的#include下面。

978-7-111-33881-9-Part03-95.jpg

为了实现一致性,我们需要更新增益滑动条信息的句柄函数。改变CC6X_CONTROLDlg::OnReleasedcaptureSlider1()函数的线性输入来匹配下面的代码。

978-7-111-33881-9-Part03-96.jpg

为了使用Windows定时器,需要做几件事。首先,产生一个消息句柄函数,如必要增加启动和结束定时器代码。增加消息句柄,然后:

●在C6X_ControlDlg.cpp文件里单击右键,并选择“Class Wizard…”类向导。(www.xing528.com)

●选择如图E.1所示的有WM_TIMER消息,单击增加函数AddFunction按钮。这就会将消息句柄函数增加到C6X_ControlDlg.cpp文件中。

●关闭类向导对话框。

在这个应用程序中,定时器应该在DSK运行按钮被单击时就要启动,而单击DSK复位按钮时定时器停止。将下面代码放置在CC6X_CONTROLDlg::OnRunBut-ton()函数最下面。这个代码会使定时器每200ms发出一个消息,通过先前定义的SCOPE_TIMER_ID来识别该消息。

978-7-111-33881-9-Part03-97.jpg

978-7-111-33881-9-Part03-98.jpg

图E.1 MFC类向导

KillTimer()函数用来停止定时器。在CC6X_CONTROLDlg::OnResetButton()函数起始处放置以下代码。不必担心程序关闭后停止定时器的问题,这会由Windows自动处理。

978-7-111-33881-9-Part03-99.jpg

为了简单化,应用程序将会直接将音频数据画到应用程序对话窗中。为支持这样的做法,对话框需要做得更大来控制按钮移动。这在可视源编辑窗中很容易完成。打开应用程序对话框,画一个更大尺寸的对话框,移动按钮到另一边。图E.2所示是一个简单的布置例子。

剩余需要完成的任务是往定时器消息句柄函数添加所需代码来实现以下功能:

●核实定时器消息是我们所需的功能之一。

●检查DSK上的数据是否有效。如果无效,退出消息句柄函数。

●如果数据有效,从DSK读取数据,并重置索引值到零。

●通过画一个背景矩形,擦除显示区域。

●绘制新数据。为简单化,这个函数只描绘单音频通道数据。

978-7-111-33881-9-Part03-100.jpg

图E.2 简单应用程序对话框

执行这个功能的代码如下。这应该用于完全替换CC6X_CONTROLDlg::OnTimer()函数主体。

978-7-111-33881-9-Part03-101.jpg

978-7-111-33881-9-Part03-102.jpg

改完之后,编译并运行程序。单击Run DSK按钮则会看到如图E.3所示的对话框。

涉及示波器应用的一些更加增强的功能将是:

●在显示上添加一个同步周期波形触发;

●增加一个增益控制来改变显示幅度;

●或者为立体声编解码器划分两个通道。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈