论坛登陆 用户: 密码:
联系我们
设为首页
加入收藏
业界新闻 网络编程 程序开发 网页图象 聊天通讯 软件应用 网络安全 硬件学堂 教育频道 站长club
  ·推荐新闻
 
·美前任官员认为amd告倒英特
·搜索引擎关键字排行简介
·网站优化教程(一)
·msn近期遭受木马病毒骚扰 用
·用qq管理你的系统^_^ 
·测评中心金山毒霸联合发布7
·qq群聊实名 普通用户不受影
·雅虎思科联手推数字邮件签名
·这18条背下来没人敢和你忽悠
·自己动手,拯救丢失的硬盘数
  ·资料搜索
 
  ·相关文章
·深度探索c++对象模型(完结篇)
·深度探索c++对象模型(10)
·深度探索c++对象模型(9)
·深度探索c++对象模型(8)
·深度探索c++对象模型(7)
·深度探索c++对象模型(6)
·深度探索c++对象模型(5)
·深度探索c++对象模型(4)
·深度探索c++对象模型(3)
·深度探索c++对象模型(2)
  ·热门新闻
首页>>程序开发>>c/c++区>>文章正文

用builder c++设计串行口com1或com2的读写操作


 日期:2005-7-18 9:13:56     来源:易特网络技术   编辑:黑鹰  点击:

  一个通讯类(对串口的读写),可以不用做修改就用在程序中

 

 

 

 

 

 

tserialport.h

#ifndef __serialport_h__
#define __serialport_h__

#define wm_comm_break_detected wm_user+1 // a break was detected on input.
#define wm_comm_cts_detected wm_user+2 // the cts (clear-to-sennd) sig
nal changed state.
#define wm_comm_dsr_detected wm_user+3 // the dsr (data-set-reaady) si
gnal changed state.
#define wm_comm_err_detected wm_user+4 // a line-status error ooccurre
d. line-status errors are ce_frame, ce_overrun, and ce_rxparity.

#define wm_comm_ring_detected wm_user+5 // a ring indicator was etec ted.
#define wm_comm_rlsd_detected wm_user+6 // the rlsd (receive-lin
-sig
nal-detect) signal changed state.
#define wm_comm_rxchar wm_user+7 // a character w
s received and pl
aced in the input buffer.
#define wm_comm_rxflag_detected wm_user+8 // the event character w
s
received and placed in the input buffer.
#define wm_comm_txempty_detected wm_user+9 // the last character in
th
e output buffer was sent.

class tserialport
{
public:
// contruction and destruction
tserialport();
virtual ~tserialport();

// port initialisation
bool initport(tform* pportowner, uint portnr = 1, uint baud =
19200,
char parity = 'n', uint databits = 8, uint stopsbits = 1, dword dwcom
mevents = ev_rxchar | ev_cts, uint nbuffersize = 512);

// start/stop comm watching
bool startmonitoring();
bool restartmonitoring();
bool stopmonitoring();

dword getwritebuffersize();
dword getcommevents();
dcb getdcb();

void writetoport(char* string);

protected:
// protected memberfunctions
void processerrormessage(char* errortext);
static dword _stdcall commthread(lpvoid pparam);
static void receivechar(tserialport* port, comstat comstat);
static void writechar(tserialport* port);

// thread
handle m_hthread;

// synchronisation objects
critical_section m_cscommunicationsync;
bool m_bthreadalive;

// handles
handle m_hshutdownevent;
handle m_hcomm;
handle m_hwriteevent;

// event array.
// one element is used for each event. there are two event handles fo
r each port.
// a write event and a receive character event which is located in th
e overlapped structure (m_ov.hevent).
// there is a general shutdown when the port is closed.
handle m_heventarray[3];

// structures
overlapped m_ov;
commtimeouts m_commtimeouts;
dcb m_dcb;

// owner window
tform* m_powner;

// misc
uint m_nportnr;
char* m_szwritebuffer;
dword m_dwcommevents;
dword m_nwritebuffersize;
};

#endif __serialport_h__


tserialport.cpp

#include
#pragma hdrstop
#include "serialport.h"
#include
#include
#pragma package(smart_init)
//
// constructor
//
tserialport::tserialport()
{
m_hcomm = null;

// initialize overlapped structure members to zero
m_ov.offset = 0;
m_ov.offsethigh = 0;

// create events
m_ov.hevent = null;
m_hwriteevent = null;
m_hshutdownevent = null;

m_szwritebuffer = null;

m_bthreadalive = false;
}

//
// delete dynamic memory
//
tserialport::~tserialport()
{
do
{
setevent(m_hshutdownevent);
} while (m_bthreadalive);

delete [] m_szwritebuffer;
}

//
// initialize the port. this can be port 1 to 4.
//
bool tserialport::initport(tform* pportowner, // the owner (cwnd) of t
he port (receives message)
uint portnr,
/ portnumber (1..4)
uint baud,
/ baudrate
char parity,
/ parity
uint databits,
/ databits
uint stopbits,
/ stopbits
dword dwcommevents, // ev_rx
har, ev_cts etc
uint writebuffersize)
/ size to the writebuffer
{
assert(portnr > 0 && portnr < 5);
assert(pportowner != null);

// if the thread is alive: kill
if (m_bthreadalive)
{
do
{
setevent(m_hshutdownevent);
} while (m_bthreadalive);
}

// create events
if (m_ov.hevent != null)
resetevent(m_ov.hevent);
m_ov.hevent = createevent(null, true, false, null);

if (m_hwriteevent != null)
resetevent(m_hwriteevent);
m_hwriteevent = createevent(null, true, false, null);

if (m_hshutdownevent != null)
resetevent(m_hshutdownevent);
m_hshutdownevent = createevent(null, true, false, null);

// initialize the event objects
m_heventarray[0] = m_hshutdownevent; // highest priority
m_heventarray[1] = m_ov.hevent;
m_heventarray[2] = m_hwriteevent;

// initialize critical section
initializecriticalsection(&m_cscommunicationsync);

// set buffersize for writing and save the owner
m_powner = pportowner;

if (m_szwritebuffer != null)
delete [] m_szwritebuffer;
m_szwritebuffer = new char[writebuffersize];

m_nportnr = portnr;

m_nwritebuffersize = writebuffersize;
m_dwcommevents = dwcommevents;

bool bresult = false;
char *szport = new char[50];
char *szbaud = new char[50];

// now it critical!
entercriticalsection(&m_cscommunicationsync);

// if the port is already opened: close it
if (m_hcomm != null)
{
closehandle(m_hcomm);
m_hcomm = null;
}

// prepare port strings
sprintf(szport, "com%d", portnr);
sprintf(szbaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, da
tabits, stopbits);

// get a handle to the port
m_hcomm = createfile(szport,
/ communication port string (comx)

generic_read | generic_write,
/ read/write types
0,
/ comm devices must be opened with exclusive acce
ss
ss
null,
/ no security attributes
open_existing,
/ comm devices must use open_existing
file_flag_overlapped,
/ async i/o
0);
/ template must be 0 for comm devices

if (m_hcomm == invalid_handle_value)
{
// port not found
delete [] szport;
delete [] szbaud;

return false;
}

// set the timeout values
m_commtimeouts.readintervaltimeout = 1000;
m_commtimeouts.readtotaltimeoutmultiplier = 1000;
m_commtimeouts.readtotaltimeoutconstant = 1000;
m_commtimeouts.writetotaltimeoutmultiplier = 1000;
m_commtimeouts.writetotaltimeoutconstant = 1000;

// configure
if (setcommtimeouts(m_hcomm, &m_commtimeouts))
{
if (setcommmask(m_hcomm, dwcommevents))
{
if (getcommstate(m_hcomm, &m_dcb))
{
m_dcb.frtscontrol = rts_control_enable;
/ set rts bit high!
if (buildcommdcb(szbaud, &m_dcb))
{
if (setcommstate(m_hcomm, &m_dcb))
; // normal operation... continu

else
processerrormessage("setcommstat
()");
}
else
processerrormessage("buildcommdcb()");
}
else
processerrormessage("getcommstate()");
}
else
processerrormessage("setcommmask()");
}
else
processerrormessage("setcommtimeouts()");

delete [] szport;
delete [] szbaud;

// flush the port
purgecomm(m_hcomm, purge_rxclear | purge_txclear | purge_rxabort | pu
rge_txabort);

// release critical section
leavecriticalsection(&m_cscommunicationsync);

return true;
}

//
// the commthread function.
//
dword _stdcall tserialport::commthread(lpvoid pparam)
{
// cast the void pointer passed to the thread back to
// a pointer of tserialport class
tserialport *port = (tserialport*)pparam;

// set the status variable in the dialog class to
// true to indicate the thread is running.
port->m_bthreadalive = true;

// misc. variables
dword bytestransfered = 0;
dword event = 0;
dword commevent = 0;
dword dwerror = 0;
comstat comstat;
bool bresult = true;

// clear comm buffers at startup
if (port->m_hcomm) // check if the port is opened
purgecomm(port->m_hcomm, purge_rxclear | purge_txclear | purge_r
abo
rt | purge_txabort);

// begin forever loop. this loop will run as long as the thread is a
live.
for (;;)
{

// make a call to waitcommevent(). this call will return immedi
tly

// because our port was created as an async port (file_flag_over
app
ed
// and an m_overlappedstructerlapped structure specified). this
cal
l will cause the
// m_overlappedstructerlapped element m_overlappedstruct.hevent,
whi
ch is part of the m_heventarray to
// be placed in a non-signeled state if there are no bytes avail
ble
to be read,
// or to a signeled state if there are bytes available. if this
eve
nt handle
// is set to the non-signeled state, it will be set to signeled
hen
a
// character arrives at the port.

// we do this for each port!

bresult = waitcommevent(port->m_hcomm, &event, &port->m_ov);

if (!bresult)
{
// if waitcommevent() returns false, process the last er
or to dete
rmin
rmin
// the reason..
switch (dwerror = getlasterror())
{
case error_io_pending:
{
// this is a normal return value if ther
are no bytes
// to read at the port.
// do nothing and continue
break;
}
case 87:
{
// under windows nt, this value is retur
ed for some reason.
// i have not investigated why, but it i
also a valid reply
// also do nothing and continue.
break;
}
default:
{
// all other error codes indicate a seri
us error has
// occured. process this error.
port->processerrormessage("waitcommevent
)");
break;
}
}
}
else
{
// if waitcommevent() returns true, check to be sure the
e are
// actually bytes in the buffer to read.
//
// if you are reading more than one byte at a time from
he buffer

// (which this program does not do) you will have the si
uation occ
ur
// where the first byte to arrive will cause the waitfor
ultipleobj
ects()
// function to stop waiting. the waitformultipleobjects
) function

// resets the event handle in m_overlappedstruct.hevent
o the non-
signelead state
// as it returns.
//
// if in the time between the reset of this event and th
call to
// readfile() more bytes arrive, the m_overlappedstruct.
event hand
le will be set again
// to the signeled state. when the call to readfile() oc
urs, it wi
ll
// read all of the bytes from the buffer, and the progra
will
// loop back around to waitcommevent().
//
// at this point you will be in the situation where m_ov
rlappedstr
uct.hevent is set,
// but there are no bytes available to read. if you pro
eed and ca
ll
// readfile(), it will return immediatly due to the asyn
port setu
p, but
// getoverlappedresults() will not return until the next
character
arrives.
//
// it is not desirable for the getoverlappedresults() fu
ction to b
e in
// this state. the thread shutdown event (event 0) and
he writefi
le()
// event (event2) will not work if the thread is blocked
by getover
lappedresults().
//
// the solution to this is to check the buffer with a ca
l to clear
commerror().
// this call will reset the event handle, and if there a
e no bytes
to read
// we can loop back through waitcommevent() again, then
roceed.
// if there are really bytes to read, do nothing and pro
eed.

bresult = clearcommerror(port->m_hcomm, &dwerror, &comst
t);

if (comstat.cbinque == 0)
continue;
} // end if bresult

// main wait function. this function will normally block the th
ead


// until one of nine events occur that require action.
event = waitformultipleobjects(3, port->m_heventarray, false, in
ini
te);

switch (event)
{
case 0:
{
// shutdown event. this is event zero so it wil
be
// the higest priority and be serviced first.

port->m_bthreadalive = false;

// kill this thread. break is not needed, but m
kes me feel bette
r.
exitthread(100);
break;
}
case 1: // read event
{
getcommmask(port->m_hcomm, &commevent);
if (commevent & ev_cts)
::sendmessage(port->m_powner->handle, wm
comm_cts_detected, (wpar
am) 0, (lparam) port->m_nportnr);
if (commevent & ev_rxflag)
::sendmessage(port->m_powner->handle, wm
comm_rxflag_detected, (w
param) 0, (lparam) port->m_nportnr);
if (commevent & ev_break)
::sendmessage(port->m_powner->handle, wm
comm_break_detected, (wp
aram) 0, (lparam) port->m_nportnr);
if (commevent & ev_err)
::sendmessage(port->m_powner->handle, wm
comm_err_detected, (wpar
am) 0, (lparam) port->m_nportnr);
if (commevent & ev_ring)
::sendmessage(port->m_powner->handle, wm
comm_ring_detected, (wpa
ram) 0, (lparam) port->m_nportnr);

if (commevent & ev_rxchar)
// receive character event from port.
receivechar(port, comstat);

break;
}
case 2: // write event
{
// write character event from port
writechar(port);
break;
}

} // end switch

} // close forever loop

return 0;
}

//
//
// start comm watching
//
bool tserialport::startmonitoring()
{
dword lpthreadid;
m_hthread =createthread(null,
0,
commthread,
this,
0,
&lpthreadid);
if(m_hthread==null)
{
processerrormessage("create thread error");
return false;
}
return true;
}

//
// restart the comm thread
//
//
bool tserialport::restartmonitoring()
{
resumethread(m_hthread);
return true;
}

//
// suspend the comm thread
//
bool tserialport::stopmonitoring()
{
suspendthread(m_hthread);
return true;
}

//
// if there is a error, give the right message
//
void tserialport::processerrormessage(char* errortext)
{
char *temp = new char[200];


lpvoid lpmsgbuf;

formatmessage(
format_message_allocate_buffer | format_message_from_system,
null,
getlasterror(),
makelangid(lang_neutral, sublang_default), // default language
(lptstr) &lpmsgbuf,
0,
null
);

sprintf(temp, "warning: %s failed with the following error: \n%s\npo
rt: %d\n", (char*)errortext, lpmsgbuf, m_nportnr);
application->messagebox(temp, "application error", mb_iconstop);

localfree(lpmsgbuf);
delete[] temp;
}

//
// write a character.
//
void tserialport::writechar(tserialport* port)
{
bool bwrite = true;
bool bresult = true;

dword bytessent = 0;

resetevent(port->m_hwriteevent);

// gain ownership of the critical section
entercriticalsection(&port->m_cscommunicationsync);

if (bwrite)
{
// initailize variables
port->m_ov.offset = 0;
port->m_ov.offsethigh = 0;

// clear buffer
purgecomm(port->m_hcomm, purge_rxclear | purge_txclear | purge_r
abo
abo
rt | purge_txabort);

bresult = writefile(port->m_hcomm,
/ handle to comm port
port->m_szwritebuffer, /
/ pointer to message buffer in call
ing finction
strlen((char*)port->m_sz
ritebuffer), // length of message to s
end
&bytessent,
/ where to store the number of bytes sent
&port->m_ov);
/ overlapped structure

// deal with any error codes
if (!bresult)
{
dword dwerror = getlasterror();
switch (dwerror)
{
case error_io_pending:
{
// continue to getoverlappedresu
ts()
bytessent = 0;
bwrite = false;
break;
}
default:
{
// all other error codes
port->processerrormessage("write
ile()");
}
}
}
else
{
leavecriticalsection(&port->m_cscommunicationsync);
}
} // end if(bwrite)

if (!bwrite)
{
bwrite = true;

bresult = getoverlappedresult(port->m_hcomm, // handle to com
port

&port-
m_ov, // overlapped structure
&bytes
ent, // stores number of bytes sent
true);
// wait flag

leavecriticalsection(&port->m_cscommunicationsync);

// deal with the error code
if (!bresult)
{
port->processerrormessage("getoverlappedresults() in wri
efile()");

}
} // end if (!bwrite)

// verify that the data size send equals what we tried to send
if (bytessent != strlen((char*)port->m_szwritebuffer))
{
printf("warning: writefile() error.. bytes sent: %d; message len
th:
%d\n", bytessent, strlen((char*)port->m_szwritebuffer));
}
}

//
// character received. inform the owner
//
void tserialport::receivechar(tserialport* port, comstat comstat)
{
bool bread = true;
bool bresult = true;
dword dwerror = 0;
dword bytesread = 0;
unsigned char rxbuff;


for (;;)
{
// gain ownership of the comm port critical section.
// this process guarantees no other part of this program
// is using the port object.

entercriticalsection(&port->m_cscommunicationsync);

// clearcommerror() will update the comstat structure and
// clear any other errors.

bresult = clearcommerror(port->m_hcomm, &dwerror, &comstat);

leavecriticalsection(&port->m_cscommunicationsync);

// start forever loop. i use this type of loop because i
// do not know at runtime how many loops this will have to
// run. my solution is to start a forever loop and to
// break out of it when i have processed all of the
// data available. be careful with this approach and
// be sure your loop will exit.
// my reasons for this are not as clear in this sample
// as it is in my production code, but i have found this
// solutiion to be the most efficient way to do this.

if (comstat.cbinque == 0)
{
// break out when all bytes have been read
break;
}

entercriticalsection(&port->m_cscommunicationsync);

if (bread)
{
bresult = readfile(port->m_hcomm, // handl
to comm port
&rxbuff,
/ rx buffer pointer
1,
/ read one byte
&bytesread,
/ stores number of bytes read
&port->m_ov);
/ pointer to the m_ov structure
// deal with the error code
if (!bresult)
{
switch (dwerror = getlasterror())
{
case error_io_pending:
{
// asynchronous i/o is s
ill in progress
// proceed on to getover
appedresults();
bread = false;
break;
}
default:
{
// another error has occ
red. process this error.
port->processerrormessag
("readfile()");
break;
}
}
}
else
{
// readfile() returned complete. it is not neces
ary to call getov
erlappedresults()
bread = true;
}
} // close if (bread)

if (!bread)
{
bread = true;
bresult = getoverlappedresult(port->m_hcomm, // handl
to comm port


&port->m_ov, // overlapped structure

&bytesread, // stores number of bytes read

true); // wait flag

// deal with the error code
if (!bresult)
{
port->processerrormessage("getoverlappedresults(
in readfile()");

}
} // close if (!bread)

leavecriticalsection(&port->m_cscommunicationsync);

// notify parent that a byte was received
::sendmessage((port->m_powner)->handle, wm_comm_rxchar, (wparam)
rxb
uff, (lparam) port->m_nportnr);
} // end forever loop

}


//
// write a string to the port
//
void tserialport::writetoport(char* string)
{
assert(m_hcomm != 0);

memset(m_szwritebuffer, 0, sizeof(m_szwritebuffer));
strcpy(m_szwritebuffer, string);

// set event for write
setevent(m_hwriteevent);
}

//
// return the device control block
//
dcb tserialport::getdcb()
{
return m_dcb;
}


//
// return the communication event masks
//
dword tserialport::getcommevents()
{
return m_dwcommevents;
}

//
// return the output buffer size
//
dword tserialport::getwritebuffersize()
{
return m_nwritebuffersize;
}

//----------------------------------------------------------------

上一篇:控制台窗口界面的编程控制(六)
下一篇:没有了
[发送给好友] [打印本页] [关闭窗口] [返回顶部转载请注明来源:http://www.iyit.net
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
责任编辑: 黑鹰 投稿作者: 易特网络
信息来源: 易特网络技术 录入时间: 2005-7-18 9:13:56
浏览次数: 投稿信箱: shtghy@163.com
设置首页 - 版权声明 - 广告服务 - 关于我们 - 联系我们 - 友情连接
copyrights ©2004-2005 iyit.net all rights reserved. 网站合作、广告联系qq:147007642、466949678
易特网络技术 点击这里给我发消息