通过485串口采集单片机发送的数据,一共有128路,应该如何循环采集?
我这里有128台仪器串联,然后其中一台连485接到到电脑上,电脑上的界面就负责采集这些仪器发送过来的数据,仪器发送数
据时是一台一台发的,有时间的先后顺序,不能同时发,我该怎么来循环接收这些数据呢?我现在用的是Timer事件,隔400ms
接收一次,不知道是否可以?有人推荐我用线程,但是我对线程一点都不了解,不知道怎么用。而且不知道是不是用线程会更
好,或者还有没有别的更好的方法。请大家指教!谢谢!
[解决办法]
关键是需要一个应用协议区分不同仪器
[解决办法]
[解决办法]
timer事件显然是不合理的,时间长了可能丢失数据,时间短了浪费资源,可以用异步方式或开一个线程监视数据的到来。
[解决办法]
为什么要循环接收?你还要按顺序接收数据?
我们公司也做这样的,就是让设备自动发,我这边等着收就是了。
硬件设备通讯应该都有规约协议的
设备也会有唯一的地址,除非你广播发数据。
如果是设备发送数据,那它们应该有个心跳时间,间隔多长时间给主机发一次,
那你就能算出你Timer的间隔时间了,设个数据缓冲区,接收设备发的数据
定时读数据和清理缓冲区。
如果你是给设备发请求数据,再让设备发回来,那就不用这么麻烦了吧。
[解决办法]
不用线程的话,做个数据缓冲区。
给表发数据
等待表回发数据(等待时间设个合理的时间,根据通讯速率)
判断缓冲区的数据,是否有数据
没有,再发N次,超过N次跳出。
有数据,判定数据是否正确。
发下一个表的数据
[解决办法]
就是暂时存设备发过来的数据的地方,你要不用线程,先这么做吧。
[解决办法]
485?你是要从串口读数据吧,用timer的话,如果超时的话,可能会丢失数据的
[解决办法]
最好统一输入,用485全都用485.用IP或COM线.就全用某一种.
你这一半,那一半,估计调试的时候够呛,你调试完全部,有空再调试一半是这,一半是那,也来得及.
用TIMER可行的.但不好,TIMER时间短的话,你的程序跟死机一个样,人家想用机器也不行.
你还是用线程好,调试好接收的时间间隔,就不停的收集数据,然后收集数据后,做好规则,再显示.
最好就是可以扔数据,就是坏数据,直接扔掉不要....不然就要修正数据.
[解决办法]
你这个情况就象我上次做的温度采集差不多,不过我的只有十几台设备。由于水平有限,采用循环发收,稳定性一直不好,偶尔会丢数据,就放弃了。等着看看你的成功方案~~我觉得设备多了用同步通讯方式肯定不行的,但异步操作我还是没有搞清WINDOWS下的机理。
[解决办法]
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!