68336016 发表于 2012-12-1 06:26:52

江湖救急:一个串口接收软件,会无故自动退出,毫无提示

我用才CSerialPort类写的一个串口接收软件,波特率是115200,下位机每10ms发送20个字节到上位机,上位机只接收不发送。
传输速度是够的,我保存了几十万行数据都不会出错,而且在软件里面也判断了帧头和长度,确保传输有错也能忽略掉接收下一帧。

软件以前一直在用没有什么问题的,昨天同事(新笔记本,其他软件只有金山卫士)发现用着会自动退出,但是监控下位机仍然有数据上传,传过来的数据也是正常的。

于是我在自己电脑连续测试(加大数据量)了5,6个小时,软件接收处理数据一切正常的。后来我用软件(应该是耗内存类型)进行录像,发现我的串口软件界面的数据就会混乱然后自动退出,重新了同事遇到的现象。(这时我继续用串口调试助手接收下位机数据,数据仍然是正常的)。

现在我觉得就是一些耗内存型或者病毒扫描软件导致我的串口软件自动退出,但是我软件在任务管理器也就占用15M左右,想不明白。为什么偏偏把我的软件给弄崩溃了?

farmerzhangdl 发表于 2012-12-1 06:26:53

68336016 发表于 2012-12-4 01:18 static/image/common/back.gif
不是干扰啊
我现在到达客户所在地,现在宾馆4台笔记本测试,相同硬件



试过我上面说的生产者-消费者模型的方法了么?老是等大家猜测不是办法,我觉得你用个把个小时写一个试一下就什么都知道了。肯定是软件的问题,你就查代码吧。要不然你就把代码贴出来给大伙儿看看,一个串口软件也不是什么保密的东西。

winfisher 发表于 2012-12-1 07:10:45

有杀毒软件会影响串口数据接收。比如瑞星,能明显接收到瑞星在串口数据插入的瑞星广告。
你用portmon监听串口,看一下,在崩溃的时候,串口数据是怎样的?

NJ8888 发表于 2012-12-1 08:07:22

一般崩溃是数组越界,比如你收的数据包带有地址,这个包送到数组给定空间开始的地方,正常是这个地址是有效的,但错了话,送到其他地方,覆盖了其他数据,程序会崩溃

68336016 发表于 2012-12-1 09:27:13

NJ8888 发表于 2012-12-1 08:07 static/image/common/back.gif
一般崩溃是数组越界,比如你收的数据包带有地址,这个包送到数组给定空间开始的地方,正常是这个地址是有效 ...

软件写得少,经验不足啊

反复试验很多次,发现很可能是一个编辑框刷新得太快10ms一次,导致软件静悄悄崩溃退出。
改成1s一次后,在我电脑上边测试边录像也没事了。

还得到同事电脑验证下

68336016 发表于 2012-12-1 09:31:05

winfisher 发表于 2012-12-1 07:10 static/image/common/back.gif
有杀毒软件会影响串口数据接收。比如瑞星,能明显接收到瑞星在串口数据插入的瑞星广告。
你用portmon监听串 ...

崩溃时候串口上来数据还是对的

应该是我软件写的有问题,每10ms收到一个数据更新下一个编辑框,可能编辑框刷新速度跟不上,导致串口上来的数据不能及时处理。

68336016 发表于 2012-12-1 09:31:33

winfisher 发表于 2012-12-1 07:10 static/image/common/back.gif
有杀毒软件会影响串口数据接收。比如瑞星,能明显接收到瑞星在串口数据插入的瑞星广告。
你用portmon监听串 ...

崩溃时候串口上来数据还是对的

应该是我软件写的有问题,每10ms收到一个数据更新下一个编辑框,可能编辑框刷新速度跟不上,导致串口上来的数据不能及时处理。

北小斗 发表于 2012-12-1 09:43:13

用C#做过串口工具,刷新太快确实会出现这个问题尤其绘制波形的时候

wye11083 发表于 2012-12-1 10:19:50

不会用线程啊?后台收,前台处理。

mcu_lover 发表于 2012-12-1 10:31:40

wye11083 发表于 2012-12-1 10:19
不会用线程啊?后台收,前台处理。

应该是前台刷新不过来了,10ms刷新一次编辑框,肯定不行,太快了,数据量大了会卡死的。

lijieamd 发表于 2012-12-1 10:35:44

这位兄弟,我猜测有可能是跨线程操作的锁死现象,你是不是用了串口的接受event函数接收数据?如果是用的这个,就极有可能

68336016 发表于 2012-12-1 10:40:33

本帖最后由 68336016 于 2012-12-1 10:42 编辑

wye11083 发表于 2012-12-1 10:19 static/image/common/back.gif
不会用线程啊?后台收,前台处理。

线程简单应用也会

不过能不那么复杂就尽量用简单的办法了

我们做事比较郁闷的,软件和电路板都是安装在设备上的,公司没有多余设备,生产好就发给客户。
老板宗旨从来不给时间测试,东西组装差不多就催交货,收到钱再说,产品质量那是无所谓的。但是设备发到外省有问题就麻烦了。
搞了一年多,连我这个所谓的设计人员都没机会完善测试一下

armku 发表于 2012-12-1 10:48:51

我的一个软件,运行中经常退出(一般一两天一次),安装有服务器安全狗和金山杀毒套装,系统是2003,后来把别的软件卸载掉就没有问题了。

xiaobendan001 发表于 2012-12-1 10:55:02

和那个STC的下载软件有一拼

68336016 发表于 2012-12-1 11:37:20

悲剧,在自己2台电脑怎么虐待都正常

在客户那2台电脑就不行,准备出差

龙折翼 发表于 2012-12-1 14:24:16

尼玛,第一次听说瑞星杀毒软件居然还会在串口里面插入广告,笑死我了!

wye11083 发表于 2012-12-1 15:35:55

这种简单的线程没什么技术含量的。再说你也没必要10ms刷新一次,毕竟windows最快也得15ms才能响应一次。所以你完全可以每50ms刷一次,缓冲开大点,记得最大64字节。

BJKBJ90 发表于 2012-12-1 15:45:20

本帖最后由 BJKBJ90 于 2012-12-1 15:48 编辑

靠线上你套个磁环还退出你找我。前段时间出现这问题就是这么解决的。
别再软件找毛病了,上面的楼都是在瞎忽悠你。

68336016 发表于 2012-12-1 15:46:59

wye11083 发表于 2012-12-1 15:35这种简单的线程没什么技术含量的。再说你也没必要10ms刷新一次,毕竟windows最快也得15ms才能响应一次。所 ...

我是用cserialport类,它本身有线程在循环查询串口数据,收到一个字节就事件形式通知主线程。我就在那消息函数解析数据。同时开了个500ms的定时器来刷新界面控件。在我电脑是没问题了,在客户那2台一样xp系统的笔记本,没几分钟还是退出。

BJKBJ90 发表于 2012-12-1 15:50:26

买了一根破线,和软件没有半毛钱关系。

winfisher 发表于 2012-12-1 18:54:02

龙折翼 发表于 2012-12-1 14:24 static/image/common/back.gif
尼玛,第一次听说瑞星杀毒软件居然还会在串口里面插入广告,笑死我了!

我当时也觉得奇怪。。。
但却是有瑞星的网址。

winfisher 发表于 2012-12-1 18:54:35

68336016 发表于 2012-12-1 15:46 static/image/common/back.gif
我是用cserialport类,它本身有线程在循环查询串口数据,收到一个字节就事件形式通知主线程。我就在那消 ...

有没有做事件记录?看看是哪里出的异常,这样才能解决。

winfisher 发表于 2012-12-1 18:55:34

wye11083 发表于 2012-12-1 15:35 static/image/common/back.gif
这种简单的线程没什么技术含量的。再说你也没必要10ms刷新一次,毕竟windows最快也得15ms才能响应一次。所 ...

据悉,window的time事件最短时间间隔是55ms,在往下就不准了。
50ms刷一次,有必要没?

BJKBJ90 发表于 2012-12-1 19:39:06

2013前最有技术含量的笑话、、、{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}

wye11083 发表于 2012-12-1 20:56:29

winfisher 发表于 2012-12-1 18:55 static/image/common/back.gif
据悉,window的time事件最短时间间隔是55ms,在往下就不准了。
50ms刷一次,有必要没? ...

15ms,不是55ms,大哥你记错了吧。老子天天写程序,还没听说过55ms的。

winfisher 发表于 2012-12-1 21:26:59

我是从vckbase一个关于定时器研究的帖子里看到了,之前一个同事也说个55ms的事情。
你应该是对 的吧:
http://www.vckbase.com/index.php/wv/752.html,这有提到55ms。
对System.Windows.Forms.Timer的编程不能再简单了――它有一个非常简单和可直接编程的接口。Start和Stop方法实际上提供了一个设置使能属性的改变方法(其本身是对Win32®的SetTimer和KillTimer功能的一个包装)。我刚才提到的间隔属性,名字本身就说明了问题。即使技术上你可以设置间隔属性低到1毫秒,但你应该知道在.NET框架文档中指出这个属性大约精确到55毫秒(假定UI线程对于处理是可用的)。
附一篇看不大懂的:
http://www.vckbase.com/index.php/wv/1024

68336016 发表于 2012-12-1 23:21:56

BJKBJ90 发表于 2012-12-1 15:50 static/image/common/back.gif
买了一根破线,和软件没有半毛钱关系。

都是力特FT232

ele_eye 发表于 2012-12-2 01:41:39

不要接收1个字节就产生事件在接收一个数据包时 几乎是1ms不到一个事件,太快了 应该改成串口超时事件 在超时时间内没有数据到来,就向主线程发送事件
我用的是delphi delphi的spcomm 就是这样操作才合理,

BJKBJ90 发表于 2012-12-2 10:27:18

68336016 发表于 2012-12-1 23:21 static/image/common/back.gif
都是力特FT232

谁说力特的就不能退出????

ginonie 发表于 2012-12-2 11:21:23

用异常处理了吗?try catch.大大增加程序稳定性!

plumlee 发表于 2012-12-2 12:27:29

ele_eye 发表于 2012-12-2 01:41 static/image/common/back.gif
不要接收1个字节就产生事件在接收一个数据包时 几乎是1ms不到一个事件,太快了 应该改成串口超时事件 在 ...

这个代码用VB怎么写呀?



wye11083 发表于 2012-12-2 12:43:48

winfisher 发表于 2012-12-1 21:26 static/image/common/back.gif
我是从vckbase一个关于定时器研究的帖子里看到了,之前一个同事也说个55ms的事情。
你应该是对 的吧:
http ...

请问你了解windows定时器原理吗?我告诉你准确数字吧,windows启动时会设置一个计数器作为中断源,这个计数器中断时间就是15ms!所以,你Sleep(15)它延时就是15ms,但是你小于15ms,它的延时是0ms!这个时间是硬件决定的,不是函数决定的!记住一点,CPU有一堆计数器,所以用一个专门用作中断源并不是很麻烦的事情。
这些文章里给出的并不是真正的数值,只是经验值。但是在VC中,最小精度就是15ms。C#中我具体没用过,但是一般延时15ms时,输出不会是55ms,就是15ms。如果你的延时不是15ms,只能说你电脑有病。
这是延时测试代码:
C++
#include "iostream"
#include "windows.h"
using namespace std;

void main()
{
        LARGE_INTEGER freq,start,end;
        QueryPerformanceFrequency(&freq);
        QueryPerformanceCounter(&start);
        Sleep(15);
        QueryPerformanceCounter(&end);
        cout<<((double)(((double)end.QuadPart)-((double)start.QuadPart)))/((double)freq.QuadPart)<<endl;
}
我的电脑输出是0.0147181,或者0.015xxxx,总之就是一个中断的时间!
因此,你把刷屏时间延长一些,比如100ms(实践证明,你就算延时500ms,客户也不会觉得不爽!)。除非电脑非常牛B,否则很少有电脑能做到50ms刷新一次,尤其是C#,基于COM框架的CLR,别指望性能有多高,我的C++程序执行同样的算法,速度比C#快10倍以上。你应该还是没有用多线程。前台和后台全部分离。还有就是C#线程由于是在COM之上的,所以一旦崩溃,程序是立马挂掉。所以你再确定是不是有BUG。
再说一遍,没写过多少程序的,尤其是多线程程序的,没有资格在这里跟我做对。老子当年写程序写到看到代码就想吐。不要以为会写几行代码就有多么了不起。你写的代码越多,越发现自己是多么的无知!

winfisher 发表于 2012-12-2 12:49:10

本帖最后由 winfisher 于 2012-12-2 12:53 编辑

会写几行代码就nb了?
我也就会写几行烂代码,挣几文铜臭而已。比不得你这样的大牛。
张口老子,闭口老子,大家看看谁更牛气?

Talsinpo 发表于 2012-12-2 12:50:37

winfisher 发表于 2012-12-1 07:10 static/image/common/back.gif
有杀毒软件会影响串口数据接收。比如瑞星,能明显接收到瑞星在串口数据插入的瑞星广告。
你用portmon监听串 ...

靠,不会吧。这有什么意义呢,不会显示广告吧

winfisher 发表于 2012-12-2 12:51:59

反正有ruixing字样的一串字符。

ele_eye 发表于 2012-12-2 13:32:33

plumlee 发表于 2012-12-2 12:27 static/image/common/back.gif
这个代码用VB怎么写呀?

VB 我不会了 好多年不用 都交给老师了

68336016 发表于 2012-12-2 14:07:14

ele_eye 发表于 2012-12-2 01:41不要接收1个字节就产生事件 在接收一个数据包时 几乎是1ms不到一个事件,太快了 应该改成串口超时事件 在 ...

我2帧间隔10ms左右,每帧20个字节,波特率115200,也就是不到0.1ms就一个字节产生事件消息。接收到一帧20个数据后,组合成数据。在我电脑反复试验倒是没事,在客户电脑就是不行。

发现一个问题,如果在这个串口消息函数里面加个模式对话框,在某个情况弹出对话框暂停函数,然后关闭对话框,软件就会静悄悄自动退出了。
而软件界面上的一些编辑框(用1秒的定时器刷新),对应的是某些变量值,这些值跟串口消息函数没关系的(仅仅初始化某个值,没经过任何调用)。但是在软件自动退出之前,这些编辑框显示的数就变得非常大。

68336016 发表于 2012-12-2 14:08:06

ele_eye 发表于 2012-12-2 01:41不要接收1个字节就产生事件 在接收一个数据包时 几乎是1ms不到一个事件,太快了 应该改成串口超时事件 在 ...

我2帧间隔10ms左右,每帧20个字节,波特率115200,也就是不到0.1ms就一个字节产生事件消息。接收到一帧20个数据后,组合成数据。在我电脑反复试验倒是没事,在客户电脑就是不行。

发现一个问题,如果在这个串口消息函数里面加个模式对话框,在某个情况弹出对话框暂停函数,然后关闭对话框,软件就会静悄悄自动退出了。
而软件界面上的一些编辑框(用1秒的定时器刷新),对应的是某些变量值,这些值跟串口消息函数没关系的(仅仅初始化某个值,没经过任何调用)。但是在软件自动退出之前,这些编辑框显示的数就变得非常大。

wye11083 发表于 2012-12-2 14:12:31

68336016 发表于 2012-12-2 14:07 static/image/common/back.gif
我2帧间隔10ms左右,每帧20个字节,波特率115200,也就是不到0.1ms就一个字节产生事件消息。接收到一帧20 ...

怀疑你缓冲溢出了。你好好查查吧。

ele_eye 发表于 2012-12-2 14:18:03

呵呵 0.1ms每一个事件,太快了,只要电脑稍微有一点慢,或者主线程有一点稍微的阻塞,就会出现有的事件丢失,串口数据指针被覆盖,或者对同一个缓冲同时读写,或者串口数据混乱,所以就出现LS所说的现象:
1 弹出模式对话框,主线程就阻塞了,就会出现异常,
2 刷新编辑框用200ms刷新就可以了,确实没有影响,只能说明你的协议不够健壮,只要数据混乱了(有的被覆盖重写了),数据就解释错误,出现很大的数据值。

但是自动退出,我在delphi里面没有遇到过,delphi里面一般会弹出错误提示,或者提示 内存不可写之内的提示。就是这些问题带来的

68336016 发表于 2012-12-2 15:22:16

ele_eye 发表于 2012-12-2 14:18 static/image/common/back.gif
呵呵 0.1ms每一个事件,太快了,只要电脑稍微有一点慢,或者主线程有一点稍微的阻塞,就会出现有的事件丢失 ...

现在火车上笔记本没电也没法试了。我通讯上应该还比较可靠,每次都判断帧头和数据长度。用一堆错误数据夹在里面也能自动丢弃掉,程序继续运行。

这自动退出应该还是楼上说的缓冲区原因。关于缓冲区我都有些糊涂了,ft232接收缓冲区是184个字节,而设备管理器看到的ft232驱动又能设置到4096,搞不清这2个关系。我实际波特率115200,设备管理器上的是9600,也不清楚之间的联系。而我软件的串口缓冲区跟这些又有什么联系。

68336016 发表于 2012-12-2 18:44:24

在我自己电脑测试:理论上两帧间隔10ms左右,我在串口消息函数中,每200帧插sleep 2秒这样还是不会崩溃。不过几十帧之间插那么大延时就不行,软件就自动退出了,跟客户电脑故障一样,编辑框内容混乱了。

chinabn 发表于 2012-12-3 10:23:15

高速、底层的场合不要基于FrameWork框架,Jave之类的 效率是很低的

尽量用BCB6,VC6这些最精简的做,效率出奇的高,不会有任何的问题。

w1000 发表于 2012-12-3 10:47:25

plumlee 发表于 2012-12-2 12:27 static/image/common/back.gif
这个代码用VB怎么写呀?

VB 不是可以设置 接收多少字符然后产生事件。比较早之前用过。忘得差不多了。

68336016 发表于 2012-12-3 10:54:28

本帖最后由 68336016 于 2012-12-3 10:57 编辑

chinabn 发表于 2012-12-3 10:23 高速、底层的场合不要基于FrameWork框架,Jave之类的 效率是很低的 尽量用BCB6,VC6这些最精简的做,效率 ... 我一秒钟100次数据,每次20字节,一秒钟也就2000字节,帧间隔理论是10ms。数据很少占不了多少缓存。 我把每帧的接收时间写到文件中,通常是间隔是 0ms,16ms,0ms,16ms,0的估计是us间隔看不出来。总体就是有时写快有时写慢,平均后跟理论值差不多。如果我在某些帧后sleep(1000)1秒,延迟的那上百帧还是能在1ms内接收处理完毕。 而且我在vs2005堆栈设置里加到10MByte,比默认1MByte大了10倍。还是会崩溃,不过在win7环境能提示stackhash。

farmerzhangdl 发表于 2012-12-3 11:20:23

本帖最后由 farmerzhangdl 于 2012-12-3 11:21 编辑

我认为可能有两个原因,一、缓冲区溢出,这个经常会毫无征兆的退出程序;二、你的刷新时间太快,这样windows有些控件处理来不及就退了出去,从你把默认的栈加到10M仍然出现这个问题来看,这个可能性比较大。
PS:上面有人说windows定时器只能15ms,还煞有介事的写了个15ms定时的来证明,我特意去写了个程序测试。结果即便是你写个sleep(1),两次调用QueryPerformanceCounter的值也是不一样的,虽然我知道sleep(1)肯定是定时不准确,但是这样写例子会误导人的,不是管自己叫老子就能证明自己厉害的。多线程很厉害么?不好意思负载平衡的UltraMonkey有一部分就是我写的。windows定时器不可能15ms的,你可以用timeSetEvent\CreateTimerQueueTimer\QueryPerformanceCounter都可以得到1ms的定时精度。不过我有个经验是你不能在一个程序里定时好几个ms级定时器,这样都会出现延时不正确,不过这个只是个人经验,存在编码错误的可能。

编辑原因:写错了个字,拼音输入法害人。

68336016 发表于 2012-12-3 12:49:43

farmerzhangdl 发表于 2012-12-3 11:20我认为可能有两个原因,一、缓冲区溢出,这个经常会毫无征兆的退出程序;二、你的刷新时间太快,这样window ...

界面刷新我已经用定时器1s刷一次。
cserialport类是收到一个字符就用SendMessage往主线程发送一个串口消息。现在问题就是串口消息函数如果耗时太久,而且阻塞太频繁,程序就会挂掉。我试验的结果是:每几十帧阻塞一秒肯定挂,几百帧阻塞一秒没事。如果是这个原因,我想不通在客户新装笔记本情况下,有什么可能导致软件频繁被阻塞那么久。

68336016 发表于 2012-12-3 12:51:45

farmerzhangdl 发表于 2012-12-3 11:20我认为可能有两个原因,一、缓冲区溢出,这个经常会毫无征兆的退出程序;二、你的刷新时间太快,这样window ...

界面刷新我已经用定时器1s刷一次。
cserialport类是收到一个字符就用SendMessage往主线程发送一个串口消息。现在问题就是串口消息函数如果耗时太久,而且阻塞太频繁,程序就会挂掉。我试验的结果是:每几十帧阻塞一秒肯定挂,几百帧阻塞一秒没事。如果是这个原因,我想不通在客户新装笔记本情况下,有什么可能导致软件频繁被阻塞那么久。

farmerzhangdl 发表于 2012-12-3 13:13:13

68336016 发表于 2012-12-3 12:51 static/image/common/back.gif
界面刷新我已经用定时器1s刷一次。
cserialport类是收到一个字符就用SendMessage往主线程发送一个串口消 ...

一般这种实时性比较强的处理你不应该使用消息的,windows的消息阻塞起来会产生比较严重的问题,尤其是在进行跨进程的消息发送的时候。正确的处理是你接收到的串口数据丢到专门的数据缓冲区,使用另外一个线程来进行处理,这样兼顾了数据的完整性和处理速度的问题。典型的处理可以参看生产者-消费者模式。

farmerzhangdl 发表于 2012-12-3 13:15:14

本帖最后由 farmerzhangdl 于 2012-12-3 13:17 编辑

68336016 发表于 2012-12-3 12:51 static/image/common/back.gif
界面刷新我已经用定时器1s刷一次。
cserialport类是收到一个字符就用SendMessage往主线程发送一个串口消 ...

另外,看你的消息是使用sendmessage,这个在处理不及时的时候的确会产生永久阻塞的问题,建议换一种处理方式。上面我的回复有建议。

编辑原因:没有看明白问题已经说了是sendmessage。

kent 发表于 2012-12-4 00:02:17

68336016
--------------------------------------------------------
从你描述的现象来判断,故障是硬件引起的。
硬件方面最主要的因素有:串口线抗干扰性能强弱、主机与从机之间分频精度两个方面。特别是后者,分频存在误差是绝对的。通过降低波特率也不会解决此类问题。解决此类问题的方法,一般是采用双工方式,使用软件协议解决。常用的有ModBus通讯协议。当然,也可自定义。该协议网上资料非常多,这里不多说了。
目前,你可发现——从机正常发送数据。主机程序中断了。你可采取如下方案:主机与从机建立通讯前,设置握手信号。当在设定的时间之后,没有返回数据,重新发送握手信号,如“0xAA”。主机接收到握手信号后,重新初始化串口相关变量,并且返回应答信号,如“0x55"等。从机在收到应答后,从断点处继续发送数据,通讯即可恢复。

68336016 发表于 2012-12-4 01:18:00

kent 发表于 2012-12-4 00:02 static/image/common/back.gif
68336016
--------------------------------------------------------
从你描述的现象来判断,故障是硬件 ...

不是干扰啊
我现在到达客户所在地,现在宾馆4台笔记本测试,相同硬件

我自己带了2个笔记本,其中一台特地重装XP系统,没安任何开发的软件,就装我的串口软件,依然可以长时间工作,这说明并不是系统缺少某些文件造成的。


而客户的2台笔记本也是新买不久的,系统是电脑城装的(不是同时买,所以系统不一定完全一样),在这2台上面很快就挂了,跟我电脑区别就是这2台式I3 I5,比我的强悍一些{:lol:}


愁死了,急急忙忙就算把串口处理代码重新写也未必有用,原因还不明

68336016 发表于 2012-12-4 10:25:08

本帖最后由 68336016 于 2012-12-4 10:28 编辑

farmerzhangdl 发表于 2012-12-4 10:07 http://www.amobbs.com/static/image/common/back.gif
试过我上面说的生产者-消费者模型的方法了么?老是等大家猜测不是办法,我觉得你用个把个小时写一个试一 ...

不好意思啊,我不太熟悉写PC上的软件,所以急急忙忙我也没办法重新写一个串口出来。

期间一直在火车上,昨天夜里才来到客户这里

其实我用的就CSerialPort那个类而已,我将程序简化到最低,只不过在主线程里面的消息函数收一个个字符,不做任何其他操作。

在我笔记本,重装一个新系统,我夜里挂了7个小时,收到280W帧数据,一个都没丢失。

客户笔记本,重装一个一样的新系统,甚至1,2分钟就挂掉了。



twitter 发表于 2012-12-4 10:26:56

wye11083 发表于 2012-12-2 12:43 static/image/common/back.gif
请问你了解windows定时器原理吗?我告诉你准确数字吧,windows启动时会设置一个计数器作为中断源,这个计 ...

vc下能做到的不意味着其它语言能轻松做到,否则一般也不会把vc实现做为性能改进的一种手段。因为其它语言在实现它们自己定义的Timer时,很可能是使用了实时性很差的方式,比如vb6的Timer最短就只能做到50ms左右(取决于CPU性能,差的连80以下都跑不到),而且间隔还很不稳定。

farmerzhangdl 发表于 2012-12-4 10:28:20

68336016 发表于 2012-12-4 10:25 static/image/common/back.gif
不好意思啊,我不太熟悉写PC上的软件,所以急急忙忙我也没办法重新写一个串口出来。

其实我用的就CSeria ...

但是你这样说也没有用啊,在不同机器上的表现不同,已经很明白的说明了你的软件是有缺陷的,你再在论坛上喊几天,结果也是一样的。

farmerzhangdl 发表于 2012-12-4 10:30:08

twitter 发表于 2012-12-4 10:26 static/image/common/back.gif
vc下能做到的不意味着其它语言能轻松做到,否则一般也不会把vc实现做为性能改进的一种手段。因为其它语言 ...

这个可以使用win32api来解决,就像我上面说的,至少可以使用timersetevent等三种以上的方法来解决这个问题。

twitter 发表于 2012-12-4 10:46:36

本帖最后由 twitter 于 2012-12-4 10:48 编辑

farmerzhangdl 发表于 2012-12-4 10:30 static/image/common/back.gif
这个可以使用win32api来解决,就像我上面说的,至少可以使用timersetevent等三种以上的方法来解决这个问 ...

关于.net那个串口类的实时性能问题,我记得以前讨论过的,当时我找到篇老外写的文章(楼主可以参考下http://www.hanselman.com/blog/PerformanceOfSystemIOPortsVersusUnmanagedSerialPortCode.aspx),那个老外比较过后得到结论,就是说要自己用API去实现读写串口的,自带那个类是靠不住的,托管代码访问硬件设备的效率对于楼主的应用要求来说实在是不怎么够的。
自己实现的好处是,可以把它扔到独立线程里去干这事,这样被UI等问题卡住一段时间的可能就比较低了。

cocom 发表于 2012-12-4 10:49:59

wye11083 发表于 2012-12-1 20:56 static/image/common/back.gif
15ms,不是55ms,大哥你记错了吧。老子天天写程序,还没听说过55ms的。

其实受最早DOS的影响,PC的最基本时基是每秒18.2次中断,即每54.945mS一次时基中断,估计微软的WINDOWS至今支持此基本时基,有些编程软件你设定的1m间隔可能就要每隔54.945mS处理一次,要小于此间隔要专门的功能调用实现,不同的编程软件有不同的方法。
这种地方比你老,比你牛的人多了去了,但没有牛人会说老子的。

zhouzmt 发表于 2012-12-4 11:10:15

我也觉得论坛是讨论技术的地方,不是骂人的地方

68336016 发表于 2012-12-4 12:04:25

farmerzhangdl 发表于 2012-12-4 10:28 static/image/common/back.gif
但是你这样说也没有用啊,在不同机器上的表现不同,已经很明白的说明了你的软件是有缺陷的,你再在论坛上 ...

我正写个简单的日志函数,插入到关键地方,看看能不能捕捉到最后异常信息

ddqq 发表于 2012-12-4 12:19:31

本帖最后由 ddqq 于 2012-12-4 13:19 编辑

这里面有高人出没

楼主不要固执认为自己的电脑上运行正常的程序,在别的机器上运行就应该正常,或者说就认为没有问题

farmerzhangdl 发表于 2012-12-4 13:06:06

68336016 发表于 2012-12-4 12:04 static/image/common/back.gif
我正写个简单的日志函数,插入到关键地方,看看能不能捕捉到最后异常信息 ...

我认为你是抓不到的。。。

68336016 发表于 2012-12-4 13:58:39

本帖最后由 68336016 于 2012-12-4 14:11 编辑

farmerzhangdl 发表于 2012-12-4 13:06 http://www.amobbs.com/static/image/common/back.gif
我认为你是抓不到的。。。

感谢热心的各位坛友

我是用写文本的函数插入到各个地方,观察到程序崩溃时候,代码中的m_rxCounter变量变得很大,而代码里它只可能到达17

已经找到可能的原因了,都是自己粗心造成的,看来CSerialPort类在115200kbs情况下,只要不是一直连续大量接收数据,还是能应付的。不过为了更可靠,自己有空还是重写下软件。
之前软件测试过能用的,后来自己又修改了下,结果看错大括号位置,将几行关键代码放到括号内了,导致串口数据错误处理失效,因此一旦被干扰,就没法继续运行了,导致堆栈溢出
LONG CDeflectionDlg::OnDataArrive(WPARAM ch, LPARAM port) // 串口消息函数,子线程CSerialPort类每收到一个字符就SendMessage到主线程
{
    char rxChar = (char)ch;
    m_rxBuffer = rxChar; //m_rxBuffer是接收用的数组,开辟了100字节,m_rxCounter表示数组数据的长度
   
   if (m_rxCounter > 1)//已经收到2个字节,判断帧头是否正确
    {
      if ((m_rxBuffer != 0xff) && (m_rxBuffer != 0x55))//如果同步头错误,重新接收一帧
      {
            m_rxCounter = 0;
      }
    }

   //计算校验码忽略帧头0xff,0x55
    if (m_rxCounter > 2)
    {
      m_checkSum += rxChar;
    }

   if (m_rxCounter>17)
   {
      处理分析的代码      
<FONT color=red>m_rxBuffer = 0;
       memset(m_rxBuffer, 0x00, sizeof(m_rxBuffer)); //这2行代码本应该放到下面大括号外的,不管收到18个字节数据是否正确,都应该清空数组和索引值的</FONT>
   }
}

farmerzhangdl 发表于 2012-12-4 14:02:31

68336016 发表于 2012-12-4 13:58 static/image/common/back.gif
感谢热心的各位坛友

我是用写文本的函数插入到各个地方,观察到程序崩溃时候,代码中的m_rxCounter变量 ...

除了说晕,还能说什么。。。
写代码的第一要素就是当你敲下{的时候就要顺手敲下}

68336016 发表于 2012-12-4 14:10:23

farmerzhangdl 发表于 2012-12-4 14:02 static/image/common/back.gif
除了说晕,还能说什么。。。
写代码的第一要素就是当你敲下{的时候就要顺手敲下} ...

我也不是专门写软件的,平时大部分工作都是技工性质的,重复的体力劳动
没事需要的时候能写下单片机和简单VC程序,但是没有养成好的习惯。
工作中往往一两年都不会接触代码的

68336016 发表于 2012-12-5 07:54:16

我的2个电脑分别是2000多的杂牌gateway和tkinkpad t400,都没产生一个误码。

客户总共3台联想e系列的thinkpad,全部误码严重,看来更硬件质量也有很大关系

BJKBJ90 发表于 2012-12-9 18:39:48

靠临时改变主意了?
悬赏改了?
这是什么贴,逗你玩贴子??

68336016 发表于 2012-12-11 12:02:55

BJKBJ90 发表于 2012-12-9 18:39 static/image/common/back.gif
靠临时改变主意了?
悬赏改了?
这是什么贴,逗你玩贴子??

看清楚了『已解决』没有?500莫元已经给其中一个坛友了,悬赏只能给一个人的,不能给多人的。

68336016 发表于 2012-12-11 12:15:03

本帖最后由 68336016 于 2012-12-11 12:23 编辑

kent 发表于 2012-12-4 00:02 static/image/common/back.gif
68336016
--------------------------------------------------------
从你描述的现象来判断,故障是硬件 ...

软件修改了下,在设备实物上测试了,客户电脑帧错误率万分之一左右,程序正常工作,丢几个数据帧影响也不大。(都是一下子连续错误几帧,帧内部丢失字节而不是被干扰修改,波特率降低一半客户电脑该丢还是会丢,我电脑不会)

我用的是同一根USB转串口线和下位机电路板,这时通讯的时钟等跟PC应该没什么关系了

68336016 发表于 2012-12-11 21:28:13

BJKBJ90 发表于 2012-12-11 20:41花500元游戏下论坛,最终还是自己解决

那你认为我需要把代码,实物设备搬到论坛来,这样才算求教问题的办法?
难道别人给的思路和建议就不行?

kent 发表于 2013-2-26 09:00:14

"分频存在误差是绝对的。通过降低波特率也不会解决此类问题。"类似的意思,我在STC系列DATASHEET与STM32系列DATASHEET都看到过.我认为,你现在碰到的问题就属于这一类.
你说:某几个品牌的笔记本都好的,换THINKPAD品牌就不行了.------还是说明跟硬件有关.对于设计产品的工程师来说,你的软件,不能光对某台机子适用.应该在不同机子,不同环境下都能用.请你设计软件时考虑到这个问题,增加几条异常处置代码即可解决此类问题.

kent 发表于 2013-2-26 09:21:43

发表于 2012-12-11 12:15:03 |只看该作者 本帖最后由 68336016 于 2012-12-11 12:23 编辑
软件修改了下,在设备实物上测试了,客户电脑帧错误率万分之一左右,程序正常工作,丢几个数据帧影响也不大。(都是一下子连续错误几帧,帧内部丢失字节而不是被干扰修改,波特率降低一半客户电脑该丢还是会丢,我电脑不会)

我用的是同一根USB转串口线和下位机电路板,这时通讯的时钟等跟PC应该没什么关系了
-----------------------------------------------------------------------------------------------------------------------
不好意思,工作忙,很少上网了.现在才看到你的回复.

你讲的"客户电脑帧错误率万分之一左右,程序正常工作,丢几个数据帧影响也不大。(都是一下子连续错误几帧,帧内部丢失字节而不是被干扰修改,波特率降低一半客户电脑该丢还是会丢,我电脑不会)"
-----------我完全赞同.问题是,不是丢几帧,而是出现连续的乱码.对于图像数据,你不知道哪些数据是对的,哪些数据是错的.
你要不硬件解决,增加其它几条线,如全握手,或循环回送握手连接方式.(TD,RD,RTS,CTS,DSR,CD,DTR,RI等)
要不用软件解决,如在接收中断函数里,使用协议(如MODBUS),检查出非法数据.在出现异常后,立即处理掉当前进程,重新接收.
页: [1]
查看完整版本: 江湖救急:一个串口接收软件,会无故自动退出,毫无提示