GDIPlus双缓存技术在USB采集卡控制软件中的应用
2011-05-21杨增宝
杨增宝 , 杨 浩
(1.重庆大学 重庆 400044;2.长江师范学院 重庆 408100)
心电、脑电、胃电等生物电信号通常都集中在频率低段,对采样电路和波形显示设备的要求都不太高。但为了能对象肌电一类相对较高频率的生物电信号进行更高质量的采样和精确分析,就要求有更高速率的数据采集设备。常规数据采集卡都采用PCI接口,安装和携带都非常麻烦,给人们的研究工作带来了极大的不便。因此,设计一款基于USB接口的高速率数据采集卡,对分析更复杂的生物电信号有着十分重要的作用,也会给研究工作带来更大的方便。
图1 硬件结构图Fig.1 Block diagram of hardware
1 硬件环境介绍
控制软件针对的是该款自行设计的,以Cypress公司生产的CY7C68013A为核心的USB数据采集卡,该卡充分利用了USB2.0的高带宽数据传输优势,在采样精度为12 Bit的条件下,还能达到单通道最高6 Ms/s的数据采样速率。采集卡的硬件设计如图1所示。
图中,隔离电路采用轨至轨、低噪声运放LT1677连接成跟随器实现,有较高的通频带;A/D转换器采用了ADI公司的AD9220,其转换精度为12 Bit,最高采样速率可达10 Ms/s;USB接口电路由Cypress公司的CY7C68013A构成,它率先支持USB2.0传输标准,内建一个可工作在48 MHz时钟的增强型8051内核[1],利用它可以方便地通过上位机对其工作状态进行设定,而且它内部还自带4 kB FIFO,每个端点都可独立使用其中的1 k。
该设计方案的最大特点是做到了硬件结构的最简化,因而成本最低、工作稳定度也最高。设计中最主要的创新点是去掉了通常由FPGA或CPLD来执行的外部控制逻辑,让A/D转换器的时钟信号CLK直接由CY7C68013的GPIF输出信号CTL来提供,在简化了外围控制逻辑的同时,又保证了较高的采样速率(因为GPIF的驱动时钟为12 MHz),同时还很好地解决了时钟同步问题。
2 GDIPlus双缓存技术在控制软件中的实现
GDIPlus(Graphics Device Interface Plus)是 Windows系列操作系统用来执行绘画及其他相关图形操作的一套子系统[2],它是一组通过C++类实现的应用程序编程接口,它不仅在GDI的基础上添加了许多新特性,而且对原有的GDI功能进行了各种优化。在它的基础上,采用GDIPlus双缓存技术[3]绘图,不仅可以非常容易地编写出与设备无关的应用程序,而且可以实现更好的绘图效果。
由于硬件平台数据采样率比较高,这就要求上位机的波形显示程序要有尽可能高的效率才能达到理想的动态波形显示效果,因此我们将GDIPlus双缓存技术引入到此硬件平台的控制软件开发当中。
由于GDIPlus提供了更丰富的绘图方法,因而生成平滑度效果十分良好的图形线条,同时还能跟早期GDI编程一样对所绘图形的属性进行控制,该方法具有更高的实用价值。
控制软件在绘制波形前,首先要从USB端口获取AD采集的原始数据,这一过程需要通过访问驱动程序来实现。
2.1 应用程序与驱动程序的接口
控制软件首先通过bOpenDriver()方法与驱动程序建立连接,并打开USB设备,函数原型如下:
BOOL bOpenDriver (HANDLE *phDeviceHandle,PCHAR devname)
{
char completeDeviceName[64]="";
char pcMsg[64]="";
strcat(completeDeviceName,"\\.\");
strcat(completeDeviceName,devname);
*phDeviceHandle=CreateFile(completeDeviceName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if(*phDeviceHandle==INVALID_HANDLE_VALUE)
{
return (FALSE);
}
else
{
return (TRUE);
}
}
然后应用程序通过DeviceIoControl()方法[4]从CY7C68013A的EP6端点获取AD转换器采集到的数据结果,得到的数据在指针inBuffer中,其函数原型如下:
inBulkControl.pipeNum=1;//选择EP6为输入端口DeviceIoControl(usbInHandle, //指定 USB 设备句柄
IOCTL_EZUSB_BULK_READ,//指定传输类型为Bulk IN
(PVOID)&inBulkControl, //传输控制缓冲区指针
sizeof (BULK_TRANSFER_CONTROL), //传输控制缓冲区大小
inBuffer,//数据输入缓冲区指针
TransferSize,//数据传输量大小
&nBytes,//实际返回的字节数
NULL);
如果采集到的数据还需进行数字滤波[5]或其它算法的加工,可直接对inBuffer中的数据进行相应处理。处理完后的结果便可用于波形显示。
由于AD采集的每一个数据都对应波形上的一个点,所以波形显示的主要目的就是把这些离散的点连成线条。因此,控制软件会非常频繁地调用DrawLine()函数。如果DrawLine()函数直接把图形绘制到绘图窗口,其绘图效率会严重下降。最为严重的问题还在于每一帧图形绘制完毕后的擦除操作会导致整个绘图窗口的闪烁。为有效解决这两个问题,设计引入了双缓存的绘图方法。
2.2 GDIPlus双缓存技术的实现过程
实现双缓存技术的基本思想是:创建一个跟显示窗口等大的内存空间作为虚拟画布,用来保存临时绘制的图像,当一帧完整的图形全部绘制完毕之后,再一次性将此虚拟画布的内容复制到显示窗口中,完成最终显示任务。由于内存的访问速度远高于实际窗口绘图,所以绘图效率成倍地提高。再加上整个绘图过程和擦除动作都是在虚拟画布中以后台的方式完成的,所以前一帧与后一帧之间的擦图操作被隐藏,闪烁问题得到了有效解决。
虚拟画布的创建在GDIPlus中需要用Bitmap bmp()方法来实现,其调用参数 rect.Width()和 rect.Height()保障了它与实际窗口面积等大。应用程序原则上可以调用任何GDIPlus提供的绘图函数来在虚拟画布所对应的缓存区中绘制图形映像,但本控制软件的主要任务是绘制波形图,所以只调用了DrawLine()函数。需要特别指出的是,在GDIPlus库中,画点和画线都只能用DrawLine()函数来完成[6],两者实现了统一。
程序最后调用Graphics.DrawImage()方法,将虚拟画布中的图形映像直接拷贝到显示窗口内存,快速完成将虚拟画布中图像显示到实际窗口的任务。整个过程的关键代码如下:
void CGdiDrawDlg::OnWave()
{
CWnd*pWnd=GetDlgItem(IDC_WAVE);
CClientDC dc(pWnd);
Graphics g(dc.m_hDC);
CRect clientrect;
GetClientRect(&clientrect);
CRectrect (clientrect.left,clientrect.top,clientrect.Width(),clientrect.Height());
Bitmap bmp(rect.Width(),rect.Height());//——创建虚拟画布
Graphics gTmp(&bmp);//——获取虚拟画布的
Graphics引用
SolidBrush br(Color(255,0,0,0)); //定义背景画刷
gTmp.FillRectangle (&br,0,0,rect.Width (),rect.Height()); //定义填充背景
Pen pen(Color(255,255,50,50),1);//定义画笔及其属性pen.SetWidth(1); //设置画笔线宽
gTmp.SetSmoothingMode (SmoothingModeHighQuality);//反锯齿平滑显示
for(i=0;i< sizeof(inBuffer);i++)
{
gTmp.DrawLine(&pen,i,inBuffer[i],i+1,inBuffer[i+1]);
//根据inBuffer里面的数据在虚拟画布上绘图
}
g.DrawImage (&bmp,0,0); //将虚拟画布中的图形映像绘制到实际窗口
}
3 结束语
图2是该卡在6 Ms/s采样率下对22 kHz正弦波的采样结果,对于如此高速率的数据流,任何软件都无法完成对所有采样点的同步实时显示,所以本软件目前也只能完成对该信号数据的分段抽样显示,抽样率为20帧/秒,所以对于软件的绘图效率部分还有待进一步研究和提高。综上所述,GDIPlus双缓存技术是Windows平台支持的高效图形显示方案,通过该技术在本设计中的应用表明,它实现了高效、平滑的波形显示效果,使得动态波形快速显示的闪烁问题得以有效解决,能满足工程设计要求。
图2 控制软件运行图Fig.2 Running diagram of control software
[1]钱峰.EZ-USB FX2单片机原理编程及应用[M].北京:北京航空航天大学出版社,2006.
[2]Chand M.GDI+图形程序设计[M].韩江,等译.北京:电子工业出版社,2005.
[3]Kruglinski D J, Wingo S.Visual C++6.0技术内幕[M].北京:北京希望电子出版社,1999.
[4]CypressSemiconductor.CypressCyAPIprogrammer’s reference[EB/OL].(2003)[2010-03-20].http://www.mikrocontroller.net/attachment/34631/CyAPI.pdf.
[5]陈辉,李远.基于USB2.0的数据采集卡[J].自动化技术与应用,2008,27(6):91-93 CHEN Hui,LI Yuan.A data acquisition card based on USB2.0[J].Techniques of Automation and Applications,2008,27(6):91-93
[6]张国辉,胡闻达,李慧智.基于GDI+的缓冲区建立及边界描述方法[J].测绘科学技术学报,2010,27(3):229-232 ZHANG Guo-hui, HU Wen-da, LI Hui-zhi.A way to establish buffer area and describe boundary based on GDI+[J].Journal of Geomatics Science and Technology,2010,27(3):229-232.