现代计算机接口技术实验.docx
《现代计算机接口技术实验.docx》由会员分享,可在线阅读,更多相关《现代计算机接口技术实验.docx(50页珍藏版)》请在冰豆网上搜索。
![现代计算机接口技术实验.docx](https://file1.bdocx.com/fileroot1/2023-4/17/a9502390-7a6b-438b-8539-bf1f3a9a724f/a9502390-7a6b-438b-8539-bf1f3a9a724f1.gif)
现代计算机接口技术实验
现代计算机接口技术
及MFC程序实现
武汉工业学院计算机与信息工程系
目录
实验1定时与中断接口程序设计………………………………………………………………………1
实验2操作PC机上的8250实现串行通信………………………………………………………5
实验3基于DLL与HOOK技术的键盘消息拦截与读音……………………………………10
实验4MFC串行通信程序设计…………………………………………………………………………16
实验5DirectShow接口实现视频显示与帧捕获………………………………………………20
实验6基于Socket接口的网络通信MFC程序设计…………………………………………27
实验1定时与中断接口程序设计
一实验目的
1.了解定时器/计数器8253、并行I/O接口8255A在PC机中的电路连接方法;
2.学习使用TURBOC++对8253、8255进行编程操作;
3.熟悉拦截PC机中断向量的TC++编程方法。
二实验内容
1.8253、8255在PC/XT机中的电路连接介绍
1.19MHz
PC机启动后,系统设置的初始状态为:
芯片
有关工作方式
初值
运行情况
8253
通道0#:
方式3(方波发生器)
计数初值:
0000H
OUT输出55ms方波至8259的IRQ0
通道2#:
?
(1KHz)
计数初值:
?
(1190)
?
(1KHz方波)
8255
PB0、PB1:
方式0(简单输出)
控制蜂鸣器发声。
0:
不发声,1:
发声
8259
IRQ0:
允许中断
中断类型号:
8
CPU响应8号中断
表中,8253的通道2#的工作方式和计数初值未知,要求自己设置。
2.程序要求
利用TURBOC++开发环境设计程序,实现如下功能:
(1)程序启动时,要求输入定时时间,以秒为单位。
(2)按秒计时,每秒到达时,在屏幕上显示当前为第几秒,同时蜂鸣器发出短促叫声;
(3)当定时时间到,则显示“TimeUp!
”,结束程序。
三实验环境
硬件环境:
PC机一台;
软件环境:
操作系统不限,TURBOC++3.0。
四实验步骤
1.建立源文件
启动TURBOC++3.0,建立Timer.CPP。
保存到D:
\×××(学号)\Timer.CPP;
2.设置TC工作目录
选菜单Options/Directories,第1、2栏保持不变,第3、4栏填写您的文件存放目录,OK。
如此,TC生成的可执行文件等将会存放到此工作目录下。
样例如下:
3.输入源程序
以下源程序仅供参考。
#include//支持标准输入输出,如printf()。
#include//支持接口访问、中断向量操作函数
#include//支持exit()函数
#ifdef__cplusplus//定义C++使用的中断函数标识符。
若是×××.C程序,则不需要
#define__CPPARGS...
#else
#define__CPPARGS
#endif
intnTick=0,sec=0,flag=0;
unsignedcharsys_PB,my_PB;
voidinterruptfar(*sys_int_08)(__CPPARGS);//若是×××.C,则函数参数不写
voidinterruptfarmy_int_08(__CPPARGS)//若是×××.C,则函数参数不写
{//8号中断,每55ms中断一次,由8253的0号定时器定时,并向8259IRQ0申请中断
++nTick;
if(tinck==1)outportb(0x61,my_PB);//开始鸣叫
elseif(tinck==3)outportb(0x61,sys_PB);//停止鸣叫
elseif(nTick>18)
{//1second/55ms近似等于18
flag=1;
nTick=0;
sec++;
}
sys_int_08();//调用系统的中断向量
}
//==========================================
voidmain()
{unsignedintTime_up;
printf("PleaseinputUpTime(5--30):
");
scanf("%d",&Time_up);
printf("\n");
if(Time_up<5||Time_up>30)
{printf("InputError!
");
exit
(1);//结束程序
}
outportb(0x63,0x82);//设置8255,PB为输入方式
sys_PB=inportb(0x61);//读取PB口,内容
my_PB=sys_PB|0x03;//将PB口低2位(PB0,PB1)置1
outportb(0x63,0x80);//设置8255,PB为输出方式
//8253通道2,产生1KHz方波,送到扬声器,使扬声器发声
outportb(0x43,0xb6);//CW=10110110B,通道2,先低字节,再高字节,方式3,二进制
outportb(0x42,0xa6);//lowbyte,
outportb(0x42,0x04);//highbyte,0x04a6=1190,f=1.19MHz,out=f/1190=1000Hz
sys_int_08=getvect(0x08);//保存系统的中断向量
setvect(0x08,my_int_08);//设置系统向量
while
(1)
{if(flag==1)
{flag=0;
printf("%d",sec);
if(sec==Time_up)break;
}
}
printf("TimerUp!
\n\n");
outportb(0x61,sys_PB);//恢复系统的PB口状态
setvect(0x08,sys_int_08);//恢复系统的中断向量
}
4.运行程序,再完成如下内容
(1)8253的通道0在程序中起什么作用?
为什么在程序中没有对其进行初始化及赋初值?
(2)修改8253通道0#的初值,使计时精度严格为1秒。
提示:
可采用动态初值,即一秒内的每次中断采用不同的初值,使每次中断得到的时间间隔之和为1000ms。
55ms的定时=65535×1/1.19MHz
(3)my_int_08()函数什么时候被调用?
(4)将main()函数的最后一句注释掉,再执行,会有什么结果?
假定是在纯DOS环境下执行这个程序。
(5)本程序为什么采用DOS环境编写程序,而不采用Windows环境?
六实验报告
实验报告是科学实验中的重要技术文档,应如实记录实验中发生的现象、处理措施和结果。
实验报告的组成一般为:
实验项目名称(要求严格与本指导书一致)、实验日期、场地、采用的软硬件环境,实验者;对于为什么采用此环境,必要时可作出说明。
例如,本实验为什么要采用TC,而不采用VC?
实验目的:
具体写要做成什么,期望得出什么结果。
不要照抄本指导书。
实验过程:
具体写操作的过程,对于源程序,不一定全部写出,但应画出模块图、流程图。
核心代码可写出。
特别要写出实验中碰到的问题及分析、解决办法。
实验结果及分析:
如实写出结果,对结果进行分析,可进一步提出改进、提高的办法。
实验2操作PC机上的8250实现串行通信
一实验目的
1.了解8250在PC机中的电路连接方法;
2.学习使用TURBOC++对8250进行编程操作;
3.利用8259中断实现RS232串行通信。
二实验指导
1.8250内部基本结构简介
为便于理解,以下仅给出8250内部的简化逻辑结构和主要管脚,详情请参阅有关技术资料。
D7…D0
注:
各寄存器旁标注的十六进制数是该寄存器在PC中的I/O地址。
2.8250内部寄存器功能简介
Ø线路控制寄存器LCR
DLAB
SB
SP
EPS
PEN
STB
WLS1
WLS0
数据位数
00:
5;01:
6
10:
7;11:
8
停止位数
0:
1
1:
1.5或2
01:
奇校验
11:
偶校验
×0:
无校验
附加奇偶校验?
0:
不附加
1:
附加
0:
读写RBR、THR
1:
读写除数寄存器
Ø线路状态寄存器LSR
0
TSRE
THRE
BI
FE
PE
OE
DR
接收缓冲器满?
0:
未满
1:
满
接收奇偶错?
0:
无错
1:
有错
接收格式错?
0:
无错
1:
有错
发送保持空?
0:
不空
1:
空
发送移位器空?
0:
不空,正在发
1:
空,发完
接收重叠错?
0:
无错;1:
有错
Ø中断允许寄存器IER
0
0
0
0
I0E
I3E
I1E
I2E
1:
允许Modem状态改变中断
1:
允许接收出错中断
1:
允许发送保持器空中断
1:
允许接收缓冲器满中断
Ø中断标识寄存器IIR(只读)
0
0
0
0
0
ID2
ID1E
IP
00:
接收出错中断
01:
接收缓冲器满中断
10:
发送保持器空中断
11:
Modem状态改变中断
有否未决中断?
0:
无
1:
有
是何中断?
Ø除数寄存器
用于设置波特率。
波特率=时钟频率÷(16×除数寄存器的值)。
若已知波特率,则:
除数寄存器的值=时钟频率÷(16×波特率)。
ØModem控制寄存器MCR
0
0
0
LOOP
OUT2
OUT1
RTS
DTR
1:
环路检测(自发自收)
1:
数据终端就绪
1:
请求发送
ØModem状态寄存器MSR
RLSD
RI
DSR
CTS
△RLSD
TERI
△DSR
△CTS
读出值为8250芯片的Modem部分4个输入引脚的状态。
“△”表示比较前次的读出值有改变。
3.8250在PC/XT机中的电路连接介绍
主板上有两片8250,分别对应串口1和串口2。
8250(对应COM1)的端口地址为3F8H~3FFH,其中断信号传到8259的IRQ4。
IRQ4的中断类型码为0CH。
8250(对应COM2)的端口地址为2F8H~2FFH,其中断信号传到8259的IRQ3。
IRQ3的中断类型码为0BH。
本实验仅操作串口1对应的8250(对应COM1),实现串行通信。
8259
4.程序要求
利用TURBOC++开发环境设计程序,实现如下功能:
(1)设置8250:
波特率=1200,奇校验,8位数据,1停止位;
按LOOP方式工作,自发自收;
允许接收中断。
(2)拦截8259IRQ4中断,在此中断中接收数据,在程序中显示数据。
(3)将程序改为两机之间通信,一机发送,另一机接收。
三实验环境
硬件环境:
PC机一台;串行通信终接头一个(用于一个串口自发自收);串行通信电缆一根(用于两机之间通信)。
软件环境:
操作系统不限,TURBOC++3.0。
四实验步骤
1.输入源程序
(LOOP方式),自收自发实验。
以下源程序仅供参考。
#include
#include
voidinit_RS232();//初始化COM1,包括8250和8259
voidinterruptfarmy_interupt();//本程序的中断响应函数
voidinterruptfar(*old_int_rs232)();//指向系统原来的中断响应函数
unsignedintold_IMR;//保存8259中断屏蔽寄存器IMR的原值,以便程序退出时复原
unsignedcharinput_buf[1024];//定义接收缓冲区
unsignedcharoutput_buf[1024]={0xa1,0xb2,0xc3,0xd4,0xe5,0xf6};//定义发送缓冲区及要发送的数据
unsignedintinput_buf_point;//指向当前存放接收数据的缓冲区位置
unsignedintoutput_buf_point;//指向当前要发送字节的缓冲区位置
intsend_OK;//收发完成标志。
0=收发未完成,1=收发完成
intoutput_bytes=6;//应发送的字节数,设要发送6个字节
voidmain()
{inti;
clrscr();//清屏
init_RS232();//设置8250、8259的初始化值
send_OK=0;//先置为0,表示收发未完成。
for(;;){
printf("Pressanykeytosend,\"q\"toexit\n\n");
if(getch()=='q')break;
printf("SendingData:
");//先把待发送的数据显示出来
for(i=0;iprintf("%02x",output_buf[i]);
};
printf("\n");
output_buf_point=0;//目前已发送了0个数据
input_buf_point=0;//目前收到0个数据
outportb(0x3f8,output_buf[output_buf_point++]);//发送第一个字符,后续字符将在前一个
//字符引起的中断响应中发送;
while(!
send_OK);//等待收发完成(收发工作在中断函数中进行)
printf("recevingData:
");//收发完成,把收到的数据显示出来
for(i=0;iprintf("\n\n");
}
outportb(0x21,old_IMR);//将8259的中断屏蔽寄存器IMR复原
setvect(0x0c,old_int_rs232);//将COM1的中断向量复原
}
voidinit_RS232()//8250、8259初始设置函数
{inti;
disable();//由于要修改系统的中断方式,故先关中断,保证下面的操作不影响系统工作
outportb(0x3fb,0x80);//10000000,写8250控制字,允许改动波特率
outportb(0x3f8,0x60);//设置波特率=1200bps.8250的时钟=1.8432MHz,除数=0060H=92,
outportb(0x3f9,0x00);//故波特率=1.8432/(16*92)=0.001252Mbps=1252bps.
outportb(0x3fb,0x2b);//00101011,再写控制字,锁定波特率,奇校验,8位数据,1停止位
outportb(0x3fc,0x13);//00010011,写Modem控制字,LOOP=1,RTS=1,DTS=1
outportb(0x3f9,0x05);//设置中断允许寄存器IER,允许接收中断
old_int_rs232=getvect(0x0c);//保存系统原中断向量。
COM1的中断类型码=12
setvect(0x0c,my_interupt);//将COM1的中断向量改为指向本程序中的中断函数
old_IMR=inportb(0x21);//读8259中断屏蔽寄存器IMR,其I/O地址为21H
i=old_IMR&0xef;//允许IRQ4中断,其他中断源维持系统的原设置不变
outportb(0x21,i);
outportb(0x20,0x20);//置位OCW2中的EOI,使中断服务寄存器自动清零,避免中断重复响应
enable();
}
voidinterruptmy_interupt()//COM1中断服务程序
{unsignedintcom_state;
unsignedintdata;
com_state=inportb(0x3fd);//读线路状态寄存器LSR
com_state=com_state&0x0007;
if(com_state==0x0001){//接收器满
data=inportb(0x3f8);//读取接收缓冲器
input_buf[input_buf_point++]=data;//将读得的数据存放到接收缓冲区
if(output_buf_pointdata=output_buf[output_buf_point++];//从发送缓冲区取得要发送的数据
outportb(0x3f8,data);//发送1字节
}
elsesend_OK=1;
}
//else{//接收出错,处理略
//}
outportb(0x20,0x20);//置位8259的OCW2中的EOI位,使中断服务寄存器自动清零,避免中断重复响应
}
2.运行程序,再完成如下内容
(1)改为7位数据格式发送,观察结果。
(2)修改程序,实现两机通信。
实验3基于DLL与HOOK技术的键盘消息拦截与读音
一实验目的
1.了解MFCDLL动态连接库的编程方法;
2.了解HOOK技术和回调函数的运行机制;
3.学习MFC中加载动态连接库的方法。
二实验指导
1.HOOK的基本概念
在Windows下,当硬件或软件产生中断时,系统会发送一个消息给用户程序。
因此,用户程序一般不使用中断,而是采用拦截系统消息的方法。
为了拦截不属于本应用程序的消息,拦截程序必须得到系统的认可,由系统安装成全局运行。
HOOK即通常所说的钩子。
实际上,HOOK就是上面所说的消息拦截程序段。
通过系统调用,把它挂入系统。
每当HOOK所希望的消息发出,在没有到达目的窗口前,HOOK程序就先捕获该消息,得到控制权。
HOOK程序先处理该消息,再向系统传递该消息。
也可以丢弃该消息。
系统维护着一个HOOK链,最近安装的HOOK总放在链的开始,从而得到优先执行。
全局HOOK必须在DLL(动态连接库)中。
2.HOOK函数的形式及其安装方法
HOOK函数在程序中应为全局函数,即:
HOOK函数不应写在一个类中。
HOOK函数是一个消息响应函数,由系统调用,应以回调函数的形式出现,其格式为:
LRESULT_declspec(dllexport)_stdcallCALLBACKKeyboardProc(
intnCode,//若为HC_ACTION,说明后两参数含有击键的消息
WPARAMwParam,//虚键码
LPARAMlParam//击键的有关信息,如重复次数等
)
写好HOOK函数后,应进行安装,才能得到系统的回调。
安装HOOK的函数为:
HHOOKSetWindowsHookEx(
intidHook,//钩子的类型,按键为WH_KEYBOARD
HOOKPROClpfn,//钩子函数的地址
HINSTANCEhMod,//包含钩子函数的模块句柄
DWORDdwThreadId//指定监视的线程。
若为NULL,则为全局钩子
);
3.程序要求
运用MFC开发环境设计程序,实现如下功能:
(1)编写含有按键HOOK的DLL,要求当按键时,能读出按键名称
(2)编写安装DLL的应用程序。
三实验环境
硬件环境:
PC机一台;
软件环境:
WindowsXP操作系统,VC++6.0,26段声音文件A.WAV,……,Z.WAV。
四实验步骤
1.建立DLL
(1)启动VC++,选File\New,在Project选卡中按如下操作:
(2)进入MFCAppWizard_step1of1,按如下操作:
(3)在KeyHook.h文件中添加代码(见粗体字部分):
……
LRESULT_declspec(dllexport)_stdcallCALLBACKKeyboardProc(
intnCode,
WPARAMwParam,
LPARAMlParam
);
BOOL_declspec(dllexport)_stdcallinstallhook();
classCKeyHookApp:
publicCWinApp
{
……
(4)在KeyHook.cpp文件中添加代码(见粗体字部分):
#include"stdafx.h"
#include"KeyHook.h"
#include"mmsystem.h"
#ifdef_DEBUG
……
#endif
#pragmadata_seg(".SHARDAT")
staticHHOOKhkb=NULL;//定义HOOK句柄
#pragmadata_seg()
HINSTANCEhInst;//定义本实例的句柄
BOOL_declspec(dllexport)_stdcallinstallhook()//安装HOOK的函数
{
hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hInst,0);
returnTRUE;
}
BOOL_declspec(dllexport)UnHook()//卸载HOOK的函数
{
BOOLunhooked=UnhookWindowsHookEx(hkb);
returnunhooked;
}
LRESULT_declspec(dllexport)_stdcallCALLBACKKeyboardProc(//HOOK回调函数
IntnCode,WPARAMwParam,LPARAMlParam)
{
if(((DWORD)lParam&0x40000000)&&(HC_ACTION==nCode))
{
if(wParam>='A'&&wParam<='Z'){
charKeyName[20],temp[10];
strcpy(KeyName,"sound\\");
temp[0]=wParam;