简体   繁体   English

在Windows中将位写入COM端口-等效于INPORTB函数

[英]Writing bits to COM port in Windows - equivalent to INPORTB function

I am writing a program to control a relay switch connected thru the serial (RS-232) COM1 port. 我正在编写程序来控制通过串行(RS-232)COM1端口连接的继电器开关。 The device I am using has contains two relay switches. 我正在使用的设备包含两个继电器开关。 These are either 'open' or 'closed'. 这些是“打开”或“关闭”的。

By default, both relays are open. 默认情况下,两个继电器都是打开的。 The number 1 relay is closed by setting bit 1 in the modem control register. 通过设置调制解调器控制寄存器中的位1,可以关闭1号继电器。 Number 2 relay is closed by setting bit 0 in the modem control register. 通过将调制解调器控制寄存器中的位0设置,可以关闭2号继电器。

In C, this can be achieved as follows: 在C语言中,可以通过以下方式实现:

x = inportb(0x3FC);
x=x & ~2; //Set bit 1 to zero
x=x | 2;        //Set bit 1 to one
x=x & ~1; //Set bit 0 to zero
x=x | 1;        //Set bit 0 to one

C++ however, does not make COM port access so easy (or so I am led to believe). 但是,C ++并没有使COM端口访问变得如此容易(或者使我相信)。 I currently have the following code, which successfully opens and closes the COM port so that it can be communicated with in C++ and Windows: 我目前有以下代码,可以成功打开和关闭COM端口,以便可以在C ++和Windows中进行通信:

#include <windows.h>

//Initialise Windows module
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance,
LPSTR lpszArgument, int nFunsterStil)

{
 //Define the serial port precedure
 HANDLE hSerial;

 //Initialise relay
 hSerial = CreateFile("COM1",GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

 //SOME CODE MUST GO HERE

 //Deactivate relay
 CloseHandle(hSerial);

 return 0;
}

However, I am at a loss as to how to 'set bits'. 但是,我对如何“设置位”不知所措。 I'm still very new to C++. 我对C ++还是很陌生。 Any help would be gratefully appreciated. 任何帮助将不胜感激。

You need to understand how your device works. 您需要了解设备的工作方式。 You cannot "set bits" directly in hSerial. 您不能直接在hSerial中“设置位”。 Having COM port opened, you can send/receive bytes. 打开COM端口后,您可以发送/接收字节。 Possibly you need to send something to device using WriteFile (hSerial, ...). 可能您需要使用WriteFile (hSerial,...)将某些内容发送到设备。 Maybe you need to read information from device using ReadFile (hSerial, ...). 也许您需要使用ReadFile (hSerial,...)从设备读取信息。 COM port is not port as it was called in DOS, this is not address or register. COM端口不是在DOS中调用的端口,它不是地址或寄存器。 This is input/output stream. 这是输入/输出流。 You work with COM port like C program works with STDIN and STDOUT - read and wrire information from/to port. 您可以使用COM端口,就像C程序可以使用STDIN和STDOUT一样-从端口读取和写入信息。

Once you understand what your device needs (this means, define communication protocol ), implement it in the program. 一旦了解了设备的需求(这意味着定义通信协议 ),就可以在程序中实现它。 Read this article: Serial Communications http://msdn.microsoft.com/en-us/library/ff802693.aspx - everything Win32 programmer needs to know about serial communications. 阅读本文:串行通信http://msdn.microsoft.com/zh-cn/library/ff802693.aspx-Win32程序员需要了解有关串行通信的所有信息。

I am presuming that C example you give is not actually on a Windows box and is from some embedded platform is that correct? 我假设您提供的C示例实际上不在Windows机器上,并且是从某些嵌入式平台上编写的,对吗? As it looks like you have direct access to the COM port hardware. 看起来您可以直接访问COM端口硬件。

It is not as such C++ that makes this more challenging it is that Windows will not give you direct access to the hardware as you have on your embedded system. 并非如此的C ++带来了更大的挑战,而是Windows无法像您在嵌入式系统上那样直接访问硬件。 It is in fact not possible to set the level of specific pins on the COM port through the standard Windows API, you would need to write a driver that runs with increased privileges to achieve that. 实际上,不可能通过标准Windows API设置COM端口上特定引脚的级别,您需要编写一个具有增加的特权运行的驱动程序才能实现。 It might be impossible to do what you are trying to without writing a driver, something I wouldn't recommend. 如果不编写驱动程序,可能无法做您想做的事情,我不建议这样做。

The best solution would be to write the embedded end to accept commands as data sent over the RS-232 rather than look for levels on specific pins. 最好的解决方案是编写嵌入式端,以接受命令作为通过RS-232发送的数据,而不是在特定引脚上查找电平。 The answer from Alex Farber provides a good link to get you started with serial comms in windows. Alex Farber的答案提供了一个很好的链接,可让您开始使用Windows中的串行通信。

Not 100% sure what you are doing here, or what you want. 无法100%确定您在这里做什么或想要什么。 The data on the serial port is, well, serial and you cannot drive relays directly by sending data to the UART tx buffer on 0x3FC. 串行端口上的数据是串行的,您不能通过将数据发送到0x3FC上的UART tx缓冲区直接驱动继电器。 That and, as pointed out by other posters, access to the IO map is privileged since W95/98/ME/otherWintendo. 自从W95 / 98 / ME / otherWintendo以来,这种特权(正如其他发布者所指出的那样)具有访问IO映射的特权。

There may be good news - if you only need to drive two, (high sensitivity/low current), relays, you can do it by utilising the RTS and DTR control lines. 可能有个好消息-如果您只需要驱动两个(高灵敏度/低电流)继电器,则可以利用RTS和DTR控制线来实现。 The current available from these pins is enough to drive a 12V coil via. 这些引脚提供的电流足以驱动12V线圈通孔。 a diode, (line shifts from +12 to -12 so you need the diode on an ordinary non-polarised relay plus, if the relay does not already contain one, another diode to clamp any back EMFs during switching). 一个二极管(线路从+12转换为-12,因此您需要在普通的非极化继电器上加上一个二极管,如果继电器中还没有二极管,则需要另一个二极管来钳位开关过程中的任何反电动势)。

RTS/DTR can be driven from the serial APIs without any special privilege. 可以从串行API驱动RTS / DTR,而无需任何特殊特权。

I am doing this now to simulate a flow sensor switch when testing an embedded controller. 我现在正在执行此操作,以在测试嵌入式控制器时模拟流量传感器开关。

Note that the relays cannot be toggled at any great rate - the IO is very slow. 请注意,不能以任何较大的速率切换继电器-IO非常慢。 I can get about 15Hz on a good day. 我可以在美好的一天得到15Hz左右的声音。 4*4GHz cores, 12GB of RAM and my PC can only toggle 1 bit at 15Hz! 4 * 4GHz内核,12GB RAM和我的PC只能以15Hz的频率切换1位!

Rgds, Martin 马丁·罗格斯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM