【问题标题】:How to set DTR/RTS state that will be used when CreateFile() opens COM port如何设置 CreateFile() 打开 COM 端口时将使用的 DTR/RTS 状态
【发布时间】:2009-06-04 14:39:53
【问题描述】:

我编写/支持了一个名为 uCon (http://www.umonfw.com/ucon) 的终端仿真器。它全部基于“good-ole”Win32,并且完全在'C'中。我最近被要求支持将 uCon 连接到 COM 端口并设置 DTR/RTS 以用于 RS232 流控制之外的目的。我知道我可以在使用 EscapeCommFunction() 和/或 SetCommState() 调用 CreateFile() 之后执行此操作;但是,这些函数只能在 CreateFile() 返回打开端口的句柄之后调用。不幸的是,当 CreateFile() 打开端口时,它会将 DTR/RTS 设置为其默认状态,这可能(也可能不会)与我希望保留 DTR 的状态不同。

例如,假设用户有一块板子连接到 PC 的串口,并且 DTR 线用于将板子置于一些非标准状态。 DTR 不活动时,板子运行“正常”,但偶尔 DTR 活动用于将硬件转换到其他状态。

在我见过的大多数情况下,CreateFile() 使 DTR 处于活动状态,然后我调用 clear DTR 使其恢复为非活动状态;但是,这是我需要避免的故障。我找到了一个名为 GetDefaultCommConfig() 和 SetDefaultCommConfig() 的函数集,但无法让它们成功工作。所以,我的问题是……

有没有办法预先定义调用 CreateFile() 时将在 RS232 控制线上建立的默认状态?有没有人成功使用过GetDefaultCommConfig()/SetDefaultCommConfig()?

在我看来,这应该允许我预先确定 DTR 的值是 调用 CreateFile() 时使用...

整数 建立DefaultDTR(char *comPortName, int dtr) { 通讯配置 cc; DWORD bsize = sizeof(COMMCONFIG); if (GetDefaultCommConfig(comPortName,&cc,&bsize) == 0) { ShowLastError("GetDefaultCommConfig()"); 返回(-1); } 如果 (dtr) cc.dcb.fDtrControl = DTR_CONTROL_ENABLE ; 别的 cc.dcb.fDtrControl = DTR_CONTROL_DISABLE ; if (SetDefaultCommConfig(comPortName,&cc,bsize) == 0) { ShowLastError("SetDefaultCommConfig()"); 返回(-1); } }

但是,您可能已经猜到了,事实并非如此。 有什么想法吗?

【问题讨论】:

  • 你看过这里吗:msdn.microsoft.com/en-us/library/ms810467.aspx 这篇文章提供了 BuildCommDCB() 作为替代方案......也许这对你有用?
  • @Ed:我遇到了完全相同的问题。你能解决吗?我提供赏金。
  • 你看过这里吗:codeguru.com/forum/showthread.php?t=291244 手头有同样的问题。然而,TDM 声称在打开端口后将 DTR 设置为其状态是唯一定义的方法。如果 100 毫秒的开关延迟导致硬件失效,那么从一开始就存在设计缺陷。
  • @Bort:在我的情况下,它不会杀死它,它只会让 X 射线管无用地旋转,应该避免但不是致命的。我同意你的观点,但无论如何,MODE 解决方案非常有效。

标签: c++ c windows serial-port


【解决方案1】:

可能不是最快的方法,但这是可行的:

#include <stdlib.h>
#include <stdio.h>

int
EstablishDefaultDTR(char *comPortName, int dtr){
    char commandString[256];
    if ( !system(NULL) ){
        ShowLastError("system()");
        return(-1);
    }        
    sprintf( commandString, "MODE %s dtr=%s%", comPortName, dtr? "on":"off"  );
    return system( commandString );
}

【讨论】:

  • 不就是打开端口,设置DTR状态吗?如果您已经打开了端口,那么MODE 命令将失败。下次打开端口时,它会保持以前的状态。您可以通过打开端口、设置 DTR、关闭端口然后在代码中再次打开它来获得相同的行为。
  • 我在打开它之前这样做,它可以工作。我没有检查对 CreateFile 的调用是否成功,但端口以正确的 DTR 状态打开(之前,它总是以 DTR 设置开始),并且通信按预期工作。
  • 即使我打开端口、清除 DTR、关闭它并稍后再次打开它,我也可以看到硬件在设置 DTR 的一小段时间内做出反应(一个 LED 点亮并且一个 X 射线管旋转半秒)。有了这个解决方案,这根本不会发生。
【解决方案2】:

您没有初始化 COMMCONFIG 结构。这很可能是问题所在,因为文档明确表示您必须至少设置 dwSize

cc.dwSize = sizeof(COMMCONFIG);

【讨论】:

  • 在第一次通话之前这样做是行不通的。两个调用都返回非零,因此,显然,它们成功了。在调用GetDefaultCommConfig 之后,我检查了cc 的内容,我看到的唯一奇怪的事情是cc.dcb.DCBLength 等于3435973836。我会在第一次通话之前尝试使用BuildCommDCB。欢迎任何其他建议。
  • 我找到了一种解决方法并将其发布为答案。我会等到赏金到期,看看是否有人提出了更好的解决方案。
  • @Danra:不。我试图将我的代码添加到问题中,但我的编辑被拒绝了。基本上,在声明COMMCONFIG 并设置它的大小之后,我使用BuildCommDCB 来设置它的DCB。我在GetDefaultCommConfig 之前尝试过这样做。在那次调用之后,我在调用SetDefaultCommConfig 之前更改了结构内容以禁用 DTR。我检查了调试器,所有结构内容一直都是有意义的,但端口仍然总是在设置 DTR 的情况下打开。我还在某处读到这种方式不适用于某些设备,所以我放弃并采用了我的答案中的解决方案,
  • 我的“设备”是别人制作的微控制器,作为 X 射线发生器的接口。我对电子部分知之甚少,我只是被告知如果我设置或清除 DTR 和 RTS 会发生什么,并且我通过 Tx 接收一些数据以通知某些事件。
  • @Danra: 这是我用BuildCommDCB 试过的code,也许你注意到了一些错误(除了明显的;它在我的测试之外无法编译,我只是把它放在那里分享它)
猜你喜欢
  • 2019-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
相关资源
最近更新 更多