WindowsAPI.docx
- 文档编号:22898997
- 上传时间:2023-04-28
- 格式:DOCX
- 页数:13
- 大小:19.79KB
WindowsAPI.docx
《WindowsAPI.docx》由会员分享,可在线阅读,更多相关《WindowsAPI.docx(13页珍藏版)》请在冰豆网上搜索。
WindowsAPI
1WindowsAPI通信函数方法
与通信有关的WindowsAPI函数共有26个,但主要有关的有:
CreateFile()用“comn”(n为串口号)作为文件名就可以打开串口。
ReadFile()读串口。
WriteFile()写串口。
CloseHandle()关闭串口句柄。
初始化时应注意CreateFile()函数中串口共享方式应设为0,串口为不可共享设备,其它与一般文件读写类似。
以下给出API实现的源代码。
1.1发送的例程
//声明全局变量
HANDLEm_hIDComDev;
OVERLAPPEDm_OverlappedRead,m_OverlappedWrite;
//初始化串口
voidCSerialAPIView:
:
OnInitialUpdate()
{
CView:
:
OnInitialUpdate();
CharszComParams[50];
DCBdcb;
Memset(&m_OverlappedRead,0,sizeof(OVERLAPPED));
Memset(&m_OverlappedWrite,0,sizeof(OVERLAPPED));
m_hIDComDev=NULL;
m_hIDComDev=CreateFile(“COM2”,GENERIC_READ│GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL│FILE_FLAG_OVERLAPPED,NULL);
if(m_hIDComDev==NULL)
{
AfxMessageBox(“Cannotopenserialport!
”);
gotoendd;
}
memset(&m_OverlappedRead,0,sizeof(OVERLAPPED));
memset(&m_OverlappedWrite,0,sizeof(OVERLAPPED));
COMMTIMEOUTSCommTimeOuts;
CommTimeOuts.ReadIntervalTimeout=0×FFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier=0;
CommTimeOuts.ReadTotalTimeoutConstant=0;
CommTimeOuts.WriteTotalTimeoutMultiplier=0;
CommTimeOuts.WriteTotalTimeoutConstant=5000;
SetCommTimeouts(m_hIDComDev,&CommTimeOuts);
Wsprintf(szComparams,“COM2:
9600,n,8,1”);
m_OverlappedRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
m_OverlappedWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
dcb.DCBlength=sizeof(DCB);
GetCommState(m_hIDComDev,&dcb);
dcb.BaudRate=9600;
dcb.ByteSize=8;
unsignedcharucSet;
ucSet=(unsignedchar)((FC_RTSCTS&FC_DTRDSR)!
=0);
ucSet=(unsignedchar)((FC_RTSCTS&FC_RTSCTS)!
=0);
ucSet=(unsignedchar)((FC_RTSCTS&FC_XONXOFF)!
=0);
if(!
SetCommState(m_hIDComDev,&dcb)‖
!
SetupComm(m_hIDComDev,10000,10000)‖
m_OverlappedRead.hEvent==NULL‖
m_OverlappedWrite.hEvent==NULL)
{
DWORDdwError=GetLastError();
if(m_OverlappedRead.hEvent!
=NULL)CloseHandle(m_OverlappedRead.hEvent);
if(m_OverlappedWrite.hEvent!
=NULL)CloseHandle(m_OverlappedWrite.hEvent);
CloseHandle(m_hIDComDev);
}
endd:
;
}
//发送数据
voidCSerialAPIView:
:
OnSend()
{
charszMessage[20]=“thankyouverymuch”;
DWORDdwBytesWritten;
for(inti=0;i<sizeof(szMessage);i++)
{
WriteFile(m_hIDComDev,(LPSTR)&szMessage[i],1,&dwBytesWritten,&m_OverlappedWrite);
if(WaitForSingleObject(m_OverlapperWrite,hEvent,1000))dwBytesWritten=0;
else{
GentOverlappedResult(m_hIDComDev,&m_OverlappedWrite,&dwBytesWritten,FALSE);
m_OverlappedWrite.Offset+=dwBytesWritten;
}
dwBytesWritten++;
}
}
1.2接收例程
DCBComDcb;//设备控制块
HANDLEhCom;//globalhandle
hCom=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hCom==INVALID_HANDLE_VALUE)
{
AfxMessageBox("无法打开串行口");
}
else
{
COMMTIMEOUTSCommTimeOuts;
SetCommMask(hCom,EV_RXCHAR);
SetupComm(hCom,4096,4096);/*设置收发缓冲区尺寸为4K*/
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|
PURGE_TXCLEAR|PURGE_RXCLEAR);//清收发缓冲区
//以下初始化结构变量CommTimeOuts,设置超时参数CommTimeOuts.ReadIntervalTimeout=0×FFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier=0;
CommTimeOuts.ReadTotalTimeoutConstant=4000;
CommTimeOuts.WriteTotalTimeoutMultiplier=0;
CommTimeOuts.WriteTotalTimeoutConstant=4000;
SetCommTimeouts(hCom,&CommTimeOuts);//设置超时参数
ComDcb.DCBlength=sizeof(DCB);
GetCommState(hCom,&ComDcb);//获取当前参数
ComDcb.BaudRate=9600;//波特率
ComDcb.ByteSize=8;//数据位
ComDcb.Parity=0;/*校验0~4=no,odd,even,mark,space*/
SetCommState(hCom,&ComDcb);
}//设置新的通信参数
接收可用定时器或线程等
DWORDdRead,dReadNum;
unsignedcharbuff[200];
dRead=ReadFile(hCom,buff,100,&dReadNum,NULL);//接收100个字符,
//dReadNum为实际接收字节数
2利用端口函数直接操作
这种方式主要是采用两个端口函数_inp(),_outp()实现对串口的读写,其中读端口函数的原型为:
int_inp(unsignedshotport)
该函数从端口读取一个字节,端口号为0~65535。
写端口的函数原型为:
int_outp(unsignedshotport,intdatabyte)
该函数向指定端口写入一个字节。
不同的计算机串口地址可能不一样,通过向串口的控制及收发寄存器进行读写,可以实现灵活的串口通信功能,由于涉及具体的硬件电路讨论比较复杂,在此不加赘述。
3MSComm控件
MSComm控件是微软开发的专用通信控件,封装了串口的所有功能,使用很方便,但在实际应用中要小心对其属性进行配置。
下面详细说明该类应用方法。
3.1MSComm控件的属性
CommPort:
设置串口号,类型short:
1-comm12-comm2.
Settings:
设置串口通信参数,类型CString:
B波特率,P奇偶性(N无校验,E偶校验,O奇校验),D字节有效位数,S停止位。
PortOpen:
设置或返回串口状态,类型BOOL:
TURE打开,FALSE关闭。
InputMode:
设置从接收缓冲区读取数据的格式,类型long:
0-Text1-Bin。
Input:
从接收缓冲区读取数据,类型VARIANT。
InBufferCount:
接收缓冲区中的字节数,类型:
short。
InBufferSize:
接收缓冲区的大小,类型:
short。
Output:
向发送缓冲区写入数据,类型:
VARIANT。
OutBufferCount:
发送缓冲区中的字节数,类型:
short。
OutBufferSize:
发送缓冲区的大小,类型:
short。
InputLen:
设置或返回Input读出的字节数,类型:
short。
CommEvent:
串口事件,类型:
short。
3.2程序示例
串口初始化
if(!
m_comm.GetPortOpen())
m_comm.SetPortOpen(TURE);/*打开串口*/
m_comm.SetSettings("4800,n,8,1");/*串口参数设置*/
m_comm.SetInputMode(0);/*设置TEXT缓冲区输入方式*/
m_comm.SetRthresHold
(1);/*每接收一个字符则激发OnComm()事件*/
接收数据
m_comm.SetInputLen
(1);/*每次读取一个字符
VARINATV1=m_comm.GetInput();
/*读入字符*/
m_V1=V1.bstrval;
发送字符m_comm.SetOutput(Colevariant("Hello");/*发送“Hello”*/
3.3注意
SetOutput方法可以传输文本数据或二进制数据。
用SetOutput方法传输文本数据,必须定义一个包含一个字符串的Variant。
发送二进制数据,必须传递一个包含字节数组的Variant到Output属性。
正常情况下,如果发送一个ANSI字符串到应用程序,可以以文本数据的形式发送。
如果发送包含嵌入控制字符、Null字符等的数据,要以二进制形式发送。
此处望引起读者注意,笔者曾经在此犯错。
4VC++类CSerial
4.1串行通信类CSerial简介
Cserial是由MuMegaTechnologies公司提供的一个免费的VC++类,可方便地实现串行通信。
以下为该类定义的说明部分。
classCSerial
{
public:
CSerial();
~CSerial();
BOOLOpen(intnPort=2,intnBaud=9600);
BOOLClose(void);
intReadData(void*,int);
intSendData(constchar*,int);
intReadDataWaiting(void);
BOOLIsOpened(void){return(m_bOpened);}
protected:
BOOLWriteCommByte(unsignedchar);
HANDLEm_hIDComDev;
OVERLAPPEDm_OverlappedRead,m_OverlappedWrite;
BOOLm_bOpened;
}
4.2串行通信类Cserial成员函数简介
1.CSerial:
:
Cserial是类构造函数,不带参数,负责初始化所有类成员变量。
2.CSerial:
:
Open这个成员函数打开通信端口。
带两个参数,第一个是埠号,有效值是1到4,第二个参数是波特率,返回一个布尔量。
3.CSerial:
:
Close函数关闭通信端口。
类析构函数调用这个函数,所以可不用显式调用这个函数。
4.CSerial:
:
SendData函数把数据从一个缓冲区写到串行端口。
它所带的第一个参数是缓冲区指针,其中包含要被发送的资料;这个函数返回已写到端口的实际字节数。
5.CSerial:
:
ReadDataWaiting函数返回等待在通信端口缓冲区中的数据,不带参数。
6.CSerial:
:
ReadData函数从端口接收缓冲区读入数据。
第一个参数是void*缓冲区指针,资料将被放入该缓冲区;第二个参数是个整数值,给出缓冲区的大小。
4.3应用VC类的一个实例
1.固定式EBM气溶胶灭火系统简介
固定式EBM气溶胶灭火装置分区启动器是专为EBM灭火装置设计的自动控制设备。
可与两线制感温、感烟探测器配套使用,当监测部位发生火情时,探测器发出电信号给分区启动器,经逻辑判断后发出声、光报警,延时后自动启动EBM灭火装置。
为了便于火灾事故的事后分析,需对重要的火警事件和关键性操作进行记录,记录应能从PC机读出来;PC机能控制、协调整个系统的工作,这些都涉及通信。
本例中启动器采用RS-485通信接口,系统为主从式网络,PC机为上位机。
具体的通信协议为:
(1)下位机定时向上传送记录的事件;
(2)应答发送,即PC机要得到最新事件记录,而传送时间未到时,PC机发送命令,下位机接收命令后,把最新记录传给上位机;(3)上位机发送其它命令如校时、启动、停止、手/自动等。
2.通信程序设计
部分上位机程序
(1)发送命令字程序,代码如下
voidCCommDlg:
:
OnSend()
{
CSerialSerial;
//构造串口类,初始化串行口
if(Serial.Open(2,9600))//if-1
//打开串行口2,波特率为9600bps
{
staticcharszMessage[]="0";
//命令码(可定义各种命令码)
intnBytesSent;
intcount=0;
resend:
nBytesSent=Serial.SendData(szMessage,strlen(szMessage));
//发送命令码
charrdMessage[20];
if(Serial.ReadDataWaiting())//if-2
{
Serial.ReadData(rdMessage,88);
//rdMessage定义接收字节存储区,为全局变量//
if((rdMessage[0]!
=0x7f)&&(count<3))
{
count++;
gotoresend
}
if(count>=3)
MessageBox(“发送命令字失败”);
}
else//if-2
MessageBox("接收数据错误");
}
else//if-1
MessageBox("串行口打开失败");
}
下位机通信程序:
#include
#include
#include
#definecount9
#definecom_code0x00
#definecom_code10xff
unsignedcharbuffer[count];
intpo,year,month,date,hour;
intminute,second,recordID;
intsum;
main()
{
…
/*初始化串口和定时器*/
TMOD=0×20;
TH1=0×fd;
TR1=0×01;
ET1=0×00;
ES=1;
EA=1;
/*待发送数据送缓冲区*/
buffer[0]=0×ff;//数据特征码
buffer[1]=count+1;//数据长度
buffer[2]=year;//年
buffer[3]=month;//月
buffer[4]=date;//日
buffer[5]=hour;//时
buffer[6]=minute;//分
buffer[7]=second;//秒
buffer[8]=recordID;//事件号
for(po=0;po
sum+=buffer[po];
buffer[9]=sum;//校验和
…
}
/*发送中断服务程序*/
voidsend(void)interrupt4using1
{
inti;
RI=0;
EA=0;
do
{
for(i=0;i<=count;i++)
{
SBUF=buffer[i];//发送数据和校验和//
while(TI==0);
TI=0;
}
while(RI==0);
RI=0;
}while(SBUF!
=0);//主机接收不正确,重新发送//
EA=1;
Return;
}
5应用总结
根据不同需要,选择合适的方法。
我们选用的用VC++类实现的上位机和下位机的串行通信方法具有使用简单、编写程序方便的特点。
经过半年多应用于EBM灭火系统的情况来看,该方法实现的系统运行稳定可靠,是一种值得推广的简单易行的通信方法。
参考文献
1KateGregoryVisualC++6开发使用手册.北京:
机械工业出版社,1999
2何立民.单片机的C语言应用程序设计.北京:
北京航空航天大学出版社,1997
3马风格.VC控件与串行通讯.1999现代计算机,2000(4)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- WindowsAPI