串口操作与线程的应用(涘,没有分了。)(0分)

正如你所讲的。我也是用的spcomm,我的问题是以第二步发送消息时如何得知第一步的发送顺利完成(以收到单片机返还消息为准)
我的方法是用了全局变更,但是它不起作用。
 
既然这样,那就跟线程无关了,你剩下的事情就是你协议的完善与否了,我想撞墙式
的配合是必须的。也就是说,程序发送一串字符,然后在规定的时间内等待回应,
如果规定时间内没有得到回应,那么你再发送一次,直到你重试的次数为止,
弹片机在接受到你发送的东西必须回应,以避免让程序在等待。但是仔细一想,这
逻辑是错误的,因为大家都彼此为对方的消息做出回应的时候将形成无限的循环。
所以必须设置一个特定的字节串作为终止特征码。也就是我上面说的确认桢。
任何一方在接受到对方的字节流后校验,如果正确发确认桢,如果错误,发否认桢
任何一方接受到确认桢后,将不再发送原有内容,程序往下执行,接到否认桢则
重发上次的内容,直到对方接受正确,或因重试次数太多而宣告通讯失败。
其实我上面说的就是基于我先前的一个与弹片机通讯程序来说的 。
发出字节串
开始计时并开始计算重试次数
如果重试次数太多,。。。。
实际的程序要根据你所徐要的协议来完成,必须两方面很好的配合。

 
如果嫌这里慢,而我又刚好在线的话 可以联系msn
lvxqjp@hotmail.com
 
大哥,你讲的协议我都知道。
我的关键问题是:
我的程序是如此做的:
全局变更SRS用来标识发送是否成功
procedure SendData(.....);发送子程序,肯定没有问题。
begin
end
procedure Spcomm ReceiveData()//spcomm的接收程序
begin
//发送完成后给全局变更SRS赋值:11
SRS:=11;
end;
procedure form1.button1click()
begin
SRS=10;
senddata(...);//发送第一批数据
if SRS=11 then

SendData(....);发送第二次数据
end;
我的程序在做完第一次发送后,按想像,SRS应该在接受数据过程中改为11,
可实际并不是如此,而是SRS依然是10。
如何解决?
 
还没有结束?
来自:dcsdcs, 时间:2002-4-16 8:35:00, ID:1046218 | 编辑
程序设计有两种问题,技术和非技术的,技术的可以绕过去,非技术的实际上在很大程度上决定软件的成功与失败!!!!!!!!!!

 
dcsdcs:我的问题应该可以用技术解决的。请出招吧。
 
不是跟你说了吗,不要想法子在你的button事件里测试,因为这个值的更改总是
在接收到弹片机的内容以后才能更改,所以,除了第一次发送的内容以外,任何
别的发送是依据于接收内容的,所以,这些发送必须在接收事件里处理。
procedure SendData(.....);发送子程序,肯定没有问题。
begin
end
procedure Spcomm ReceiveData()//spcomm的接收程序
begin
//判断接收到的内容,如果符合需要把SRS更改为11
//否则要求重发或者退出
//SRS=11??
//发送第二 个内容。
end;

或者这样
procedure form1.button1click()
begin
SRS=10;
senddata(...);//发送第一批数据
end;
//这里再加一个button
procedure form1.button2click()
begin
if SRS=11 then

SendData(....);发送第二次数据
end;

 
procedure Spcomm ReceiveData()//spcomm的接收程序
begin
//发送完成后给全局变更SRS赋值:11
SRS:=11;
end;
procedure form1.button1click()
begin
SRS=10;
senddata(...);//发送第一批数据
Sleep(5000);
//可以吧!!!!!!!!!!!!,跟你说这样不好,你也不听,看,把Sleep都用上,话还没有说完,你怎么又钻进去了!!
if SRS=11 then

SendData(....);发送第二次数据
end;
 
即使使用了SLEEP(5000)也不见得能解决问题,弊端有2:
1--5000的事件不一定够,也可能太长了,这样做根本就不是即时通讯
2--即使5000的时间是可用的,我觉得它也不能获得最新的SRS值,也就是说无法
刷新这个值,即使它确实变成11了,也不行。我不知道我这样说对不对,毕竟有3年没
用delphi了,不知道新版本是否有新特性,听说用6。0了
如果非要在button中,下面的方法可能是可取的
procedure form1.button1click()
var
i:Integer;
begin
srs=10;
//senddata(data1)

while(true)do
begin
if srs=11 then

break;
application.ProcessMessage;
sleep(50);
inc(i);
if i>=100 then
break;
end;
if i<100 then
senddata(data2);


 
同意lvxq,最好在
最好还是不要想法子在button事件里测试
 
各位兄弟对我真是够关心的了。不管如何,先行谢过了。
 
我还是不可以呀。大侠继续出招吧。
大家对我的问的问题有没有清楚???????
我想我的问题可能是线程同步的问题。
 
新招实在是没有了
只能是这样总结了:
1。不要尝试在button的事件里监测一个动态变化的变量
2。如果你采用了spcomm,那你实在没必要自己采用线程了。
3。在发送一个新的消息之前,如果其结果是建立在接收到的结果的基础之上的,你可以在
Spcomm的接收事件中处理,也就是说,接收到你指定要的信息后,马上进行下一步发送
在此基础上,完备你的通讯协议,最好区别接收的第一个问题和后面别的问题的回应
信号,比如,你发送第一个消息后,需要等到 ‘Ans01’后可以发送第二个消息,在接收
到'Ans02'后表示第二个消息对方处理完毕,这样做你可能比较容易在spcomm得接收事件
中分别处理。而且,这样做,你可能可以不要你上面说的那个变量。
4。如果你非要自己处理多线程,千万要记得同步,用上面说的WaitForSingleObject/
WaitForMutileObject等也可以,当然也可以使用sys....什么函数,我记不起了
同步的标准是这样的; 在线程中使用VCL控件也是不安全的,因此,如非万不得以,
也不要使用类是下面的话:
Label1.Caption:='1111';
5.我的话完了/
 
我知道你在建议我在spcom的接收函数中处理下一个操作的开始。
但在实际中,我的操作多达上百个。
我的想法是当用户要操作时(通过按钮响应),批量进行N个端口操作
(但这些操作又分别是基于前一个操作正确响应并返还相应标志符后进行)。
所以可能lvxq没有理解我的意图。
 
什么操作有100个??共有n个端口,N=??
一个按钮负责几个??
你全部理清了么?怎么就没法在接受事件里处理?
前面已经说的很清楚了,你在同一button的事件里想检测变量的变化,本来就是很
ogasiyi的。而如果你采用多线程,线程的开销肯定是不划算的。算了,不说了,没劲

 
谢谢你了lvxq.我真恨不得把你拉到我的代码前来。
急死我了。
意思是,用户可以点了按钮后机器自动批量进行100个读操作。
 
尽管还是不完全明了你的意思,但我的理解是这样的:
1。你要做的是在按钮按下后允许spcomm的接收,尽管我不知道你需要监视多少端口,但是
这并没有本质的区别,你设置一个全局的布尔型变量,在button按下后把它变成true.
而在接收事件中,先判断该变量是否为true,否则直接exit跳出处理。
2。既然你要进行的是读操作,你可以在接收事件中判断是否合法,根据返回标记决定是否
发送下一组信息。
3。spcomm的发送和接收本来就是基于线程实现的,你没必要自己进行多线程的处理。
4。尽管可能存在100个读操作需要同时进行的可能,但是spcomm和windows会为你处理,尽管
处理的结果可能是造成部分数据丢失,但是只要你协议完备,是可以弥补的。
 
lvxq对我如此耐心,不管如何。我要谢谢你。兄弟,你在那里混。我在南京有空来玩。
 
我只是要对1个串口操作。
但是我的操作有很多步。(我无法对单片机做出改变)
比如第一步我从串口读出用户号。第二步要读出小区号,第三步读出年龄。
第二步要在确保第一步成功读出方可进行。
第三步要在确保第二步成功读出方可进行。
......
我无法在后一步知道前一步的成功与否(我只能在接收完毕后,置一个变量来标识),
也就是在后一步的操作时,我要先检查一下这个变量。
(我只能这么做)
但我无法成功检测到它的变更。
这样你知道我的意思 了吗?
 
我在日本东京
我觉得这怎么跟我过去做vod点播这么像啊。我当初做一个同轴电缆双向传输就是这样的。
你在南京哪里啊??
我当初的做法也差不多,也是要先收用户号再读取别的信息。我是放在接收事件里处理的
因为事情过去好多年了,详细情况也记不起来了,大致是这样。
先读取用户号,判断是否合法用户,如果是,发送命令要求单片机发送小区号。。。。
如果这样做的话,需要一个完备的通讯协议,比如
ff f1 .....代表取用户,
ff f2 .....代表取小区号。。。。
但是你现在说单片机没法改,那样的话就比较棘手了。不过还是给你个提示把
仍旧在接收事件中处理,当你接收到一个合法的用户号后,新创建一个线程(事实上)
由于你只有一个端口,如果你同时只处理一个用户或者同时处理的用户的最大数目是
固定的话,你可以,。。。
对不起,现在有点事,以后再写
 
顶部