/*
** FILENAME CSerialPort.cpp
**
** PURPOSE This class can read, write and watch one serial port.
** It sends messages to its owner when something happends on the port
** The class creates a thread for reading and writing so the main
** program is not blocked.
**
** CREATION DATE 15-09-1997
** LAST MODIFICATION 12-11-1997
**
** AUTHOR Remon Spekreijse
**
**
*/
#include "stdafx.h"
#include "SerialPort.h"
#include <assert.h>
int m_nComArray[20];
//
// Constructor
//
CSerialPort::CSerialPort()///构造函数
{
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;
m_nWriteSize=1;///
m_bIsSuspened = FALSE;///
}
//
// Delete dynamic memory
//
CSerialPort::~CSerialPort()///析构函数
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
// if the port is still opened: close it
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
// Close Handles
if(m_hShutdownEvent!=NULL)
CloseHandle( m_hShutdownEvent);
if(m_ov.hEvent!=NULL)
CloseHandle( m_ov.hEvent );
if(m_hWriteEvent!=NULL)
CloseHandle( m_hWriteEvent );
TRACE("Thread ended\n");
delete [] m_szWriteBuffer;
}
//
// Initialize the port. This can be port 1 to MaxSerialPortNum.
///初始化串口。只能是1-MaxSerialPortNum
//
BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
UINT portnr, // portnumber (1..MaxSerialPortNum)
UINT baud, // baudrate
char parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
UINT writebuffersize) // size to the writebuffer
{
assert(portnr > 0 && portnr < MaxSerialPortNum+1);///add by itas109 2014-01-09
assert(pPortOwner != NULL);
// if the thread is alive: Kill
///如果线程存在,则关掉进程
if (m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
}
// create events
if (m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
else
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent != NULL)
ResetEvent(m_hWriteEvent);
else
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent != NULL)
ResetEvent(m_hShutdownEvent);
else
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];
/*
多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,
无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每
个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和
LeaveCriticalSection函数。
*/
// 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);///可以显示COM10以上端口//add by itas109 2014-01-09
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
// get a handle to the port
/*
通信程序在CreateFile处指定串口设备及相关的操作属性,再返回一个句柄,
该句柄将被用于后续的通信操作,并贯穿整个通信过程串口打开后,其属性
被设置为默认值,根据具体需要,通过调用GetCommState(hComm,&&dcb)读取
当前串口设备控制块DCB设置,修改后通过SetCommState(hComm,&&dcb)将其写
入。运用ReadFile()与WriteFile()这两个API函数实现串口读写操作,若为异
步通信方式,两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读
写函数返回值为FALSE的情况下,调用GetLastError()函数,返回值为ERROR_IO_PENDING,
表明I/O操作悬挂,即操作转入后台继续执行。此时,可以用WaitForSingleObject()
来等待结束信号并设置最长等待时间
*/
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
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
///配置
///分别调用Windows API设置串口参数
if (SetCommTimeouts(m_hComm, &m_CommTimeouts))///设置超时
{
/*
若对端口数据的响应时间要求较严格,可采用事件驱动方式。
事件驱动方式通过设置事件通知,当所希望的事件发生时,Windows
发出该事件已发生的通知,这与DOS环境下的中断方式很相似。Windows
定义了9种串口通信事件,较常用的有以下三种:
EV_RXCHAR:接收到一个字节,并放入输入缓冲区;
EV_TXEMPTY:输出缓冲区中的最后一个字符,发送出去;
EV_RXFLAG:接收到事件字符(DCB结构中EvtChar成员),放入输入缓冲区
在用SetCommMask()指定了有用的事件后,应用程序可调用WaitCommEvent()来等待事
件的发生。SetCommMask(hComm,0)可使WaitCommEvent()中止
*/
if (SetCommMask(m_hComm, dwCommEvents))///设置通信事件
{
if (GetCommState(m_hComm, &m_dcb))///获取当前DCB参数
{
m_dcb.EvtChar = 'q';///设置字件字符
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
if (BuildCommDCB(szBaud, &m_dcb))///填写DCB结构
{
if (SetCommState(m_hComm, &m_dcb))///配置DCB
; // normal operation... continue
else
ProcessErrorMessage("SetCommState()");
}
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 | PURGE_TXABORT);
// release critical section
///释放临界资源
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);
return TRUE;
}
//
// The CommThread Function.
///线程函数
///监视线程的大致流程:
///检查串口-->进入循环{WaitCommEvent(不阻塞询问)询问事件-->如果有事件来到-->到相应处理(关闭\读\写)}
//
UINT CSerialPort::CommThread(LPVOID pParam)
{
// Cast the void pointer passed to the thread back to
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
最新serialport类.rar (4个子文件)
最新serialport类
CSerialPort.cpp 30KB
旧版
SerialPort.cpp 18KB
SerialPort.h 3KB
CSerialPort.h 5KB
共 4 条
- 1
资源评论
落木青云
- 粉丝: 45
- 资源: 7
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功