示波器程序设计源代码+实验报告大作业(共53页).doc
精选优质文档-倾情为你奉上示 波 器 C语言程序设计姓 名: 龚 吉 祥 同 组 人: 王 辉 亚 谭 超 班 级: 09 软件(1)班 学 号: A093GZ 指导老师: 陈 美 成 院 校: 贵州航天职业技术学院 时 间: 2011-11-09 目 录一:摘要、引言 -4二:程序分析-62.1:软件需要实现的功能 -62.2:编译环境 -62.3:项目规划 - 62.4:程序的技术难点 - 7三:程序设计及算法分析 -83.1 程序框架设计 -83.1.1 :程序设计草图 -83.1.2 程序流程图 - 93.1.3 程序所需全局变量:-103.1.4 函数分析:-103.2 程序模块函数详解 -133.2.1:按钮的设计-133.2.2,设置按钮按下的效果函数 -153.2.3,制作旋转圆形按钮 -173.2.4:图形模式下的汉字输出 -203.3 程序界面的绘制 -21 3.3.1 绘波区的刻度函数 -223.3.2 绘制程序固定不变的界面 -223.4 动态界面需要的相关元素 -273.4.1 鼠标的监听- 283.4.2 当鼠标离开按钮,程序界面的恢复-303.4.3 当鼠标在旋转按钮上点击鼠标左键的效果函数 -313.4.4 获取鼠标点击界面上的那一个按钮 - 323.5 波形图函数 -343.5.1 正弦波 -343.5.2 方波 - 363.5.3 三角波 - 373.5.4 锯齿波 -383.5.5 模拟音波 -383.5.6 无规律波 -393.6 波形图函数测量值输出 -403.6.1:正弦波的相关数据输出- 403.7:主要操作界面及函数(主函数)-42四:示波器最终效果 - 50五:总结 -51六:展望与发展 - 52七:参考文献-53摘要:随着计算机技术的发展,传统仪器开始向计算机化的方向发展。虚拟仪器是90年代提出的新概念。虚拟仪器技术的提出与发展,标志着二十一世纪自动测试与电子测量仪器领域技术发展的一个重要方向。所谓虚拟仪器,就是在通用的计算机平台上定义和设计仪器的测试功能,使用者操作这台计算机,就像是在使用一台专门设计的电子仪器。本程序就是通过图形化虚拟示波器,因为在数据的采集和处理过程现在本组的技术能力有限,所以就通过简单的数学知识和C语言的相关知识来解决这个示波器程序。在程序中利用C语言基础知识和不断的重画图形来实现模拟的示波器。在程序重主要利用的了鼠标中断,数学的正弦函数和其他的图形函数来实现波的显示来模拟示波器。关键字: 示波器、正弦波、三角波、方波、频率、周期、振幅引言虚拟示波器是采用基于计算机的虚拟技术,用以模拟通用示波器的面板操作和处理功能,也就是使用个人计算机及接口电路来采集现场或实验室信号,并通过图形用户界面来模仿示波器的操作界面,完成信息采集、调理、分析处理和显示输出等功能。该程序所设计的虚拟示波器,是在数据采集硬件的支持下,配备一定的软件,完成波形的存储、分析、显示等功能。一般测试仪器有信号采集、信号处理和结果显示三大部分组成,这三大部分均由硬件构成。虚拟示波器也是由这三大部分组成,但是,除了信号采集部分是有硬件实现之外,其它两部分都是由软件实现。所设计的虚拟示波器总体上包括数据采集、波形显示、参数测量、频谱分析、等几大模块组成,虚拟示波器的结构框架图如下:信号输入数据采样数据处理波形显示参数测量与控制频谱分析 这是示波器的基本处理过程,而本程序只实现了, 两步,前面的数据都是通过随机函数或设定一个值,然后通过后面的相关调节来改变数据,所以本程序只实现一个简单的模拟示波器。 程序分析1 该软件需要实现的功能:(1) 波形的展宽,压缩。(2) 幅度的放大与缩小。(3) 波形的平移。(4) 实现信号的测量功能。2编译环境:(1) 硬件平台:CPU:P41.8GHz;内存:256MB以上。(2) 编译工具:Wintc中文版(3) 运行环境:windowsXP3 项目规划:q 数据的信号的采集这一个模块用来实现对外界信号的数据信号的测量。因为该部分知识尚未掌握。所以这些数据通过设置一个固定值和随机函数来代替数据的采集。q 数据信号的采集:该模块实现把收集好的信号转变为图形界面输出。本程序只通过了一些数学函数来完成。q 实现用户与程序的交互性:本程序实现这一点是通过接收用户的鼠标操作。该模块由黄金翔来完成。q 波形的显示: 该模块以实现波形的图形显示。比如:正弦波,三角波,方波,锯齿波.。该模块由袁财富完成。q 数据信号测量和显示,调频,调幅,平移:该模块实现波形的相关数据的显示,调频,调幅,平移。该模块由张志中来完成。q 程序的设计以及程序的最终组合:程序模块的组合和相关的完善,该模块由组长伍俊完成。4 程序技术难点 1:无法实现对信号的采集,如:电量,电压、电流、频率、相位差、调幅度等 2:在试验过程中无法反映相关真实的数据,只能一味的用函数模拟波形。 3: 除掉前面两条没不用考虑的技术难点,这个程序在制作过程中的技术难点就是鼠标的控制,即鼠标的点击状态,和鼠标的当前位置。4:汉字的图形画界面显示,本程序调用的是汉字字库HZK16的文字点阵图来实行汉字的显示。 5:波形的重画方法,程序执行过程中因为要不断的画波,而又因为不断的重画会导致画面的不流畅和闪烁,所以本程序中暂且采用的是檫去上一次的波的方法来减少程序的闪烁。 6:程序中波的展宽与压缩,其间不能改变波的原来的参数,只能通过一种算法来实现。 三 程序设计及算法分析说明:本程序因为需求的知识面甚广,而现在只学了C语言。而示波器的真正功能就未实现,这个程序做的就是模拟示波器的应用的一小部分。3.1 程序框架设计 3.1.1:程序的设计草图, 说明: 程序通过几次设计及查看老师给的示例图片,最终通过PS 画出了上面的草图。还有相关的坐标已由图中给出。该草图方便其他成员对整个程序大致有一个了解。开始图形初始化登陆界面:DengLu()绘制界面中的很少变动的场景Graph_face()While(1)获取鼠标的坐标和按键状态mouse(&x,&y,&z,smbo);返回用户所选的那个按钮Anniu=Return_button(x,y,z);switch(Anniu) 来恢复和显示当前按钮,和设置准备绘制什么波根据上一布获得的什么波这一不就画什么波Free(MoliNum)Closegraph结束如有退出操作没有退出操作3.1.2:程序流程图;说明: 该流程图是整个程序执行过程中的大致描述。3.1.3 程序所需全局变量:1int zf=40; /*用于存储振幅当前值*/2int zq=36; /*用于存储周期当前值*/3int py=2; /*用于存储平移当前值*/4int Chang_zf; /*用于存储振幅值改变前的值*/5int Chang_zq; /*用于存储当前周期的上次周期值*/6int Chang_py; /*用于存储当前平移的上次平移值*/7int smbo=0; /*用于存储保存当前是什么波*/8static int MoliNum32; /*用于存储模拟音波中的值*/3.1.4函数分析:void DrawButtonUp(int left,int top,int width,int height,int color)/*函数说明;函数用于画按钮没有被按下时的画面,这个函数主要画有背景的按钮,其中left,top, width, height ,color 从字面意思就可以明白表示是按钮的左上角的坐标和按钮的宽度,还有按钮背景的颜色*/void DrawButtonUp1(int left,int top,int width,int height) /*函数说明;函数用于画按钮没有被按下时的画面,这个函数没有画有背景的按钮,其中left,top, width, height ,color 从字面意思就可以明白表示是按钮的左上角的坐标和按钮的宽度,这个函数是一个“死“按钮。因为如果要改变按钮 那么 就得改原代码函数。 这个函数在本程序下面主要是实现做动态画面的,已因为这一点,为了动态效果的流畅,所以没有画按钮背景*/void DrawForm(int left,int top,int width,int height,int color) /*函数说明;函数用于绘画窗口的函数,因为要达到窗口的效果所以它和按钮有相似之处已有不同之处*/void DrawButtonDown(int left,int top,int width,int height,int color) /*函数说明;函数用于画按钮被按下时的画面,这个函数主要画有背景的按钮,其中left,top, width, height ,color 从字面意思就可以明白表示是按钮的左上角的坐标和按钮的宽度,还有按钮背景的颜色*/void DrawButtonDown1(int left,int top,int width,int height) /*函数说明;函数用于绘画按钮被按下的函数,同前面的DrawButtonUp1 一样没有画按钮背景颜色 */void DrRotationBtn(int x,int y,int r) /*函数说明;用于实现旋转按钮的绘制函数 ,X,Y是中心坐标,R 是最大半径。*/void DrawKedu(int x,int y) /*函数说明;用于实现旋转按钮DrRotationBtn刻度的绘制函数 ,X,Y是中心坐标。该函数没有半径的设置 针对后面才加的函数 。所以需要在里面改动画的位置*/void initgr() /* BGI初始化 函数说明;初始化图形模式*/void getmouse(int *x,int *y,int *key) /*函数说明;中断调用获取寄存器中存的鼠标坐标及案件状态*/void visbilemouse() /*函数说明;显示鼠标*/void mouse(int *x,int *y,int *z,int smbo) /*函数说明;画鼠标是利用将一个空矩形存入内存中,然后再在该空矩形中画鼠标形状*/void hanzi16(int x,int y,char *s,int colour) /*函数说明;中文输入输出函数,该函数需要汉字字库文件 HZK16 的支持*/void myouttext(int x, int y,int num) /*函数说明;控制单个数字的输出显示 */void Drowxy(int x,int y,int w,int h) /*函数说明;画示波器显示波的坐标, x,y 为坐标原点位置*/void Sine_date(int zf,int zq,int Chang_zf,int Chang_zq) /*函数说明;用于实现正弦波的相关数据的显示,zf当前现在波的振幅zq当前现在波的周期Chang_zf上次波的振幅Chang_zq上次波的周期*/void Podu(int zq,int py,int Chang_zq,int Chang_py) /*函数说明;用于实现正弦波的坡度的显示,该函数因为前期是实现鼠标点击处的坡度。但是在后期程序的改动所以没多用这个。已因为时间原因程序没多大改动。*/void Sinew(int zf,int zq,int py,int Chang_zf,int Chang_zq,int Chang_py) /*函数说明:画正弦波函数 */void NoRuleWave(int zf,int zq) /*函数说明;该函数原本已实现一些无规律波,或者方便扩展好改动为其他波,但是由于时间问题 这个函数就只是随便加了个随机函数*/void MOliWave(int MoliNum) /*函数说明;该函数用于随机生成一个数 ,然后用sound()PC 函数播放出这个数值的声音,已是在程序的基础上现在加的东东,方便以后更改和扩展*/void Graph_face() /*函数说明;该函数是 主要函数,其功能是实现本程序的 基本不动画面的绘制,比如按钮和背景 还其他的按钮边框之类。本函数只程序运行的开始时使用*/int Return_button(int x,int y,int z) /*函数说明;该函数是已是该程序的主要函数之一,用于判断用户当前鼠标的动作,比如一个按钮的按下,相应程序的操作。 */void Huifu()/*函数说明;该函数是已是该程序的主要函数之一,用于判断实现程序动态的效果的恢复工作,比如一个按钮按下以后鼠标离开按钮后 那么这个按钮就需要恢复到正常状态*/mousedata(int x,int y) /*函数说明;用于显示鼠标处的坐标*/void Huifu_1() /*函数说明;程序说明段的文字颜色恢复,是程序后面加上的效果。*/int DrRtinP(int x,int y,int m_x,int m_y,int Old_x,int Old_y,int r,int back) /*函数说明;x,Y为圆心坐标m_x,m_y为鼠标点击处坐标*/void DengLu() /*函数说明:做登陆效果*/void DrawSoftAny() /*函数说明:程序说明函数*/3.2:程序模块函数详解.3.2.1:按钮的设计; 分析:计算机中的按钮都是通过改变局部的颜色而达到动态的按钮效果。如图;1, 设置按钮弹起的效果函数;void DrawButtonUp(int left,int top,int width,int height,int color)/* Draw button*/ setfillstyle(1,color); bar(left,top,left+width,top+height); setcolor(15); line(left-2,top,left+width,top);line(left-1,top+1,left+width,top+1); line(left-1,top+2,left-1,top-1+height); line(left-2,top+2,left-2,top-1+height); setcolor(7); line(left,top+height,left+width,top+height); line(left-1,top+height-1,left+width+1,top+height-1); line(left-1+width,top+2,left-1+width,top+height); line(left+width,top+2,left+width,top+height); 2,为了按钮 的恢复 一下函数是恢复按钮周围变宽效果 已减少Bar();重画函数使用的时间 void DrawButtonUp1(int left,int top,int width,int height) /*Draw button */ setcolor(15); line(left-2,top,left+width,top); line(left-1,top+1,left+width,top+1); line(left-1,top+2,left-1,top-1+height); line(left-2,top+2,left-2,top-1+height); setcolor(7); line(left,top+height,left+width,top+height); line(left-1,top+height-1,left+width+1,top+height-1); line(left-1+width,top+2,left-1+width,top+height); line(left+width,top+2,left+width,top+height);函数效果如图; 3.2.2,设置按钮按下的效果函数;void DrawButtonDown(int left,int top,int width,int height,int color) /*Draw button */ setfillstyle(1,color); bar(left,top,left+width,top+height); setcolor(8); line(left-2,top,left+width,top); line(left-1,top+1,left+width,top+1); line(left-1,top+2,left-1,top-1+height); line(left-2,top+2,left-2,top-1+height); setcolor(15); line(left,top+height,left+width,top+height); line(left-1,top+height-1,left+width,top+height-1); line(left-1+width,top+2,left-1+width,top+height); line(left+width,top+2,left+width,top+height);为了按钮 的恢复 一下函数是恢复按钮周围变宽效果 已减少Bar();重画函数使用的时间 void DrawButtonDown1(int left,int top,int width,int height) /*Draw button */ setcolor(8); line(left-2,top,left+width,top); line(left-1,top+1,left+width,top+1); line(left-1,top+2,left-1,top-1+height); line(left-2,top+2,left-2,top-1+height); setcolor(15); line(left,top+height,left+width,top+height); line(left-1,top+height-1,left+width,top+height-1); line(left-1+width,top+2,left-1+width,top+height); line(left+width,top+2,left+width,top+height); 函数效果如图;3.2.3,制作旋转圆形按钮;void DrRotationBtn(int x,int y,int r) int i=0;float a; setcolor(15); for(i=0;i<=360;i+=6) a=i*PI/180; line(x+(r-5)*cos(a),y+(r-5)*sin(a),x+r*cos(a),y+r*sin(a) ; setcolor(8); circle(x,y,r); circle(x,y,r-1); circle(x,y,r+1); setfillstyle(1,7); pieslice(x,y,0,360,r-5); setfillstyle(1,15); pieslice(x,y,0,360,r-10); for(i=0;i<=360;i+=6) a=i*PI/180; line(x+(r-15)*cos(a),y+(r-15)*sin(a),x+(r-10)*cos(a),y+(r-10)*sin(a) ; 3.2.4,制作旋转按钮刻度void DrRotationBtn(int x,int y,int r,int label) /*画旋转的按钮*/ int i=0,j,k=10,last=0;float a; if(label!=0) /*如果不在调位移旋转按钮上*/ setcolor(15); for(i=0;i<=360;i+=6) a=i*PI/180; line(x+(r-5)*cos(a),y+(r-5)*sin(a),x+r*cos(a),y+r*sin(a) ; setcolor(8); circle(x,y,r); circle(x,y,r-1); circle(x,y,r+1); setfillstyle(1,7); pieslice(x,y,0,360,r-5); setfillstyle(1,15); pieslice(x,y,0,360,r-10); for(i=0;i<=360;i+=6) a=i*PI/180; line(x+(r-15)*cos(a),y+(r-15)*sin(a),x+(r-10)*cos(a),y+(r-10)*sin(a) ; /*画调节大小*/ for(j=4;j<=20;j+) for(i=(j-4)*18;i<=150;i+) a=i*PI/180; putpixel(x+(r+j)*cos(a),y+(r+j)*sin(a),0); for(j=4;j<=20;j+) for(i=350-(j-4)*18;i>210;i-) a=i*PI/180; putpixel(x+(r+j)*cos(a),y+(r+j)*sin(a),0); else setcolor(0); /*画调节大小*/ setlinestyle(0,1,3); line(x-r,y,x+r,y); setlinestyle(0,1,1); line(x-r,y,x-r+5,y-5); line(x-r,y,x-r+5,y+5);/*标箭头*/ line(x+r,y,x+r-5,y-5); line(x+r,y,x+r-5,y+5); setcolor(15); int DrRtinP(int x,int y,int m_x,int m_y,int Old_x,int Old_y,int r,int back,int label) /*x,Y为圆心坐标m_x,m_y为鼠标点击处坐标*/ float Cosa,Sina,rr; setcolor(15); if(label!=0) /*如果不在调位移旋转按钮上*/ if(Old_x!=0 && Old_y!=0) rr=sqrt(x-Old_x)*(x-Old_x)+(y-Old_y)*(y-Old_y); Cosa=(Old_x-x)/rr; Sina=(Old_y-y)/rr; line(x+(r-15)*Cosa,y+(r-15)*Sina,x+r*Cosa,y+r*Sina); else line(x,y-5,x,y-20); rr=sqrt(x-m_x)*(x-m_x)+(y-m_y)*(y-m_y); Cosa=(m_x-x)/rr; Sina=(m_y-y)/rr; setcolor(4); line(x+(r-15)*Cosa,y+(r-15)*Sina,x+r*Cosa,y+r*Sina); return (acos(Cosa)*180)/PI/30*back; /*旋转按扭的返回值*/ else setcolor(7); setlinestyle(0,1,3); line(Old_x,y-5,Old_x,y+5); setcolor(0); line(x-r-r+5,y,x+r+r-5,y); line(x,y-10,x,y+10); return (m_x-x); /*旋转按扭的返回值*/ 函数效果如图;3.2.5:图形模式下的汉字输出。void hanzi16(int x,int y,char *s,int colour) /*中文输入输出函数*/ FILE *fp; char buffer32; /* 32字节的字模缓冲区 */ register i,j,k; unsigned char qh,wh; unsigned long location; if(fp=fopen("hzk16","rb")=NULL) printf("Cant open hzk16!"); getch(); exit(0); while(*s) qh=*s-0xa0; wh=*(s+1)-0xa0; location=(94*(qh-1)+(wh-1)*32L;/* 计算汉字字模在文件中的位置 */ fseek(fp,location,SEEK_SET); fread(buffer,32,1,fp); for(i=0;i<16;i+) for(j=0;j<2;j+) for(k=0;k<8;k+) if(bufferi*2+j>>(7-k)&0x1)!=NULL) putpixel(x+8*j+k,y+i,colour); s+=2; x+=16; /* 汉字间距 */ fclose(fp);3.3:程序界面的绘制。 说明:经分析,程序中有两部份:一部分界面是一次画好就固定不变的,而另一部分是因用户的操作而动态变化的,比如当鼠标在正弦波按钮上点击鼠标左键的时候,那么在波形绘制区就会绘制一个正弦波的图形。在这过程中又可以分解为两个部分 ,鼠标按下和鼠标松开以后程序相应的反馈动作,而这部分界面就是动态界面。 在这里就先把固定不变的部分通过一个函数完成; 数字的图形显示。void myouttext(int x, int y,int num) /*控制输入数字 */ switch (num) case 1 :outtextxy(x,y,"1");break; case 0 :outtextxy(x,y,"0");break; case 2 :outtextxy(x,y,"2");break; case 3 :outtextxy(x,y,"3");break; case 4 :outtextxy(x,y,"4");break; case 5 :outtextxy(x,y,"5");break; case 6 :outtextxy(x,y,"6");break; case 7 :outtextxy(x,y,"7");break; case 8 :outtextxy(x,y,"8");break; case 9 :outtextxy(x,y,"9");break; default :; 3.3.1;绘波区的刻度函数,void Drowxy(int x,int y,int w,int h) /*画坐标 xy 为圆心坐标,w为一半的宽度h一半的高度*/ int i; setcolor(1); setlinestyle(0,0,3); line(x-w,y-1,