C++Builder 程序员博客
30 Aug
比如做测试程序,不能用软件来模拟COM口的输入吗?
不是有工具么 SUDT_SerialNull
它创建成对的 串口 比如 com3 com4 你朝 com3写 com4就收到了,,
当然这是虚拟的。。
<
你需求描述让人误解。
如果你要写 SUDT_SerialNull 的功能 那我就无解了。
如果你安装了 SUDT_SerialNul 并成功 虚拟了 Com3 Com4串口
这时候任一一款 串口调试软件,朝 Com3 发送数据, 相对于你的Com4口来说就是有数据来了
应该就是你的
“用软件来模拟COM口的输入吗?”
。。
虚拟串口的话,你需要驱动编程来实现。。
<
这个是 OS 底层技术了, 不是一天两天能搞定的。 要做的话,建议学端口驱动。
重新再审题,,你做的是测试程序,,
SUDT_SerialNull
帮你实现了串口的虚拟
你的测试程序只需要实现向COM3 根据你程序的协议写数据,, 然后测试对象指向COM4即能测试。
<
这个你要做,参考 5 7 楼
买一个呗
要不就用破解版的吧
楼主要自己写虚拟串口的程序吗?
这可是个大工程
有免费的虚拟窗口软件 vspm就是
Virtual Serial Port Driver
楼主去搜一下这个,就是11楼说的东西,我就在用这个,有破解版,很好用
10 Aug
导师让我做个上位机,和单片机通信,用RS232,但是手头只有一台笔记本(没有串口),想用CB6先做个简单的串口通信例子试试,不知哪位知道有没有在笔记本上虚拟串口的软件,最好能有个例子,谢谢了。
你可以买个USB转串口的转换器直接连接单片机
VSPM 虚拟串口软件
http://www.skycn.com/soft/30517.html
虚拟串口软件很好用的,楼上的就是,可以在你的笔记本上虚拟出好多个串口,并且还可以互相通信,非常方便
极力推荐你使用Eltima公司出品的串口转TCP程序:Serial to Ethernet Connector,我手头有4.1的中国式正版。
非常感谢大家的帮助,VSPM我下了,但是不会用。3楼的说的正是我想实现的,就是在笔记本上虚拟2个串口,我开两个串口精灵可以相互通信那种,谁知道怎么实现啊?妖哥,你说的串口转TCP是什么意思?
vspm随机带的帮助多看看,装好以后,菜单里有个虚拟串口互联插件,要把某个目录下的ini文件覆盖到上级目录上去,还是仔细看看帮助吧,很清楚的
非常感谢,感觉CSDN真好,现在用CB 的人太少了,没想到这里还有这么多热心的高手,我好好学习一下。
26 Jul
软件A 通过串口检测是否连接硬件,通过串口发送0xaa,反回0×55.来检测。
如果无硬件软体无法运行(当然使用中还需要通过串口通讯)。
现在我没有软件A的硬件,所以写一个软件B,软件B可以虚拟一个串口出来,然后设置软件A使用这个虚拟的串口,软件A通过虚拟的串口通讯,实际数据是发送到软件B,软件B通过接收的数据(软件A通过虚拟串口发送的),返回不同的数据,虚拟出这个硬件出来,使软件A可以正常运行。
现在的问题是,怎么实现软件B的虚拟串口。。。
自己写一个虚拟串口有一定的难度,你可参考
http://bbs.driverdevelop.com/htm_data/11/0404/65804.html
网上有很多虚拟串口软件,如SerialNull,不知能否符合你的要求?
好久不见keiy老大。
好久不见keiy老大。
观摩观摩下。。。
自己顶一下。。
用现成的虚拟串口软件吧
<
似乎传说中的老大都出现了,趁机问个问题
再重复一边 上网 找个软件下载
VSPD XP 5 关键字
下了就能用
不行了 发个邮件给我
我发给你
34727498@qq.com
用现成的虚拟串口软件 是不行的..
比如虚拟一个串口COM3
软件A 通过COM3 发送数据,这个数据能到我的软件B中来吗? 软件B能通过COM3返回数据给软件A吗?
http://www.powerip.net/product_VSPM.htm
VSPM虚拟串口软件Ver2.76,它将串口信号转换为网络数据,配合TCP/UDP测试工具就可以满足你的要求
运行在Client模式,会自动建立几个虚拟串口,修改远程Server地址及端口。
这个软件是我见过的最好的了,而且免费的。
再推荐一个工具AccessPort,最好的串口数据监听软件。
<
DDK 开发虚拟串口.
但有虚拟串口未必能解决楼主的问题,软件A 通过串口检测是否连接硬件,可能要求硬件回相应信息的.
楼主最好还是找到连接的硬件,才能解决问题.
"软件A 通过串口检测是否连接硬件,通过串口发送0xaa,反回0×55.来检测"
如果能确定返回0×55,两个串口对接,用一个串口调试程序就可发送返回0×55,不用虚拟串口.
找一台有两个串口的电脑,或两台个有一个串口的电脑,两个串口互相能发送接收.
<
虽然这个有点麻烦,但还是再顶顶…
<
学习
再顶顶看看.
书店有本 龚建伟 写串口书里很详细…
看来是没什么希望了…
不会呀,学习!!!
真的没有了吗?
买个串口卡有2口的,然后用串口线将2个串口连接起来,这样你就可以写软件B了,如果实时性没有要求,根本就不用写,用个串口调试软件接收就可以了,然后该回应什么自己手动输入。
一般新装的串口卡串口是com3,com4,那么A用串口3,B用串口4,按照我说的就可以试验。
串口卡不贵,一块也就100块左右吧。我的电脑装机是不带串口的,都靠她了
这么个好帖居然这么长时间没有注意。
顶顶
<
<
我也一直在进行串口产品,和基于串口通信的系统开发!要用的反馈都是才有双串口通信活着双机手动检验!今天才知道还有虚拟一说,确实能节省很大人力啊!希望传奇大哥们这个问题多指点啊!
……这个问题..你可以先用虚拟串口的工具虚拟出两个串口..比如com1和com2 接着让它们互联..然后..你的A软件..打开com1 b软件.打开com2 他们就能互通了~
24 Jul
我这里有128台仪器串联,然后其中一台连485接到到电脑上,电脑上的界面就负责采集这些仪器发送过来的数据,仪器发送数
据时是一台一台发的,有时间的先后顺序,不能同时发,我该怎么来循环接收这些数据呢?我现在用的是Timer事件,隔400ms
接收一次,不知道是否可以?有人推荐我用线程,但是我对线程一点都不了解,不知道怎么用。而且不知道是不是用线程会更
好,或者还有没有别的更好的方法。请大家指教!谢谢!
关键是需要一个应用协议区分不同仪器
<
协议我这边定好了,也知道发过来的哪条数据是哪台仪器的,我想问的是我用什么方法来循环访问所有的仪器比较合理而且省时间又比较稳定。我用timer事件来控制相邻两次访问两台仪器的时间间隔是否合理。
timer事件显然是不合理的,时间长了可能丢失数据,时间短了浪费资源,可以用异步方式或开一个线程监视数据的到来。
为什么要循环接收?你还要按顺序接收数据?
我们公司也做这样的,就是让设备自动发,我这边等着收就是了。
硬件设备通讯应该都有规约协议的
设备也会有唯一的地址,除非你广播发数据。
如果是设备发送数据,那它们应该有个心跳时间,间隔多长时间给主机发一次,
那你就能算出你Timer的间隔时间了,设个数据缓冲区,接收设备发的数据
定时读数据和清理缓冲区。
如果你是给设备发请求数据,再让设备发回来,那就不用这么麻烦了吧。
怎么开线程监视数据的到来?我得先发送请求命令,仪器才给我发数据的。我得从第一台开始依次发请求命令依次接收数据,到最后
一台接收完毕后,此次循环才算结束。在给某一台仪器发完请求命令后,需等待几百毫秒再读取接收到的数据,从而获得此仪器的测
量数据。我不知道怎么用线程监视数据是否发过来了。以前还没用线程,所以一点概念都没有。
不用线程的话,做个数据缓冲区。
给表发数据
等待表回发数据(等待时间设个合理的时间,根据通讯速率)
判断缓冲区的数据,是否有数据
没有,再发N次,超过N次跳出。
有数据,判定数据是否正确。
发下一个表的数据
您说的做个数据缓冲区,不太明白您的意思。我在timer事件里发命令接收数据等等和您说的基本差不多。
就是暂时存设备发过来的数据的地方,你要不用线程,先这么做吧。
485?你是要从串口读数据吧,用timer的话,如果超时的话,可能会丢失数据的
最好统一输入,用485全都用485.用IP或COM线.就全用某一种.
你这一半,那一半,估计调试的时候够呛,你调试完全部,有空再调试一半是这,一半是那,也来得及.
用TIMER可行的.但不好,TIMER时间短的话,你的程序跟死机一个样,人家想用机器也不行.
你还是用线程好,调试好接收的时间间隔,就不停的收集数据,然后收集数据后,做好规则,再显示.
最好就是可以扔数据,就是坏数据,直接扔掉不要….不然就要修正数据.
你这个情况就象我上次做的温度采集差不多,不过我的只有十几台设备。由于水平有限,采用循环发收,稳定性一直不好,偶尔会丢数据,就放弃了。等着看看你的成功方案~~我觉得设备多了用同步通讯方式肯定不行的,但异步操作我还是没有搞清WINDOWS下的机理。
我这128台仪器是串联的,每个都有个485的接口,然后把仪器两两串联起来,到最后一台仪器就把它的485接口和电脑连上就行了。其实都是485的串口,没涉及其他的。但是每台仪器发送接收数据不能同时,因为同时就造成数据流阻塞了。如果用线程具体该怎么写程序啊?请哪位高手说详细点!
485通讯的时候,每个设备都是有个地址的,每个设备都不能同时发送消息,但是作为程序,你不需要管他,应为这是硬件实现的
,你只需要把数据读出,保存在你自己的缓冲区里就可以了,建议还是做个线程吧,线程读取到数据后,填充到一个队列里,然后通知主程序,主程序从队列里取出数据,处理。
线程的例子,你网上查一下,很多的,也蛮简单的
您有相关的例子吗?网上搜的例子,我一点都看不懂,而且还不知道是不是针对我的这个编程软件的。
<
不要用定时器,建立一个辅助线程,在其中创建一个"异步"模式的串口,设置好事件屏蔽字,然后等待发生事件.可以最快地响应串口接收任务.
不要用线程,
用485/MODBUS最简单:
1.用485串行通迅;
2。总线式,协议用支持多端口的MODBUS协议;
但你的每台单片机如果不支持此协议就麻烦了,
因为用总线式,如果主机发命令,每台机都会
收到相同的命令串,所以,要支持多端口的软协议;
485/总线式一定要是主/从式的,
电脑是主,仪器是从,否则,仪器各顾各的发,总线上就乱了套;
电脑不发命令,仪器就不能发数据,
电脑发的取数命令中包含是哪一个节点的编号,这样,对方就响应,
电脑只要按顺序一个一个发,每个节点就依次乖乖的发数据;
这个最好的协义就是 MODBUS;
用mscomm控件,将接受的数据先缓存然后用线程处理数据,这时候就要注意临界区问题了。使用std::vector<BYTE>。接收mscomm的数据,发送当然可以使用timer,主要是发送和处理数据的时间间隔点。
拴在一根绳上的蚂蚱,串在一起了
只能一个一个的处理,如果时间太长,就分两根"绳子",每根上拴64个,依次类推
如果是一根"绳子",用不用线程无所谓
如果是多根绳子,线程或许有些改善
最好不要用Timer,因为Timer是占用的主线程时间,如果主线程非常忙的时候,Timer就不会进去,也就有可能延时,不会是实时 的接收到数据,建议用线程
在线程里面用Sleep函数来控制接收时间
一个主线程负责收发调度,一个读线程,一个写线程,最好不要用窗口线程的TIMER事件处理调度和收发,效率不高,而且对界面有影响,一般象这种慢速的读写最好开个单独线程,有数据到了可以直接向窗口发消息,要写数据可以直接向写线程发送线程消息!
你们说了这么多建议,真的很感谢!可是我还是对线程一点都不了解!能不能给个例子呢?我现在最主要是连线程是什么,怎么用都不知道啊!
楼主啊。。你连线程都没有碰过,做这个项目是不是有点牵强啊。。。。
我也做过类似的项目,不过我只需要和最多13个单片机通信,我的通信时间间隔是200MS,通信方式是这样的:
1.上位机每隔 200MS 发送一个字节,代表“通道号”,比如发送“02”。
2.这时候,下面 13 个单片机全部都会收到这个字节,即“02”
3.每个单片机检查自己的通道号是否是“02”,如果是,则把自己的规定内容发给上位机,如果不是,则不做任何动作。(当然,单片机各自的通道号是不能重复的)
4.上位机收到从单片机“02”发来的数据进行处理。完成后从步骤1开始重复,发出下一个通道号“03”。
这样循环下去,依次将通道号发送给每个单片机。。
你那 128 台单片机就可以使用这种方式来通信,简单,高效。。。。。。。
你记住,应该由上位机来决定“谁给我数据”,而不是由单片机想发就发,或者自己定义时序来发,这样的话,你根本就无法控制数据的流量和准确性。。。。切记,切记
楼主啊。。你连线程都没有碰过,做这个项目是不是有点牵强啊。。。。
我也做过类似的项目,不过我只需要和最多13个单片机通信,我的通信时间间隔是200MS,通信方式是这样的:
1.上位机每隔 200MS 发送一个字节,代表“通道号”,比如发送“02”。
2.这时候,下面 13 个单片机全部都会收到这个字节,即“02”
3.每个单片机检查自己的通道号是否是“02”,如果是,则把自己的规定内容发给上位机,如果不是,则不做任何动作。(当然,单片机各自的通道号是不能重复的)
4.上位机收到从单片机“02”发来的数据进行处理。完成后从步骤1开始重复,发出下一个通道号“03”。
这样循环下去,依次将通道号发送给每个单片机。。
你那 128 台单片机就可以使用这种方式来通信,简单,高效。。。。。。。
你记住,应该由上位机来决定“谁给我数据”,而不是由单片机想发就发,或者自己定义时序来发,这样的话,你根本就无法控制数据的流量和准确性。。。。切记,切记
使用定时器是可以的, 200ms 的间隔, 但是485总线上能挂满128个设备, 这个问题还有待验证.
我们现在称与485总线上的设备通讯一次的过程叫做轮询.
必须要保证在任何时刻, 电脑只与485总线上的一台设备通讯, 并且一定要等待设备返回了数据之后才能轮询下一个485设备.
可以把128个设备地址, 建成一个队列, 用一个定时器每200ms 一次一个一个的与设备通讯
它的过程就是
PC->串口->PC发送的数据->485总线->设备1->设备返回的数据->485总线->PC串口->PC
PC->串口->PC发送的数据->485总线->设备2->设备返回的数据->485总线->PC串口->PC
PC->串口->PC发送的数据->485总线->设备3->设备返回的数据->485总线->PC串口->PC
PC->串口->PC发送的数据->485总线->设备1->设备返回的数据->485总线->PC串口->PC
假设有3个设备接在485总线上, 上面的过程就演示了整个轮询的过程
Mark
<
<
恩。。。怕出问题是正常的。。
说实话,我不太信任 485(CAN 总线)。。。
一个最主要的原因就是,他容易受干扰。。。。。。
至于多长时间间隔去通信一次,这个要看你下面的单片机执行的具体任务和耗费的时间,不同的单片机和其执行代码,所消耗的时间是不同的,这个你应该和你们搞单片机的人多沟通(我就是的)。。。
我这个项目最长碰到的问题就是:
1.通信被干扰,导致数据不对。(我们的解决办法:对数据进行 CRC 校验)
2.单片机故障,导致某一个单片机卡死,独占整个 CAN 总线,其他单片机都无法通信(找你们那个做单片机的人解决吧)。。。。
3.内存泄露(多由串口通信引起),如果你的上位机运转时间很长的话,请你在实验室的时候多多观察其内存,我写的上位机程序,最长可以在别人的工厂里面连续不停得开机 2 个月,没出过问题
最后,128路单片机确实有点多。。。。
好像只能是127路吧,其中第一路是广播地址用的。参见modbus协议。
另开线程吧
回帖是一种美德!
开一个工作线程就行了,采用轮询方式访问硬件设备
读写的话我建议使用异步方式访问串口,对于不同的设备或者是协议,可以设置不同的延时参数
定时器不够稳定
非阻塞读写串口线程这么写
0如果线程未结束就继续执行循环
1判断主线程是否改变了状态。
2如果已经调用了读串口函数就看看有没有接收到东西。
3如果接受到看看数据是否完整。完整就准备下一个向设备写的命令,不完整就准备继续读串口函数。
4如果数据完整,写串口向下一个设备发命令。
5如果允许读串口,调用读串口函数。
6Sleep(1);睡一下,少占CPU。睡醒了回到0。
好吧,我承认我上面说了假话.. 看了美女忘了学习 O(∩_∩)O~
这类应用最好不使用TIMER,还是使用线程收数,并开足够的缓冲区!
Mark!
你的和我的一样,只不过我的下位机没有那么多,我是用线程接收的,开一个辅助线程用来接收数据,主线程用来显示数据
你最好是用pc做主机,485设备作从机,主机发命令,从机应答的形式,每个从机要有地址。
1.485接口的设备一般可以设定地址
2.pc 发地址
3.pc 接收相应地址的数据
4.第二项和第三项重复循环。
各位大侠就是厉害啊,顶,有钱的捧个钱场,没钱的捧个人场啊。
<
不错
哈哈
mark
MODBUS吧
MARK。。。
就快用到咯~~~
学习下。。。
不错哦
异步IO。
haohaohao….
学习来的
回帖是一种美德!
回帖是一种美德!
iiiiiiiiiiiiiiiiiiiiiiiiiiiii
ooooooooooooooooooooooooooooooooooooooooooo
多线程
用timer事件肯定是不合理的,应该用异步方式或开一个线程监视数据的到来。
.
呵呵呵,用我的组态软件吧,你只需要写两个函数就完成啦
一个是定义发送命令字节
一个是处理接收数据
其它的全部由组态软件完成了。
将生成128个单元,每个单元有多少数据你可以通过资源文件定义。
不过,价格有点高
我是来学习的。
仔细看了一下,18、19楼说的比较好,不过你要考虑多线程。一个串口处理128台下位机完成一个循环的时间比较长,如果对轮询时间有要求就要考虑多串口了,可以参考MOXA的多串口卡
没有事件吗
纯顶贴,不发表任何以及爱你
jf
不要用Timer,除非你想整死客户或系统是拿来演示教学用的.
用多串口卡和多线程,1线程–>1串口,1串口–>n控制器
,128个控制器可以相当是实时连接
同时应考虑数据同步,不然会出现系统错误,这比较复杂
Windows 下可以考虑使用WaitCommEvent
PC->串口->PC发送的数据->485总线->设备1->设备返回的数据->485总线->PC串口->PC
PC->串口->PC发送的数据->485总线->设备2->设备返回的数据->485总线->PC串口->PC
PC->串口->PC发送的数据->485总线->设备3->设备返回的数据->485总线->PC串口->PC
。。。。。。。
pc向串口设备发送读取数据指令
串口设备响应之后返回数据
进入下一个设备
如此循环就可以
上面大家说了半天,能告诉我一下出了 timer 能实现循环,还有什么
方法能够实现循环那??
, 如果不用 timer 做循环的话,那么用什么方式循环那?
是用 for 语句吗?谢谢。
其实这种方案有很大的问题,128路串联的话,这个和IP通讯不同,它没有侦测线路是否繁忙的命令,所以每个机器都必须不停的接收数据,判断协议,如果有数据通信,不是自己的就不通讯,这样线路就异常繁忙(串口的传输速率太低了)。
至于楼主问的timer中做循环轮询是行不通的,应该采用串口异步通信,线程中事件通知的方式。
不过我建议楼主还是用多串口卡并发通讯比较稳当.
#include <Process.h>
到这个文件里看看,解决办法就在里面
写一个静态函数,做为处理流程
用上面包将该静态函数启动为线程。
不用Timer处理
<
最近看了资料,485可能用阻塞更简单。
我这里有128台仪器串联,然后其中一台连485接到到电脑上,电脑上的界面就负责采集这些仪器发送过来的数据,仪器发送数
据时是一台一台发的,有时间的先后顺序,不能同时发,我该怎么来循环接收这些数据呢?我现在用的是Timer事件,隔400ms
接收一次,不知道是否可以?有人推荐我用线程,但是我对线程一点都不了解,不知道怎么用。而且不知道是不是用线程会更
好,或者还有没有别的更好的方法。请大家指教!谢谢!
———————————–
建议在unix 或 Linux ,使用select方式,比较好处理些。
后台负责数据采集,
前台负责数据展现。
windows下操作系统不稳定,容易出问题,连你自己都不知道。
在windows ,使用线程机制,每个线程采用阻塞的方式,也是可以的。但控制起来不是非常好,只要其中一个线程数据或处理有点小问题,呵呵,问题就麻烦了。
485就是一对一的串口通信,多一个地址字节而已。
放在TIMER里绝不可取!TIMER停掉了,你都不知道怎么回事,一个繁忙的进程里,TIMER可能不触发或延迟触发。
学习了!
11 Apr
哪位朋友有这方面的例子,能不能将部分源码贴出来看看,或者发一份给我,不胜感激.
最好是使用Pcomm控件的串口通信程序.
用WindowsAPI设计多线程的串行通信ActiveX控件
http://www.laogu.com/wz_28836.htm
谢谢,我看看先..
<
网页打不开哦..
<
29 Mar
哪位朋友有用Pcomm控件实现串口通信的源码例子,能否给小弟发一点学习一下,不胜感激.
Email:herozhang002@163.com
谢谢.
<
用Pcomm Pro开发串行通信程序
http://www.qqread.com/bcb/d258352.html
到官网下载help文件
谢谢..
<
已经看过这个例子了,不过似乎例子太简单了一点,所以才想看看有没有其它例子…不过还是谢谢你.
<
哪里,能给个链接么?谢谢.
<
23 Jan
c++builder2010用API做串口应用,参考了网上很多资料,采用异步方式,用一个线程监视事件,然后发送信息给主线程做数据处理。发现用几个问题,请教各位:
1、监视线程一直无限循环,CPU占用一直100%,用个SLEEP(1)后CPU占用下来了,事件一个也监测不到了。
//—- Place thread code here —-
mainform->commwatchthread=true;
OVERLAPPED os;
DWORD dwMask,dwTrans,err;
//if(!SetCommMask(mainform->hCom, EV_RXCHAR|EV_TXEMPTY))
//return;
//memset(&os,0,sizeof(OVERLAPPED));
unsigned char rbuf[256];
unsigned long rbytes;
os.Offset=0;
os.OffsetHigh=0;
os.hEvent=CreateEvent(NULL,TRUE,false,NULL);
if(os.hEvent == NULL) // error creating event; abort
return;
while(!Terminated)
{
if(WaitCommEvent(mainform->hCom,&dwMask,&os))
{
GetOverlappedResult(mainform->hCom,&os,&dwTrans,true);
if(dwMask&EV_RXCHAR)
{
PostMessage(mainform->Handle,WM_COMM_RXCHAR,0,0);
}
/* rbytes=mainform->ReceiveData(rbuf,256);
if(rbytes>0)
{
//mainform->memo1->Lines->Add(rbuf[0]);
for(unsigned long i=0;i <rbytes;i++)
{
mainform->stkRxdata(rbuf[i]);
}
}
}
*/
if(dwMask&EV_TXEMPTY)
{
//SendMessage(mainform->Handle,WM_COMM_TXEMPTY,0,0);
}
if(dwMask)
{
PostMessage(mainform->Handle,dwMask,0,0);
}
}
else
{
if(GetLastError() == ERROR_IO_PENDING);
// fWaitingOnStat= TRUE;
else{ // error in WaitCommEvent; abort
ShowMessage("error in WaitCommEvent");
break;
}
}
//Sleep(5);
}
CloseHandle(os.hEvent);
mainform->commwatchthread=false;
2、数据发送函数里得不到发送长度信息
2、数据发送函数里得不到发送长度信息
DWORD __fastcall Tmainform::SendData(unsigned char *sBuffer,DWORD dwBytesWritten)
{
DWORD wBytes;
BOOL bWriteStat;
DWORD dwError;
COMSTAT ComStat;
ClearCommError(hCom, &dwError, &ComStat);
wBytes = ComStat.cbOutQue;
if (dwBytesWritten < wBytes)
wBytes = dwBytesWritten;
//OutputDebugString(wBytes);
//memo1->Lines->Add(wBytes);
PurgeComm(hCom,PURGE_TXCLEAR);//|PURGE_RXCLEAR);
bWriteStat =WriteFile(hCom,sBuffer,dwBytesWritten,&wBytes,&ov_Write); //
if(!bWriteStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
WaitForSingleObject(ov_Write.hEvent,1000);
//memo1->Lines->Add(wBytes);
//PurgeComm(hCom, PURGE_TXABORT|PURGE_TXCLEAR);
return wBytes;
}
else
{
return 0;
}
}
return wBytes;
}
3、数据发送出去后经常接收不到数据,而再次发送数据后,前一次的数据也一起接收到了,不知道是发送的问题还是接收的问题,我感觉是发送的问题,因为监视线程没有收到EV_RXCHAR事件,
DWORD __fastcall Tmainform::ReceiveData(unsigned char *rBuffer,DWORD nMaxLength)
{
COMSTAT ComStat;
BOOL fReadStat;
DWORD dwErrorFlages,dwLength;
ClearCommError(hCom,&dwErrorFlages,&ComStat);
dwLength=(((DWORD)nMaxLength <ComStat.cbInQue)?(DWORD)nMaxLength:ComStat.cbInQue);
if(dwLength>0)
{
fReadStat=ReadFile(hCom,rBuffer,dwLength,&dwLength,&ov_Read);
if(!fReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
{
if(WaitForSingleObject(ov_Read.hEvent,5000)==WAIT_TIMEOUT)
dwLength=0;
}
else
{
dwLength=0;//异常情况
}
}
}
return dwLength;
}
下面是初始化串口代码
//===================================================================================
bool __fastcall Tmainform::InitComm(AnsiString DevicePort,DCB dcb)
{
COMMTIMEOUTS CommTimeOuts;
BOOL fSuccess;
hCom = CreateFile(DevicePort.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, //必须以opened w/exclusive-access
NULL, //无安全属性
OPEN_EXISTING, //必须用OPEN_EXISTING
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠I/O操作
NULL //对通信设备必须是NULL
);
if(hCom == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"打开通信设备文件失败!","错误",MB_OK);
return false;
}
if(!SetupComm(hCom,BLOCK_LENGTH,BLOCK_LENGTH))
{
MessageBox(NULL,"设置串行口内部输入、输出缓冲区长度操作异常!","错误",MB_OK);
return false;
}
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess)
{
MessageBox(NULL,"获取通信设备控制块数据结构操作异常!","错误",MB_OK);
return false;
}
fSuccess = SetCommState(hCom, &dcb);
if(!fSuccess)
{
MessageBox(NULL,"设置通信设备控制块数据结构操作异常!","错误",MB_OK);
return false;
}
PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); //清干净输入、输出缓冲区
GetCommTimeouts(hCom, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = 100;
CommTimeOuts.ReadTotalTimeoutMultiplier=500;
CommTimeOuts.ReadTotalTimeoutConstant=600;
CommTimeOuts.WriteTotalTimeoutMultiplier=500;
CommTimeOuts.WriteTotalTimeoutConstant = 500;
SetCommTimeouts(hCom, &CommTimeOuts);
//memset(&ov_Read, 0, sizeof(OVERLAPPED));
ov_Read.Offset=0;
ov_Read.OffsetHigh=0;
ov_Write.Offset=0;
ov_Write.OffsetHigh=0;
//memset(&ov_Write, 0, sizeof(OVERLAPPED));
ov_Read.hEvent = CreateEvent(NULL, TRUE, false, NULL);
ov_Write.hEvent = CreateEvent(NULL, TRUE, false, NULL);
SetCommMask(hCom, EV_RXCHAR|EV_TXEMPTY
|EV_BREAK|EV_CTS|EV_DSR
|EV_ERR|EV_RING|EV_RLSD);//设置事件驱动的类型
OutputDebugString("串口初始化成功!");
return true;
}
沙发,哈哈
<
使用PCOMM.DLL比较稳定
開源的Victor 里有現成demo
以前BCB6用的是Victor的控件,现在升级到2010最新的控件能安装,用着有问题,所以考虑自己用API写,这样也有个好处,软件体积会减小一些的。
现在问题基本解决了,我再测试一下,如果没问题我将公开源代码,有时间也可以考虑做个控件。
用API读写串口用不了这么多代码,太乱了
<
我在2010下用VICTOR的控件,接收端有一半的数据收不到,不知道是不是控件有问题,所以才用API写。也许是我应用的问题,大家可以试试。
<
<
5 Jan
代码如下:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Str;
Str = Edit1->Text;
this->ComPort1->WriteStr(Str);
}
//—————————————————————————
void __fastcall TForm1::ComPort1RxChar(TObject *Sender, int Count)
{
AnsiString str;
this->ComPort1->ReadStr(str,Count);
Memo1->Text = Memo1->Text + str;
}
问题是: 当我点击“发送”按钮,向串口comm1发送字符串时,在Memo1中获取不到发送的字符串,这是怎么回事?小弟刚接触C++,实属菜鸟级别,望高手指点,另外,有没有关于串口编程的例子程序,供小弟学习参考,小弟将不胜感激!
1、你串口连接到什么目标设备?
2、你串口配置和目标设备匹配么?
3、满足前边1、2条件下,你的串口成功打开了么?
4、向串口发送什么东西,由你决定;但是从串口上收到什么数据,由串口连接的设备决定,除非你自己做了一个转换口,在同一串口上收发对调。
lz是下位機接收端 收不到數據?
可以用串口調試助手先試試
看是沒有發下去
還是沒有收到
要例子的話
可以用開源的 Victor 串口控件 裏面有現成的demo
http://www.cppfans.com/
谢谢楼上的解答,
我现在是做的测试程序,我用的是虚拟串口软件,在自己电脑上虚拟了com1,com2 两个串口,我想在这两个串口中通信,比如说,com1发送数据,com2接收数据,这样能实现吗?请指教!
“我用的是虚拟串口软件,在自己电脑上虚拟了com1,com2 两个串口,我想在这两个串口中通信,”
首先你要確定 你虛擬成功了沒有?
“com1发送数据,com2接收数据,” 能不能成功?
成功的話再去測試自己的程序
<
30 Dec
这是妖哥以前发的代码,我运行有4个错误,为什么呢?
(118) : error C2065: 'Win32Platform' : undeclared identifier
(161) : error C2317: 'try' block starting on line '137' has no catch handlers
(161) : error C2143: syntax error : missing ';' before '__finally'
(162) : error C2143: syntax error : missing ';' before '{'
原文:
貌似我的生意最近很火?点名提问的挺多,怎么不见专家分涨呢。汗。。。
翠花,上代码。
以下代码在我的机器上试验成功,希捷ST3 250G的串口硬盘,物理序列号可以读取。
C/C++ code#define IDENTIFY_BUFFER_SIZE 512
#define IDE_ATAPI_IDENTIFY 0xA0
#define IDE_ATA_IDENTIFY 0xEC
#define DFP_RECEIVE_DRIVE_DATA 0×0007c088
#pragma pack(1)
typedef struct _IDSECTOR
{
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
}IDSECTOR, *PIDSECTOR;
typedef struct _DRIVERSTATUS
{
BYTE bDriverError;
BYTE bIDEStatus;
BYTE bReserved[2];
DWORD dwReserved[2];
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
typedef struct _SENDCMDOUTPARAMS
{
DWORD cBufferSize;
DRIVERSTATUS DriverStatus;
BYTE bBuffer[1];
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
typedef struct _IDEREGS
{
BYTE bFeaturesReg;
BYTE bSectorCountReg;
BYTE bSectorNumberReg;
BYTE bCylLowReg;
BYTE bCylHighReg;
BYTE bDriveHeadReg;
BYTE bCommandReg;
BYTE bReserved;
} IDEREGS, *PIDEREGS, *LPIDEREGS;
typedef struct _SENDCMDINPARAMS
{
DWORD cBufferSize;
IDEREGS irDriveRegs;
BYTE bDriveNumber;
BYTE bReserved[3];
DWORD dwReserved[4];
BYTE bBuffer[1];
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
#pragma pack()
void ChangeByteOrder(LPSTR lpString, int nLen)
{
USHORT i;
CHAR c;
// 63 63 72 75 6E 2E 63 6F 6D
for(int i = 0; i < nLen; i += 2)
{
c = lpString[i];
lpString[i] = lpString[i+1];
lpString[i+1] = c;
}
}
bool CrnGetHDSerialNumber(LPSTR lpBuf)
{
strcpy(lpBuf, "");
HANDLE hDevice;
if(Win32Platform == VER_PLATFORM_WIN32_NT)
// 获取第一个硬盘,如果有多个,更改PhysicalDrive?就可以了。
hDevice = CreateFile("\\.\PhysicalDrive0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
else
hDevice = CreateFile("\\.\SMARTVSD", 0, 0, NULL, CREATE_NEW, 0, 0);
if(hDevice == INVALID_HANDLE_VALUE) return false;
SENDCMDINPARAMS scip = { 0 };
char szBuffer[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE] = { 0 };
DWORD dwBytesRet = 0;
bool bSuccess = false;
try
{
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bSectorCountReg = 1;
scip.irDriveRegs.bSectorNumberReg = 1;
scip.irDriveRegs.bDriveHeadReg = IDE_ATAPI_IDENTIFY;
scip.irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
if(DeviceIoControl(hDevice,
DFP_RECEIVE_DRIVE_DATA,
&scip,
sizeof(SENDCMDINPARAMS) - 1,
szBuffer,
sizeof(szBuffer),
&dwBytesRet,
NULL))
{
PSENDCMDOUTPARAMS pOut = (PSENDCMDOUTPARAMS)szBuffer;
PIDSECTOR pIdSec = (PIDSECTOR)(pOut->bBuffer);
ChangeByteOrder(pIdSec->sSerialNumber, sizeof(pIdSec->sSerialNumber));
strncpy(lpBuf, pIdSec->sSerialNumber, 20);
bSuccess = true;
}
}
__finally
{
CloseHandle(hDevice);
}
return bSuccess;
}
//—————————————————————————
// 测试一哈
void __fastcall TForm1::Button2Click(TObject *Sender)
{
char sz[255];
CrnGetHDSerialNumber(sz);
ShowMessage(String(sz).Trim());
}
lz 你是不是忘了拷贝部分代码上去?
我试了 完全可以的
要不你留下聯繫方式
我把工程發給你
(161) : error C2317: 'try' block starting on line '137' has no catch handlers
(161) : error C2143: syntax error : missing ';' before '__finally'
(162) : error C2143: syntax error : missing ';' before '{'
少了一个catch啊
可以的,我用了完全,我找找程序
我的EMAIL: yelvfujiamian@sina.com ,谢谢了.
哪位大侠有VC6.0的完整的工程,发到我的邮箱好吗? yelvfujiamian@sina.com
只有BCB的
有BCB的DLL形式的COM组件源码吗?用来RS232通信的
我想学习下
xsnbzj@163.com
我运行了下,为什么出现以下:
[C++ Error] Unit1.cpp(145): E2451 Undefined symbol 'IDENTIFY_BUFFER_SIZE'
不好意思,拷漏了
还是不行,请发一个源程序给我吧:lyc3184@163.com,谢谢了,
30 Dec
这是妖哥以前发的代码,我运行有4个错误,为什么呢?
(118) : error C2065: 'Win32Platform' : undeclared identifier
(161) : error C2317: 'try' block starting on line '137' has no catch handlers
(161) : error C2143: syntax error : missing ';' before '__finally'
(162) : error C2143: syntax error : missing ';' before '{'
原文:
貌似我的生意最近很火?点名提问的挺多,怎么不见专家分涨呢。汗。。。
翠花,上代码。
以下代码在我的机器上试验成功,希捷ST3 250G的串口硬盘,物理序列号可以读取。
C/C++ code#define IDENTIFY_BUFFER_SIZE 512
#define IDE_ATAPI_IDENTIFY 0xA0
#define IDE_ATA_IDENTIFY 0xEC
#define DFP_RECEIVE_DRIVE_DATA 0×0007c088
#pragma pack(1)
typedef struct _IDSECTOR
{
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
}IDSECTOR, *PIDSECTOR;
typedef struct _DRIVERSTATUS
{
BYTE bDriverError;
BYTE bIDEStatus;
BYTE bReserved[2];
DWORD dwReserved[2];
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
typedef struct _SENDCMDOUTPARAMS
{
DWORD cBufferSize;
DRIVERSTATUS DriverStatus;
BYTE bBuffer[1];
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
typedef struct _IDEREGS
{
BYTE bFeaturesReg;
BYTE bSectorCountReg;
BYTE bSectorNumberReg;
BYTE bCylLowReg;
BYTE bCylHighReg;
BYTE bDriveHeadReg;
BYTE bCommandReg;
BYTE bReserved;
} IDEREGS, *PIDEREGS, *LPIDEREGS;
typedef struct _SENDCMDINPARAMS
{
DWORD cBufferSize;
IDEREGS irDriveRegs;
BYTE bDriveNumber;
BYTE bReserved[3];
DWORD dwReserved[4];
BYTE bBuffer[1];
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
#pragma pack()
void ChangeByteOrder(LPSTR lpString, int nLen)
{
USHORT i;
CHAR c;
// 63 63 72 75 6E 2E 63 6F 6D
for(int i = 0; i < nLen; i += 2)
{
c = lpString[i];
lpString[i] = lpString[i+1];
lpString[i+1] = c;
}
}
bool CrnGetHDSerialNumber(LPSTR lpBuf)
{
strcpy(lpBuf, "");
HANDLE hDevice;
if(Win32Platform == VER_PLATFORM_WIN32_NT)
// 获取第一个硬盘,如果有多个,更改PhysicalDrive?就可以了。
hDevice = CreateFile("\\.\PhysicalDrive0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
else
hDevice = CreateFile("\\.\SMARTVSD", 0, 0, NULL, CREATE_NEW, 0, 0);
if(hDevice == INVALID_HANDLE_VALUE) return false;
SENDCMDINPARAMS scip = { 0 };
char szBuffer[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE] = { 0 };
DWORD dwBytesRet = 0;
bool bSuccess = false;
try
{
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bSectorCountReg = 1;
scip.irDriveRegs.bSectorNumberReg = 1;
scip.irDriveRegs.bDriveHeadReg = IDE_ATAPI_IDENTIFY;
scip.irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
if(DeviceIoControl(hDevice,
DFP_RECEIVE_DRIVE_DATA,
&scip,
sizeof(SENDCMDINPARAMS) - 1,
szBuffer,
sizeof(szBuffer),
&dwBytesRet,
NULL))
{
PSENDCMDOUTPARAMS pOut = (PSENDCMDOUTPARAMS)szBuffer;
PIDSECTOR pIdSec = (PIDSECTOR)(pOut->bBuffer);
ChangeByteOrder(pIdSec->sSerialNumber, sizeof(pIdSec->sSerialNumber));
strncpy(lpBuf, pIdSec->sSerialNumber, 20);
bSuccess = true;
}
}
__finally
{
CloseHandle(hDevice);
}
return bSuccess;
}
//—————————————————————————
// 测试一哈
void __fastcall TForm1::Button2Click(TObject *Sender)
{
char sz[255];
CrnGetHDSerialNumber(sz);
ShowMessage(String(sz).Trim());
}
lz 你是不是忘了拷贝部分代码上去?
我试了 完全可以的
要不你留下聯繫方式
我把工程發給你
(161) : error C2317: 'try' block starting on line '137' has no catch handlers
(161) : error C2143: syntax error : missing ';' before '__finally'
(162) : error C2143: syntax error : missing ';' before '{'
少了一个catch啊
可以的,我用了完全,我找找程序
我的EMAIL: yelvfujiamian@sina.com ,谢谢了.
哪位大侠有VC6.0的完整的工程,发到我的邮箱好吗? yelvfujiamian@sina.com
只有BCB的
有BCB的DLL形式的COM组件源码吗?用来RS232通信的
我想学习下
xsnbzj@163.com
我运行了下,为什么出现以下:
[C++ Error] Unit1.cpp(145): E2451 Undefined symbol 'IDENTIFY_BUFFER_SIZE'
不好意思,拷漏了
还是不行,请发一个源程序给我吧:lyc3184@163.com,谢谢了,