串行设备使用 C 忽略 EscapeCommFunction [英] serial device ignores EscapeCommFunction with C

查看:78
本文介绍了串行设备使用 C 忽略 EscapeCommFunction的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在(最终)从 MSDOS 迁移到 Windows XP,以便通过串行端口控制仪表.我的旧 C DOS 代码运行良好.

I am migrating (finally) from MSDOS to Windows XP for controlling a meter via the serial port. My old C DOS code works fine.

我想做如下:

  • 仪表持续读取读数每隔几秒,但不发送任何信息,直到它被要求电脑
  • 当计算机准备好接收时来自仪表的信息,它要求它.它不接受其他信息.

我的问题是,读数刚刚进入计算机,因为它们是由仪表生成的.

My problem is that the readings are just coming into the computer as they are generated by the meter.

我已经设置了 DCB serail params 如下,打算使用 RTS 和 DTR 控制通信:

I have set the DCB serail params as follows, intending to control communication using RTS and DTR:

dcbSerialParams.BaudRate=CBR_4800;
dcbSerialParams.ByteSize=7;
dcbSerialParams.StopBits=TWOSTOPBITS;
dcbSerialParams.Parity=EVENPARITY;
dcbSerialParams.fDtrControl=DTR_CONTROL_ENABLE;
dcbSerialParams.fRtsControl=RTS_CONTROL_ENABLE;

我在 DOS 下的旧代码是这样的:

My old code under DOS was like this:

 outportb(COM1+4,0x03);  /* start Minolta reading */   

 for(j=0;j<=10;j++) /*each reading consists of 11 ascii characters*/
  {
  while(!((inportb(COM1+5)) & 1)); /*wait until char received*/
  reading[j]=inportb(COM1);
  }
 sscanf ( &reading[4], "%f", &lum[k] );
 
 outportb(COM1+4,0x00);  /* stop Minolta reading */

在我看来这应该可行:

void serial_notready(void)
{
EscapeCommFunction(hSerial,CLRDTR);
EscapeCommFunction(hSerial,CLRRTS);
}

void serial_ready(void)
{
EscapeCommFunction(hSerial,SETDTR);
EscapeCommFunction(hSerial,SETRTS);
}

int serial_read(char reading[])
{
DWORD dwBytesRead = 0;
int nbytes=11;
ReadFile(hSerial, reading, nbytes, &dwBytesRead, NULL);
return(dwBytesRead);
}

serial_ready(void);
x = 0; while(x == 0){x=serial_read(reading);}
serial_notready(void);

然而,Minolta 不会等待从计算机接收 RTS.它只是继续并在每个可用时发送读数.同时,计算机不会拒绝任何不需要的阅读,而是接受.

HOWEVER, the Minolta does not wait to receive the RTS from the computer. It just goes ahead and sends readings as each becomes available. At the same time, the computer does not reject any unwanted reading, but accepts it.

我一直把头撞在墙上试图弄清楚这一点,尝试了各种排列都无济于事.非常感谢任何帮助!

I have been bashing my head against the wall trying to figure this out, trying all kinds of permutations to no avail. Any help greatly appreciated!

背后的故事是我在显示器上呈现给定的亮度(亮度),然后需要相应的亮度读数.这是针对一整套亮度完成的.

The underlying story is that I present a given luminance (brightness) on a display and then need the corresponding luminance reading. This is done for a whole set of luminances.

L   ---
U      ---
M         ---
     TIME

我提供了 lum1、lum2、lum3、lum4.... 如果测量值与显示不同步,那么我可能会得到一个假设的读数 3,它实际上是 lum2,或者某种平均值,因为读数越过了边界lum2 和 lum3 显示之间.而且,正如你所说,汉斯,读数总是落后于显示亮度.即使我总是系统地落后于它的一个读数也会很糟糕(我的情况更糟 - 它是读数和亮度之间的随机关系).

I present lum1, lum2, lum3, lum4,.... If the measurements are not synchronised to the display, then I may get a supposed reading3 that is actually lum2, or some sort of average because the reading crossed the border between the lum2 and lum3 displays. And, as you said, Hans,the readings will always lag behind the display luminances. Even if I were always systematically one reading behind it would be bad (my situation is worse-- it is a a random relation between the reading and the luminance).

所以 Windows 串行例程的行为对我来说是一场噩梦.再次感谢您的帮助!

So the behaviour of the windows serial routines is a nightmare for me. Thanks again for the help!

推荐答案

dcbSerialParams.fDtrControl=DTR_CONTROL_ENABLE; 
dcbSerialParams.fRtsControl=RTS_CONTROL_ENABLE;

您立即启用 DTR 和 RTS 信号.当您打开端口时,仪表将立即开始发送数据.该数据被缓冲在驱动程序的接收缓冲区中.您之前在 DOS 代码中没有缓冲区.这取决于您调用 serial_notready() 需要多长时间.如果这需要一秒钟左右,您将拥有一个非常满的缓冲区.是的,这使得仪表看起来只是在发送数据.而且您总是在阅读旧样本.

You enable the DTR and RTS signals right away. The meter will immediately start sending data when you open the port. That data gets buffered in the driver's receive buffer. You didn't have a buffer before in the DOS code. It depends how long it takes for you to call serial_notready(). You'll have a pretty full buffer if that takes a second or so. Yes, that makes it look like the meter is just sending data. And you are always reading an old sample.

从设置为 DISABLE 的 DCB 值开始.请注意该方案是脆弱的,您可以在 DOS 中非常可靠地关闭信号.现在你有一个介于两者之间的驱动程序.您很可能最终太晚关闭 RTS.这可能会导致读数过时.另一种方法是启动一个只连续读取的线程.让你的主代码只使用它读取的最后一个值.开销很低,串口很慢.

Start with the DCB values set to DISABLE. Beware that the scheme is brittle, you could turn the signal off pretty reliably back in the DOS. Now you've got a driver in between. You may well end up turning RTS off too late. Which risks getting a stale reading. An alternative is to startup a thread that just reads continuously. And have your main code just use the last value that it read. The overhead is quite low, serial ports are slow.

这篇关于串行设备使用 C 忽略 EscapeCommFunction的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆