VC中 使用 CSerialPort类,WM_COMM_RXFLAG_DETECTED 消息问题

cyberdavinci 2010-12-20 01:30:40


我在VC中,用CSerial Port 类,写一个串口通信小程序,想用WM_COMM_RXFLAG_DETECTED这个事件告知我一次接收信息完成。

我的主程序文件是:CVerDlg.cpp,在该文件中:

ON_MESSAGE(WM_COMM_RXFLAG_DETECTED, OnCommEnd)

LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)


在CVerDlg.h中:
afx_msg LONG OnCommEnd(WPARAM ch, LPARAM port);


现在,当接收到串口发送来的消息后,我可以进入
LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)

这个函数

但是,问题在于:
如果串口到来的消息只有一个字节,我每接收完这条消息后,进入LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)这个函数一次, 如果串口发送的消息大于一个字节(2~N)则每次接收完消息后,会进入这个函数两次,为啥会这样?还盼牛人指点!!!! 或者是,我对WM_COMM_RXFLAG_DETECTED这个事件的理解有问题??
...全文
487 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
laicai1989 2013-05-24
  • 打赏
  • 举报
回复
ls 问题解决了吗 求解。。
kavy00 2012-01-12
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 xianglitian 的回复:]

引用 6 楼 cyberdavinci 的回复:
引用 5 楼 grf9527 的回复:

你到底想说什么,进入几次不重要,重要的是你怎么处理接收的。如果是end了,你也得接收下一个啊,你的协议是什么,能贴点源码吗


我的协议是:没接收到一条信息,不验证信息的内容,立即回复一条信息(回复的信息是预先存储的,且每一条按次序均不相同)。在这种情况下,如果其实只收到一条信息,但却进入了两……
[/Quote]我用的是 Serialport这个多线程类来编的一个类似与串口调试助手程序,但有个那个在接收框中 如何实现自动换行啊 就是说没接收完一次数据 就会自动换行!!我用的是OnComm(WPARAM ch,LPARAM port)这个函数来接收数据的,这个函数是每当接收缓冲区有一个字符到来时 他就响应了 那我如何判断何时数据接收完了啊
向立天 2012-01-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cyberdavinci 的回复:]
引用 5 楼 grf9527 的回复:

你到底想说什么,进入几次不重要,重要的是你怎么处理接收的。如果是end了,你也得接收下一个啊,你的协议是什么,能贴点源码吗


我的协议是:没接收到一条信息,不验证信息的内容,立即回复一条信息(回复的信息是预先存储的,且每一条按次序均不相同)。在这种情况下,如果其实只收到一条信息,但却进入了两次LONG CVer1Dlg::OnCommEnd(W……
[/Quote]你这个机制是有问题的啊
下位和上位其实是不同步的
下位来了一个消息
但是上位可能不能一次读完
这个是正常的
你不做判断不合适吧
有什么特殊需求么?
kavy00 2012-01-12
  • 打赏
  • 举报
回复
你想实现那个自动应答的话 这样应该就可以了:比如规定一个数据的协议啊 发送的数据以#结尾啊 然后在接收的时候检测#即可啊
kavy00 2012-01-12
  • 打赏
  • 举报
回复
这个是因为 你使用的OnComm()这个函数 他响应的条件是:每当接收缓冲区有一个字符到来时 他就会触发这个OnComm()函数 所以当你发一个字节的时候就触发一次 多个字节的时候就是触发多次了!!已也可以Debug下 在OnComm()设置断点 发多字节 观察变量值就很明白了 !!
cyberdavinci 2010-12-21
  • 打赏
  • 举报
回复
把CSerialPort类的代码贴出来。。。 虽然貌似这个类在网上很多的样子。。
SerialPort.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-send) signal changed state.
#define WM_COMM_DSR_DETECTED WM_USER+3 // The DSR (data-set-ready) signal changed state.
#define WM_COMM_ERR_DETECTED WM_USER+4 // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
#define WM_COMM_RING_DETECTED WM_USER+5 // A ring indicator was detected.
#define WM_COMM_RLSD_DETECTED WM_USER+6 // The RLSD (receive-line-signal-detect) signal changed state.
#define WM_COMM_RXCHAR WM_USER+7 // A character was received and placed in the input buffer.
#define WM_COMM_RXFLAG_DETECTED WM_USER+8 // The event character was received and placed in the input buffer.
#define WM_COMM_TXEMPTY_DETECTED WM_USER+9 // The last character in the output buffer was sent.

class CSerialPort
{
public:
int m_nWriteSize;
void ClosePort();
// contruction and destruction
CSerialPort();
virtual ~CSerialPort();

// port initialisation
BOOL InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity = 'N', UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = 1024);
HANDLE m_hComm;

// start/stop comm watching
BOOL StartMonitoring();
BOOL RestartMonitoring();
BOOL StopMonitoring();

DWORD GetWriteBufferSize();
DWORD GetCommEvents();
DCB GetDCB();

void WriteToPort(char* string);
void WriteToPort(char* string,int n);
void WriteToPort(LPCTSTR string);
void WriteToPort(LPCTSTR string,int n);

protected:
// protected memberfunctions
void ProcessErrorMessage(char* ErrorText);
static UINT CommThread(LPVOID pParam);
static void ReceiveChar(CSerialPort* port, COMSTAT comstat);
static void WriteChar(CSerialPort* port);

// thread
CWinThread* m_Thread;

// synchronisation objects
CRITICAL_SECTION m_csCommunicationSync;
BOOL m_bThreadAlive;

// handles
HANDLE m_hWriteEvent;
HANDLE m_hShutdownEvent;

// Event array.
// One element is used for each event. There are two event handles for each port.
// A Write event and a receive character event which is located in the 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
CWnd* m_pOwner;

// misc
UINT m_nPortNr;
char* m_szWriteBuffer;
DWORD m_dwCommEvents;
DWORD m_nWriteBufferSize;
};

#endif __SERIALPORT_H__
cyberdavinci 2010-12-21
  • 打赏
  • 举报
回复
T_T
cyberdavinci 2010-12-20
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 grf9527 的回复:]

你到底想说什么,进入几次不重要,重要的是你怎么处理接收的。如果是end了,你也得接收下一个啊,你的协议是什么,能贴点源码吗
[/Quote]

我的协议是:没接收到一条信息,不验证信息的内容,立即回复一条信息(回复的信息是预先存储的,且每一条按次序均不相同)。在这种情况下,如果其实只收到一条信息,但却进入了两次LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)函数,这是,我的程序就会发出两条不同的应答信息,但事实上,这时候应该只发送一条应答信息,这就是现在的问题。。。

代码的话,其实就是我在1楼所贴的:
我的程序中使用了CSerialPort 类,我使用了该类中定义的WM_COMM_RXFLAG_DETECTED事件(Serial Port.h文件中)
#define WM_COMM_RXFLAG_DETECTED		WM_USER+8	// The event character was received and placed in the input buffer. 


而后,在我的主程序文件(CVer1Dlg.cpp)中,定义了LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)这个函数对该事件的响应
ON_MESSAGE(WM_COMM_RXFLAG_DETECTED, OnCommEnd)

LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)


当然,在CVer1Dlg.h中,也有声明
afx_msg LONG OnCommEnd(WPARAM ch, LPARAM port);


就是这样的了。。。

现在的情况是,接收到一次串口数据后,可以进入上述函数,如果接收的数据只有一个字节,则只进入上述函数一次;如果一次接收的数据超过一个字节,就会进入上述函数两次。。。。。 我想要的结果是,一次不管接收多少个字节,只进入这个函数一次。 这个,是不是也是WM_COMM_RXFLAG_DETECTED这个事件的本来意义?或者说,我对WM_COMM_RXFLAG_DETECTED这个事件的理解有问题?
grf9527 2010-12-20
  • 打赏
  • 举报
回复
你到底想说什么,进入几次不重要,重要的是你怎么处理接收的。如果是end了,你也得接收下一个啊,你的协议是什么,能贴点源码吗
cyberdavinci 2010-12-20
  • 打赏
  • 举报
回复
哪位大侠 帮帮忙啊。。
cyberdavinci 2010-12-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 varding 的回复:]

我以前用这个串口类读取大量的数据用的是在timer里定时读取(轮询)的方式,事件没试过,也许需要设置阈值什么的?

其实进入OnCommEnd多次也没关系的,你自己要把数据重新打包然后在接收端解包就可以了
[/Quote]
如果是单纯地接受数据的话,确实这样是没什么影响的。 但是,我现在要根据收到的数据自动应答,如果接收到一次,但是却两次进入LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)函数的话,我就自动应答两次,就悲剧了。。。
varding 2010-12-20
  • 打赏
  • 举报
回复
我以前用这个串口类读取大量的数据用的是在timer里定时读取(轮询)的方式,事件没试过,也许需要设置阈值什么的?

其实进入OnCommEnd多次也没关系的,你自己要把数据重新打包然后在接收端解包就可以了
cyberdavinci 2010-12-20
  • 打赏
  • 举报
回复
求救啊!!!

那位大侠能指点下啊!!!
代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统,网络配置的管理机制与早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
代码转载自:https://pan.quark.cn/s/46fd08fb879c 网管教程 从入门到精通软件篇 ★一。★详尽的xp修复控制台指令及其应用!!! 放入xp(2000)的光盘,安装时选择R,执行修复! Windows XP(涵盖 Windows 2000)的控制台指令是在系统遭遇某些意外状况时的一种极具效用的诊断、检测以及恢复系统功能的工具。笔者确实一直期望能够将这方面的指令进行归纳,此次由老范辛苦整理了这份极具价值的秘籍。 Bootcfg bootcfg 命令用于启动配置与故障恢复(对大多数计算机而言,即 boot.ini 文件)。 带有特定参数的 bootcfg 命令仅在运用故障恢复控制台时方可使用。能够在命令行界面下运用带有不同参数的 bootcfg 命令。 用法: bootcfg /default 设定默认引导选项。 bootcfg /add 向引导清单增添 Windows 安装。 bootcfg /rebuild 重复整个 Windows 安装流程并让用户选择需添加的项目。 注意:运用 bootcfg /rebuild 之前,应先借助 bootcfg /copy 命令备份 boot.ini 文件。 bootcfg /scan 探查用于 Windows 安装的全部磁盘并展示结果。 注意:这些结果被静态存储,并用于当前会话。若在当前会话期间磁盘配置发生变动,为获取更新的探查结果,必须先重启计算机,然后再次探查磁盘。 bootcfg /list 列示引导清单已有的项目。 bootcfg /disableredirect 在启动引导程序禁用重定向。 bootcfg /redirect [ PortBaudRrate] |[ useBio...

16,550

社区成员

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

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

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