笔记本上没串口,利用虚拟串口软件VSPD和串口调试助手,目的是通过C++程序完成串口通信,但是只能实现Write操作,不能实现Read操作,附上源代码求大佬指点

坚持着的沉默者 2018-08-11 04:23:26
因为在串口通信方面是小白,所以在网上查看了很多相关的知识和代码,自己动手写了一下试试,但是一直未通过。以下是代码和调试过程的图片,求大佬指点,很急!!!!!!!!!!!!!!!!!!!
首先,打开串口并设置串口参数的函数和串口的关闭函数。



然后是串口通信的读写函数。



最后是主函数。

因为是读函数出现问题,所以在主函数中设置了一个死循环,然后利用串口调试工具重复发送数据,为的是查看串口输入缓冲区内是否含有数据,并且是否能够读取。

以下是虚拟串口,串口调试工具的操作截图以及程序的运行结果:



运行结果之所以是两种,是因为刚开始我没有利用串口调试助手让COM4向COM3发送数据,所以缓冲区内无数据,然后重复发送数据,结果是读取失败,返回的错误码998代表内存分配访问无效,然后从虚拟串口状态截图上可以发现,两个串口的参数不一致,但是如果不一致,COM3不可能像COM4发送数据,而且COM4向COM3发送数据之后,COM3的读取虽然失败,但是缓冲区内存在数据,所以我就很困惑,跪求大佬指点迷津,真的很急!!!!!!!!!!!!!!!!

最后附上利用调试工具同时打开两个串口进行通信的结果:

...全文
471 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 12 楼 zgl7903 的回复:
998 Invalid access to memory location. ERROR_NOACCESS
缓冲区有问题?


实在不好意思,我把上面那个char *read改为char read[1024] //需要分配缓冲区 给忽略掉了,现在我改完成功了。
非常感谢大佬的帮助,谢谢!谢谢!
  • 打赏
  • 举报
回复
引用 14 楼 xiaobai_8001 的回复:
主程序里char *read改成char read[1024] 试试

[quote=引用 8 楼 zgl7903 的回复:]
互传 就是你你上面说的操作

char read[1024] //char *read; 需要分配缓冲区


//返回读取的字节长度
DWORD ReadData(void *pBuffer, int iBuffLen)
{
DWORD dwReaded = 0;

DWORD dwCommErr = 0;
COMSTAT ComStat = {0};
ClearCommError(hComm, &dwCommErr, &ComStat);
if(ComStat.cbInQue > 0)
{
OVERLAPPED ovr = {0};
ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ReadFile(hComm, pBuffer, min((int)ComStat.cbInQue, iBuffLen), &dwReaded, &ovr))
{
//直接读取成功
}
else
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_IO_PENDING) //ERROR_IO_PENDING
{
if(!GetOverlappedResult(hComm, &ovr, &dwReaded, TRUE))
{
dwErr = GetLastError();
TRACE(_T("GetOverlappedResult failed %u"), dwErr);
}
}
else //failed
{
TRACE(_T("ReadFile failed %u\n"), dwErr);
}
}
}

return dwReaded;
}

[/quote]

啊!!!!谢谢谢谢!!上面那个大佬之前就告诉我这个了,我忽略了。。。谢谢提醒,现在可以了。非常感谢!
xiaobai_8001 2018-08-13
  • 打赏
  • 举报
回复
主程序里char *read改成char read[1024] 试试

引用 8 楼 zgl7903 的回复:
互传 就是你你上面说的操作

char read[1024] //char *read; 需要分配缓冲区


//返回读取的字节长度
DWORD ReadData(void *pBuffer, int iBuffLen)
{
DWORD dwReaded = 0;

DWORD dwCommErr = 0;
COMSTAT ComStat = {0};
ClearCommError(hComm, &dwCommErr, &ComStat);
if(ComStat.cbInQue > 0)
{
OVERLAPPED ovr = {0};
ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ReadFile(hComm, pBuffer, min((int)ComStat.cbInQue, iBuffLen), &dwReaded, &ovr))
{
//直接读取成功
}
else
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_IO_PENDING) //ERROR_IO_PENDING
{
if(!GetOverlappedResult(hComm, &ovr, &dwReaded, TRUE))
{
dwErr = GetLastError();
TRACE(_T("GetOverlappedResult failed %u"), dwErr);
}
}
else //failed
{
TRACE(_T("ReadFile failed %u\n"), dwErr);
}
}
}

return dwReaded;
}

zgl7903 2018-08-12
  • 打赏
  • 举报
回复
上面的那个忘了 CloseHandle, 有句柄泄漏

//返回读取的字节长度
DWORD ReadData(void *pBuffer, int iBuffLen)
{
DWORD dwReaded = 0;

DWORD dwCommErr = 0;
COMSTAT ComStat = {0};
ClearCommError(hComm, &dwCommErr, &ComStat);
if(ComStat.cbInQue > 0)
{
OVERLAPPED ovr = {0};
ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ReadFile(hComm, pBuffer, min((int)ComStat.cbInQue, iBuffLen), &dwReaded, &ovr))
{
//直接读取成功
}
else
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_IO_PENDING) //ERROR_IO_PENDING
{
if(!GetOverlappedResult(hComm, &ovr, &dwReaded, TRUE))
{
dwErr = GetLastError();
TRACE(_T("GetOverlappedResult failed %u"), dwErr);
}
}
else //failed
{
TRACE(_T("ReadFile failed %u\n"), dwErr);
}
}

CloseHandle(ovr.hEvent);
}

return dwReaded;
}
zgl7903 2018-08-12
  • 打赏
  • 举报
回复
zgl7903 2018-08-12
  • 打赏
  • 举报
回复
互传 就是你你上面说的操作

char read[1024] //char *read; 需要分配缓冲区


//返回读取的字节长度
DWORD ReadData(void *pBuffer, int iBuffLen)
{
DWORD dwReaded = 0;

DWORD dwCommErr = 0;
COMSTAT ComStat = {0};
ClearCommError(hComm, &dwCommErr, &ComStat);
if(ComStat.cbInQue > 0)
{
OVERLAPPED ovr = {0};
ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ReadFile(hComm, pBuffer, min((int)ComStat.cbInQue, iBuffLen), &dwReaded, &ovr))
{
//直接读取成功
}
else
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_IO_PENDING) //ERROR_IO_PENDING
{
if(!GetOverlappedResult(hComm, &ovr, &dwReaded, TRUE))
{
dwErr = GetLastError();
TRACE(_T("GetOverlappedResult failed %u"), dwErr);
}
}
else //failed
{
TRACE(_T("ReadFile failed %u\n"), dwErr);
}
}
}

return dwReaded;
}

  • 打赏
  • 举报
回复
引用 6 楼 zgl7903 的回复:
首先的确保串口上有数据进来
如果是物理串口,把COM3 的 RXD 和 TXD (如果是DB9头的话是Pin2 Pin3)短接起来, 自发自收

如果有两个物理串口, RXD TXD交叉连接 (+GND), 如果打开的是配对的虚拟串口, 可以串口助手打开一个,软件打开一个, 两个软件互传

两个都是虚拟串口,COM4是用串口助手打开的,COM3是希望用CPP文件中的程序打开,然后两者进行交互。CPP文件中有定义Read函数,然后在主函数中设立了死循环,希望通过串口助手向COM3发送数据,然后通过Read函数读取并输出。

串口上应该是有数据进去的,因为在死循环中,我有清空缓冲区的操作,每次循环都会执行,也就是每次发送之后,不论读取成功与否,都会清空缓冲区。在程序刚开始运行瞬间,我还没有通过串口助手发送数据,所以会显示串口内无数据的结果,然后我通过串口助手重复发送数据时,会显示读取失败,而读取失败的原因一直是内存分配访问无效,停止发送后,因为清空缓冲区的操作,会再次显示串口内无数据,证明串口内是有数据的,但是无法读取。

最后就是,您说的两个软件互传是什么意思。。。
zgl7903 2018-08-12
  • 打赏
  • 举报
回复
首先的确保串口上有数据进来
如果是物理串口,把COM3 的 RXD 和 TXD (如果是DB9头的话是Pin2 Pin3)短接起来, 自发自收

如果有两个物理串口, RXD TXD交叉连接 (+GND), 如果打开的是配对的虚拟串口, 可以串口助手打开一个,软件打开一个, 两个软件互传
  • 打赏
  • 举报
回复
引用 12 楼 zgl7903 的回复:
998 Invalid access to memory location. ERROR_NOACCESS
缓冲区有问题?


我也不知道,我不是很了解。但是程序返回的结果是这样的。
zgl7903 2018-08-12
  • 打赏
  • 举报
回复
998 Invalid access to memory location. ERROR_NOACCESS
缓冲区有问题?
  • 打赏
  • 举报
回复
引用 10 楼 zgl7903 的回复:
上面的那个忘了 CloseHandle, 有句柄泄漏

//返回读取的字节长度
DWORD ReadData(void *pBuffer, int iBuffLen)
{
DWORD dwReaded = 0;

DWORD dwCommErr = 0;
COMSTAT ComStat = {0};
ClearCommError(hComm, &dwCommErr, &ComStat);
if(ComStat.cbInQue > 0)
{
OVERLAPPED ovr = {0};
ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ReadFile(hComm, pBuffer, min((int)ComStat.cbInQue, iBuffLen), &dwReaded, &ovr))
{
//直接读取成功
}
else
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_IO_PENDING) //ERROR_IO_PENDING
{
if(!GetOverlappedResult(hComm, &ovr, &dwReaded, TRUE))
{
dwErr = GetLastError();
TRACE(_T("GetOverlappedResult failed %u"), dwErr);
}
}
else //failed
{
TRACE(_T("ReadFile failed %u\n"), dwErr);
}
}

CloseHandle(ovr.hEvent);
}

return dwReaded;
}


还是不行。。。我把您的Read函数替换成我程序里的,还是不行。。。错误码还是998。。。
  • 打赏
  • 举报
回复
引用 4 楼 zgl7903 的回复:
屏蔽 PurgeComm 那一行

结果一样,没有变化。。。。。
zgl7903 2018-08-11
  • 打赏
  • 举报
回复
屏蔽 PurgeComm 那一行
  • 打赏
  • 举报
回复
引用 1 楼 zzxiaoma 的回复:
变量的值1024改成1试试

结果一样,没有变化。
  • 打赏
  • 举报
回复
结果还是一样,没有改变。
zzxiaoma 2018-08-11
  • 打赏
  • 举报
回复
变量的值1024改成1试试
刚刚从visual basic 中杀回来,由于急切想试一下,上位机(微机)与下位机(单片机)相结合的无穷魅力,就急切的利用好心人的实例匆匆修改调试,终于建立了一座小桥,面貌和功能真是我都不忍心看。但网友比我还急切,我刚说出了想法,就相我要结果,干脆就把周日给消灭了。先拿出来共同欣赏一下,以证明这条路子是可以走的,在以后的过程中,将会有漂亮灵巧的例子和大家一起弄。 首先说明一下我的过程,另外介绍一下需要安装的软件和过程。 1。visual basic 6.0 他的版本可不旧,.net不和咱相关。软件很大,可以随便从网上找到下载安装。 2。vspd xp 5。也可以从网上下载,但为了方便,我就放一块了,可以直接安装设置。增加两个虚拟串口,就和虚拟光驱的道理是一样的。具体可以找一下资料,1,将串口选择处改为com3和com4,点击add pair就可以了。这样就与他暂时无关了,就相当于硬件pc 与 mcu 都将要连在一起了。 !!!!!!!!!注意!!!,vb的mscomm1控件设置为com3,而讲proteus 的compim设置为com4,就表示连在一起了,不能都为com3或com4!!!!!! 其他参数设置为(9600,n,8,1). 3.运行vb,运行proteus 4。看看很一般的效果,但意义还是有一点的。哈哈 !好了,过几天我再弄得漂亮一点点了。比如,让电脑界面上的设置的按钮把单片机玩弄起来,好吧。希望大家支持呀。 5感谢广大网友的例子,我在此基础上做了整合,不涉及侵犯其权利。共同进步。仅限于学习,不用于其他商业用途。

16,472

社区成员

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

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

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