当前位置: 首页 > news >正文

Lazarus结合Lazserial多线程方式的串口采集实操心得

Lazarus和delphi非常类似,只是它的跨平台功能更加诱人,号称是一套源码到处可编译。串口通讯的好处是硬件简单成熟,单片机和各种微处理装置几乎都有这接口,把它转换成RS485配上modbus协议也很常用。

  • 为什么要用多线程

串口通讯速率有限,发送方发出指令后接收方收到后进行一定处理,将数据比特位按比特率回送给发送端。处理串口的时间如果过长,尤其是串口线中断了,那主线程就因停滞而操作变得十分卡顿。除了串口采集外,tcp或udp通讯也适宜放在其它线程中,因为它握手有时耗时太长,而这些时间均由不得软件控制。

  • 在哪里定义线程类

在窗体form类下方接着定义一个线程类即可

type
TMyThreadCOM = class(TThread)
private
procedure ShowTextCOM;
protected
procedure Execute; override;
end;

其中 procedure Execute; override; 是要重写一个我们需要的过程,也就是主线程外的线程要做的任务。procedure ShowTextCOM; 是个私有过程,供Execute过程调用,主要是刷新窗体上的数据或其它显示,由外线程交给主线程协同进行刷新,避免主线程和外线程同时操作界面。如果一个私有过程不够用,那就多加几个私有过程。

  • 定义创建线程类时用的handle变量

var
Form1: TForm1;
MyThreadCOM: TMyThreadCOM;

上面的Form1:TForm1;是我们常见的窗体变量,一般只要新建一个窗体类的project就会有这一行,下面的那行是我加入的变量。

  • Execute调用的ShowTextCOM过程

就像写普通过程一样写就行,放哪不重要。

procedure TMyThreadCOM.ShowTextCOM;
begin
Form1.Caption := 'Side thread to show';
end;    

  • 写Execute过程,在这里我们向串口发送指令

procedure TMyThreadCOM.Execute;

Var
btSend: array[0..7] of Byte;
begin
btSend[0]:= $01;
btSend[1]:= $03;
btSend[2]:= $00;
btSend[3]:= $F1;
btSend[4]:= $00;
btSend[5]:= $01;
btSend[6]:= $D5;
btSend[7]:= $F9;    

       Form1.LazSerial1.Close;
Form1.LazSerial1.Open;

我们准备好指令,其中btSend的0到5真实指令,6和7是modbus CRC16校验值。关闭串口,再打开串口,类似强制Fresh一次,只是在实践中体会这样做更稳定,没有更多想法。接着往下写...

Form1.LazSerial1.WriteBuffer(btSend, 8);

这个就是我们要发送的完整指令串,指令串发送是按比特位按比特率发送的,接收方收到后会判断处理并返回结果值,这一过程是需要时间的,所以要等待一会,等到LazSerial1.DataAvailable是真的时候。如果长时间等不来呢,那就不等了,200毫秒后自动结束。

          for i:= 0 to 20 do
begin
if Form1.LazSerial1.DataAvailable = True then
break else Sleep(10);
end;

通常情况下,串口接收的数据会暂存后一并复制给用户接口,有数就应该是完整的,但实际上并不是这样,而是有了数据就DataAvailable了,此时读数据的话可能就不是完整的数据,所以,还要等一等。等多长时间呢?就是传送比特位需要的时间。比如有100个回送二进制数据,N,8,1方式按10位计算,那就是100x10=1000个比特位,9600比特率那是1秒传送9600个比特位,1000个比特位就需要 (1000/9600)x 1000 = 105 毫秒,所以,可以等上它 150 毫秒。

Sleep(150);

然后读取数据

COMreturnHEXBIN := Form1.LazSerial1.ReadData;

至此,我们就得到了一串进制的数据串。实际采集中,这个二进制串要转换成十六进制数据串,然后进行CRC16校验。

COMreturnHEXCHA := AnsiStr2HexStr(COMreturnHEXBIN);

Synchronize(@ShowTextCOM);

将COMreturnHEXCHA 从左侧截取其长度值减4后的子串,交给CRC16过程校验得到校验码,将这个校验码与串口返送回来的十六进制数据串截取前的右4位校验值进行对比,如果相同就认为是传输无误,如果不同就认为是传送错误。Synchronize(@ShowTextCOM); 这句话是让主线程协调执行私有ShowTextCOM过程,在窗体上显示一些东西(在Delphi中要去掉那个@)。过程就写到这里,需要与实际情况相结合。

  • 创建线程执行Execute

      MyThreadCOM := TMyThreadCOM.Create(True); // 创建线程后,暂停suspend
MyThreadCOM.FreeOnTerminate := True;             // 线程结束后自动释放线程资源
MyThreadCOM.Start;                                              // 起动线程

这几句话放在一个Timer时钟过程中,比如每500ms执行一次。那Execute过程就会在另外的线中执行,执行完自动释放,下一个500ms到了再次创建,周而复始。如此,线程运行时不影响主程序运行,界面操作丝滑顺畅。

  • 对LazSerial1.ReadData的附加说明

Pascal字符串与普通文本串不同,它在单独的地方记录数据串长度,因此,它的字符串可包含ASCII任意字符,因此,LazSerial1.WriteBuffer也可以用二进制数据的ASCII字符串方式接在一起通过类似LazSerial1.WriteData(Chr(01)+Chr(03)+Chr(00)+Chr(241)+......);的方法替换。发送如此,接收亦如是。ASCII字符串变成ASCII值也不复杂,串本身就是数据,取其某位将其赋给byte变量就是ascii值了。

http://www.dtcms.com/a/416044.html

相关文章:

  • nano工具
  • 专门做西装网站wordpress alipay
  • 网络公司企业网站源码aso优化违法吗
  • 中国建设法律法规网官方网站手机可以搭建网站吗
  • 怎么用网站做文案wordpress网站有支付功能吗
  • 手工做皮具国外的网站工信部网站报备
  • 上海高端品牌网站建设专家郑州东区做网站电话
  • 手表网站起名网站常用插件
  • 网站建设推广接单语wordpress 3.5 漏洞
  • 保定模板做网站手机在线做ppt的网站有哪些问题
  • win8扁平化网站牙科医院网站源码
  • 徐州建设局网新网站永康电子商务网站建设公司
  • 加盟网站建设公司电子商务网站帮助中心该怎么更好地设计
  • OpenDDS运行配置可编程化
  • 河南郑州网站制作wordpress博客页面显示文章在哪
  • 献县做网站的深圳市罗湖区住房和建设局官网
  • 郑州做网站的公司有哪些net域名大网站
  • 三相变流器矢量控制及参数设计系列(1):引言
  • 石家庄设计网站公司WordPress文章分栏置顶
  • 网站建设叁金手指花总6大学生做家教网站
  • 一流的盐城网站建设jsp网站建设项目实战总结
  • 波动率建模(二)GARCH模型及Python实现
  • AI 文案生成 “同质化” 严重?多模态提示工程与行业语料优化方案
  • 网站什么引导页h5开发软件
  • 直播app制作开发网站推广和网站优化
  • 信息安全仿真环境十二(1)
  • 网站方案建设书怎么写大诚当道设计公司
  • Qt Model/View/Delegate 架构深度解析
  • 西安高端网站建设建设网站需要提前准备的条件
  • 企业网站设计开发网站要怎么做的