请教有关串口编程方面的知识点1。creatafile() 创建文件句柄 2。writefile() 发送数据(命令)3。readfile() 读取数据 4。closehandle() 关闭句柄请问:请站长,斑主,高手解释上面的各个函数的具体做了什么事情。他的参数的具体含义是什么??
最好能结合操作系统和串口硬件结构讲讲这几个函数怎么联系在一起工作的谢谢!
最好能结合操作系统和串口硬件结构讲讲这几个函数怎么联系在一起工作的谢谢!
解决方案 »
- X264 码率控制不了啊
- 100分寻求帮助,关于ISAPI的问题
- LNK1181错误,是找不到这个lib,可是我用浏览器,在C:\Program Files\Microsoft Visual Studio\VC98\Lib
- 请教一个ESC/POS命令控制票据打印机的问题
- 单文档的标题 -“无标题”,是怎么产生的
- 点击按钮弹出对话框,如何当我鼠标点击别的地方时,自动隐藏;就像系统声音图标一样?
- 请问comer教授所著网际互连三卷本的第二卷源代码用什么工具打开?
- 生成文件的疑问
- 着急的问题:char与TCHAR..
- 关于串口与jpeg的问题,新人求助!!!求各位大神帮忙!!!
- 文件映射MapViewOfFile()使用问题
- 请教高手!关于List Control显示数据的问题
要不你也可以用MSComm控件
给你个网站自己去看看吧
http://www.gjwtech.com/
里面对串口编程讲的比较全面
WriteFile 发送
ReadFile 读取
CloseFile 关闭串口
因为COM1、COM2、...是特殊的文件名
我可以贴一点点代码过来,不是很完全的
CLSSerialPort::CLSSerialPort()
{
m_hComm = NULL;
m_hMsgWnd = NULL;
// 初始化 OVERLAPPED 结构
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
// 事件句柄
m_ov.hEvent = NULL;
m_hWriteEvent = NULL;
m_hShutdownEvent = NULL;
m_bThreadAlive = FALSE;
m_dwCommEvents = EV_RXCHAR | EV_CTS;
m_dwTimeOut = 0;
m_pSpecBuf = NULL;
}CLSSerialPort::~CLSSerialPort()
{
ClosePort(); if (m_ov.hEvent != NULL) // 读事件
ResetEvent(m_ov.hEvent);
if (m_hWriteEvent != NULL) // 写事件
ResetEvent(m_hWriteEvent);
if (m_hShutdownEvent != NULL) // 关闭事件
ResetEvent(m_hShutdownEvent);
m_hEventArray[0] = NULL; // 高优先级
m_hEventArray[1] = NULL;
m_hEventArray[2] = NULL;
}#define LeaveCriticalSectionAndReturnFalse \
{ \
LeaveCriticalSection(&m_csCommunicationSync); \
return FALSE; \
}
BOOL CLSSerialPort::InitPort(UINT uPort, UINT uBaudRate, char chParity, UINT uDataBits, UINT uStopBits)
{
BOOL bResult = FALSE;
char szPort[50];
char szBaud[50];
m_pSpecBuf = NULL;
m_uPort = uPort; ClosePort();
InitializeCriticalSection(&m_csCommunicationSync); // 初始化临界区
EnterCriticalSection(&m_csCommunicationSync); // 进入临界区
// 如果串口已经打开则关闭
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
sprintf(szPort, "COM%d", uPort); // 准备口串口字符串
sprintf(szBaud, "Baud=%d Parity=%c Data=%d Stop=%d", uBaudRate, chParity, uDataBits, uStopBits);
m_hComm = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
return FALSE;
// 设置超时
m_CommTimeouts.ReadIntervalTimeout = 1000;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
// 配置串口
if(!SetCommTimeouts(m_hComm, &m_CommTimeouts))
LeaveCriticalSectionAndReturnFalse;
if(!SetCommMask(m_hComm, m_dwCommEvents))
LeaveCriticalSectionAndReturnFalse;
if(!GetCommState(m_hComm, &m_dcb))
LeaveCriticalSectionAndReturnFalse;
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // 设置 RTS 位高
if(!BuildCommDCB(szBaud, &m_dcb))
LeaveCriticalSectionAndReturnFalse;
if (!SetCommState(m_hComm, &m_dcb)) //异常操作
LeaveCriticalSectionAndReturnFalse;
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //刷新端口
LeaveCriticalSection(&m_csCommunicationSync); //离开临界区
return StartSerialPortThread();
}DWORD __stdcall CLSSerialPort::_SerialPortThread(LPVOID pParam)
{
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comStat;
CLSSerialPort *port = (CLSSerialPort*)pParam;
port->m_bThreadAlive = TRUE; // 设置线程运行标志
if(port->m_hComm) // 判断端口是否已经打开
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //清除串口缓冲区
while(1)
{
if (!WaitCommEvent(port->m_hComm, &Event, &port->m_ov)) // 如果 WaitCommEvent() 返回 FALSE,处理错误
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING: // 端口上没有数据可读取,这是一个常见的返回值。
break;
case 87: // Windows NT下,某些情况下可能返回这个值,我没有研究过是为什么,这里没有做任何处理
break;
default: // 其它错误代码表明出现严重错误,应该处理该错误
break;
}
}
else // 缓冲区中有数据
{
ClearCommError(port->m_hComm, &dwError, &comStat);
if (comStat.cbInQue == 0)
continue;
}
Event = WaitForMultipleObjects(3, port->m_hEventArray, false, INFINITE); // 阻塞线程,等待事件发生
switch (Event)
{
case 0: // 关闭事件,这个事件应该有最高优先级
port->m_bThreadAlive = FALSE;
ExitThread(100); //退出线程,break实际上是不需要的,只是为了使结构更清析
break;
case 1: // 读事件
GetCommMask(port->m_hComm, &CommEvent);
if(port->m_hMsgWnd)
{
if (CommEvent & EV_CTS)
::SendMessage(port->m_hMsgWnd, WM_COMM_CTS_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_RXFLAG)
::SendMessage(port->m_hMsgWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_BREAK)
::SendMessage(port->m_hMsgWnd, WM_COMM_BREAK_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_ERR)
::SendMessage(port->m_hMsgWnd, WM_COMM_ERR_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_RING)
::SendMessage(port->m_hMsgWnd, WM_COMM_RING_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_DSR)
::SendMessage(port->m_hMsgWnd, WM_COMM_DSR_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_RLSD)
::SendMessage(port->m_hMsgWnd, WM_COMM_RLSD_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
if (CommEvent & EV_TXEMPTY)
::SendMessage(port->m_hMsgWnd, WM_COMM_TXEMPTY_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
}
if (CommEvent & EV_RXCHAR)
ReceiveIn(port, comStat); //从端口接收字符事件
break;
case 2: // 写事件
SendOut(port); //向端口写字符事件
break;
}
}
return 0;
}
{
DWORD lpThreadId; if(m_bThreadAlive)
return TRUE; // 创建事件
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);
// 初始化事件对象
m_hEventArray[0] = m_hShutdownEvent; // 高优先级
m_hEventArray[1] = m_ov.hEvent;
m_hEventArray[2] = m_hWriteEvent;
m_hThread = CreateThread(NULL, 0, _SerialPortThread, this, 0, &lpThreadId); if(m_hThread==NULL)
return FALSE; return TRUE;
}void CLSSerialPort::StopSerialPortThread()
{
while(m_bThreadAlive)
SetEvent(m_hShutdownEvent); // 通过设置终止事件来结束线程
m_bThreadAlive = FALSE;
}void CLSSerialPort::ReceiveIn(CLSSerialPort *port, COMSTAT comstat)
{
BOOL bRead = true;
BOOL bResult = true;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff;
ResetEvent(port->m_ov.hEvent);
for (;;)
{
EnterCriticalSection(&port->m_csCommunicationSync);
bResult = ClearCommError(port->m_hComm, &dwError, &comstat); // 更新 COMSTAT 结构体并清除所有其它错误
LeaveCriticalSection(&port->m_csCommunicationSync);
if (comstat.cbInQue == 0) //读取完所有字节后跳出循环
break;
EnterCriticalSection(&port->m_csCommunicationSync); //进入临界区
if (bRead)
{
bResult = ReadFile(port->m_hComm, &RXBuff, 1, &BytesRead, &port->m_ov);
// 处理错误代码
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
// 异步I/O仍在处理,继续执行 GetOverlappedResults();
bRead = false;
break;
}
}
else
bRead = true; // ReadFile成功,没有必要调用 GetOverlappedResults()
}
if (!bRead)
{
bRead = true;
bResult = GetOverlappedResult(port->m_hComm, &port->m_ov, &BytesRead, true);
}
LeaveCriticalSection(&port->m_csCommunicationSync); if(port->m_hMsgWnd)
::SendMessage(port->m_hMsgWnd, WM_COMM_RXCHAR, (WPARAM)RXBuff, (LPARAM) port->m_uPort);
if(port->m_pSpecBuf)
{
port->m_uExactSize++;
*(port->m_pSpecBuf) = (unsigned char)RXBuff;
port->m_pSpecBuf++;
}
}
}void CLSSerialPort::SendOut(CLSSerialPort *port)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
ResetEvent(port->m_hWriteEvent);
EnterCriticalSection(&port->m_csCommunicationSync); //进入临界区
if (bWrite)
{
// 初始化变量
port->m_ov.Offset = 0;
port->m_ov.OffsetHigh = 0;
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //清除缓冲区
if (!WriteFile(port->m_hComm, port->m_pSpecBuf, port->m_uBufSize, &BytesSent, &port->m_ov))
{
DWORD dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING: // 继续调用 GetOverlappedResults()
BytesSent = 0;
bWrite = false;
break;
default:
break; // 这里应处理其它错误
}
}
else
LeaveCriticalSection(&port->m_csCommunicationSync);
}
if (!bWrite)
{
bWrite = TRUE;
GetOverlappedResult(port->m_hComm, &port->m_ov, &BytesSent, TRUE);
LeaveCriticalSection(&port->m_csCommunicationSync);
}
port->m_uExactSize = BytesSent;
port->m_pSpecBuf = NULL;
}void CLSSerialPort::SetMessageTargetWindow(HWND hMsgWnd)
{
m_hMsgWnd = hMsgWnd;
}DCB CLSSerialPort::GetDCB()
{
return m_dcb;
}DWORD CLSSerialPort::GetCommEvents()
{
return m_dwCommEvents;
}UINT CLSSerialPort::Receive(unsigned char *pBuf, UINT uBufSize)
{
DWORD dwTicks;
ASSERT(m_hComm != NULL); m_pSpecBuf = pBuf;
m_uExactSize = 0;
SetEvent(m_ov.hEvent);
dwTicks = GetTickCount();
while((m_dwTimeOut == 0) || ((GetTickCount()-dwTicks)<m_dwTimeOut))
{
if(m_uExactSize>=uBufSize)
break;
}
ResetEvent(m_ov.hEvent);
m_pSpecBuf = NULL; return m_uExactSize;
}UINT CLSSerialPort::Send(unsigned char *pBuf, UINT uSize)
{
DWORD dwTicks;
ASSERT(m_hComm != NULL); m_uExactSize = 0;
m_pSpecBuf = pBuf;
m_uBufSize = uSize; SetEvent(m_hWriteEvent); //设置写事件
dwTicks = GetTickCount();
while((m_dwTimeOut == 0) || ((GetTickCount()-dwTicks)<m_dwTimeOut))
{
if(m_uExactSize>=uSize)
break;
}
m_uBufSize = 0;
m_pSpecBuf = NULL; return m_uExactSize;
}void CLSSerialPort::SetTimeOut(DWORD dwMilliSec)
{
m_dwTimeOut = dwMilliSec;
}void CLSSerialPort::ClosePort()
{
StopSerialPortThread();
CloseHandle(m_hComm);
m_hComm = NULL;
}UINT CLSSerialPort::Receive(UINT *puVal)
{
return Receive((unsigned char*)puVal, sizeof(UINT));
}UINT CLSSerialPort::Send(char *pString)
{
return Send((unsigned char*)pString, strlen(pString));
}
if (是) then
高手!!!!
向你学习
else
谢谢!
但仍给你一定的分
end if 你的给的代码和我买的一本书上的差不多。
我感觉C++ MFC 很复杂,很深的东西。得有一定的基础才行的我现在比较熟悉用PowerBuilder写的代码
关于com 口的pb 例子 我看了不是很理解
writefile() 中的数据写到缓冲区里去了。但是,具体到硬件上在什么地方?
然后,readfile()又是怎么把缓冲区的数据读出的?读出后,数据防在什么地方?