有人用过CSerialPort这个串口类吗?帮帮忙呀!

wangdong_monkey 2005-01-15 10:47:12
我看了http://www.gjwtech.com/scomm/sc2serialportclass.htm
里面的讲解!不过还是有很多不明白!那位老兄帮帮忙呀!
...全文
312 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
chuanke 2005-01-28
  • 打赏
  • 举报
回复
up
auly403 2005-01-28
  • 打赏
  • 举报
回复
建设你用过另外串口类吧.
要不你得更改类的封装.?


qrlvls 2005-01-26
  • 打赏
  • 举报
回复
//-----------------------------------------------------------------------------
// 描 述: 从串口发送指定长度的数据 (通知通讯线程发送)
// 参 数:
// pBuffer 需要发送的数据缓冲区指针
// uLength 需要发送的数据长度
// 返回值:
// 返回实际发出的数据长度
//-----------------------------------------------------------------------------
UINT CLSComm::SendBuffer(BYTE *pBuffer, UINT uLength)
{
if (!m_bThreadAlive)
return 0;

m_uTXCount = uLength>TX_BUFFER_LENGTH ? TX_BUFFER_LENGTH : uLength;
memcpy(m_byTXBuffer, pBuffer, uLength);
SetEvent(m_hWriteEvent);

return m_uTXCount;
}



//-----------------------------------------------------------------------------
// 描 述: 串口设备通讯控制线程
// 参 数:
// pParameter 传递给线程的参数(此处为CLSComm类的this指针)
//-----------------------------------------------------------------------------
DWORD WINAPI CLSComm::_CommThread(LPVOID pParameter)
{
CLSComm *pComm = (CLSComm*)pParameter;
DWORD BytesTransfered = 0;
DWORD dwEvent = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;

// 在线程起始时刻清除已经存在的缓冲区数据及异常状态
PurgeComm(pComm->m_hDevice, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

while (1)
{
// 在异步模式下,WaitCommEvent 并不会导致线程阻塞,在没有串口事件发生时返回 FALSE
bResult = WaitCommEvent(pComm->m_hDevice, &dwEvent, &pComm->m_ovComm);
if (!bResult)
{
dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING: // 无可读取的数据
case 87: // 另一个 WinNT 环境下的正常返回值
break;
default:
break;
}
}
else
{
ClearCommError(pComm->m_hDevice, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;
}

dwEvent = WaitForMultipleObjects(3, pComm->m_hEventArray, FALSE, INFINITE);
switch (dwEvent)
{
case USER_EVENT_QUIT: // 退出线程
pComm->m_bThreadAlive = FALSE;
return 0;
case USER_EVENT_RECEIVE: // 接收数据
GetCommMask(pComm->m_hDevice, &CommEvent);
if (CommEvent & EV_CTS)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_CTSCHANGE, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_RXFLAG)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_BREAK)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_ERR)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_RING)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_DSR)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_DSR_DETECTED, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_RLSD)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_RLSD_DETECTED, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);
if (CommEvent & EV_TXEMPTY)
::SendMessage(pComm->m_hTargetWindow, UM_COMM_TXEMPTY, (WPARAM) 0, (LPARAM) pComm->m_uCommPort);

if (CommEvent & EV_RXCHAR)
_ReceiveChar(pComm, comstat);

break;
case USER_EVENT_SEND: // 发送数据
_SendChar(pComm);
break;
}
}

return 0;
}
qrlvls 2005-01-26
  • 打赏
  • 举报
回复
考虑通过长度来识别所需发送的数据
我用m_nLength的含义便是让你在线程中通过pComm->m_nLength来WriteFile以实现发送数据的目的
qrlvls 2005-01-26
  • 打赏
  • 举报
回复
在你的函数中多了一句
m_nLength = nLength;
我不知道有什么意义。
----------------------------------------------------
因为需要SetEvent,线程可以通过 pComm->m_nLength得知需要发送的字节数
wangdong_monkey 2005-01-26
  • 打赏
  • 举报
回复
楼上的两位!能不能让我看看具体的代码?谢啦!
中级伴读 2005-01-23
  • 打赏
  • 举报
回复
用safearray
auly403 2005-01-22
  • 打赏
  • 举报
回复
m_ComPort.WriteToPort((char*)ctrl);

从这里可知能必有一个结束符..习惯用0x00
delphihero 2005-01-22
  • 打赏
  • 举报
回复
可以设置DCB结构,允许发送 00
wangdong_monkey 2005-01-22
  • 打赏
  • 举报
回复
楼上的!这不是跟没说一样吗?就是因为要发三个字符,可是第二个是0x00,所以后面的就发不过去了!要怎么解决呀?
54783szg 2005-01-19
  • 打赏
  • 举报
回复
用别人的总有的地方不明白,既然是VC就自己拿API写就没这么多麻烦事了!
yeedward 2005-01-19
  • 打赏
  • 举报
回复
不能发送0x00
wangdong_monkey 2005-01-16
  • 打赏
  • 举报
回复
qrlvls(≌AIR⌒LIKE) (≤和空气一样帅≥√)!
谢谢你的回答!
我现在将函数按你的要求改为了下面的:

void CSerialPort::WriteToPort(char* string,int nLength)
{
assert(m_hComm != 0);

memcpy(m_szWriteBuffer,string,nLength);

// set event for write
SetEvent(m_hWriteEvent);
}
在你的函数中多了一句
m_nLength = nLength;
我不知道有什么意义。
不过我看了一下m_szWriteBuffer的定义,也是字符串型的指针,我觉得你后来说的有道理,第二个字符是0x00,即使现在考进了缓冲区m_szWriteBuffer,但是可能还是会只识别一个字符,而把0x00作为结束标志,看来还是要改底层的代码!不知道怎么改?你有什么意见?谢谢!
分我多给!不够再加!别人也有份!
qrlvls 2005-01-15
  • 打赏
  • 举报
回复
BYTE* ctrl=(BYTE*)new char[3];
*ctrl=0xEE;
*(ctrl+1)=0x00;
*(ctrl+2)=0x43;
m_ComPort.WriteToPort((char*)ctrl);

第二个字节为 0x00,使用 WriteToPort 可能只能发送 0xEE 出去
comefromxian 2005-01-15
  • 打赏
  • 举报
回复
我也有个问题请教:在用这个类同时控制多个串口(3个)时,如果多次同时开关这些串口,程序出现异常,我向龚老师发信请教了,他也没有好的办法,只能让串口一直打开不关闭它,哪位有更好的办法呢?
wangdong_monkey 2005-01-15
  • 打赏
  • 举报
回复
楼上的!说了这么多!你觉得问题到底在哪儿呀???
qrlvls 2005-01-15
  • 打赏
  • 举报
回复
void CSerialPort::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);
}
这个函数只能用于发送字符串,如果你需要发送的数据中包含字符串的结束符的话是不会成功的
你可以修改这个函数
void CSerialPort::WriteBuffer(char* pBuffer, int nLength)
{
assert(m_hComm != 0);

memcpy(m_szWriteBuffer, pBuffer, nLength);
m_nLength = nLength;

// set event for write
SetEvent(m_hWriteEvent);
}
在线程中WriteFile时写入的就是 m_szWriteBuffer, 长度为 pComm->m_nLength
m_nLength是新加入的成员变量
qrlvls 2005-01-15
  • 打赏
  • 举报
回复
CSerialPort的原理:
  使用异步操作,在打开的时候初始化DCB结构,也就是初始化波特率、数据位、奇偶校验、流量控制(需要自己修改代码)、停止位,然后使用CreateFile来打开串口设备。
  使用了重叠IO方式,使得线程在读取数据的时候不阻塞,但是一但接收到数据可以通过OVERLAPPED结构中的hEvent触发接收事件,线程中等待三个事件:接收到数据、有数据需要发送、退出线程。
  发送数据和退出线程都是直接SetEvent的,而接收到数据的事件是通过OVERLAPPED结构来实现的
wangdong_monkey 2005-01-15
  • 打赏
  • 举报
回复

BYTE* ctrl=(BYTE*)new char[3];
*ctrl=0xEE;
*(ctrl+1)=0x00;
*(ctrl+2)=0x43;
m_ComPort.WriteToPort((char*)ctrl);
Sleep(1000);
*(ctrl+2)=0x41;
m_ComPort.WriteToPort((char*)ctrl);

这是我写的云台控制程序!可是WriteToPort函数好像发不过去指令!
下面是CSerialPort类定义的发送数据函数!
void CSerialPort::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);
}
kchai1 2005-01-15
  • 打赏
  • 举报
回复
不明白的地方贴出来呀
加载更多回复(1)

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧