知识
Delphi开发安卓串口通讯疑问解答
在Delphi中开发安卓串口通讯应用程序是一个涉及硬件通信的过程。下面是一篇关于如何使用Delphi进行安卓串口通讯的简单指南:1. 安装安卓开发环境,包括安卓 SDK和Delphi IDE。
2. 连接串口设备到安卓设备。
3. 在Delphi中配置串口通信设置,包括波特率、数据位、停止位和奇偶校验等。
4. 编写代码以打开串口、发送数据和接收数据。
5. 处理串口通信错误和不同寻常。
6. 测试应用程序以确保串口通信正常工作。总的来说,使用Delphi开发安卓串口通讯应用程序需要了解安卓开发环境和串口通信的基本知识。通过正确配置和编写代码,您可以轻松地与串口设备进行通信,实现数据传输和控制。
在现代技术中,串口通讯是非常常用的一种通讯方法。Delphi这个强大的集成开发环境可以用来开发安卓应用程序,并且支持串口通讯。这样的话如何在Delphi中实现安卓串口通讯呢?下面我们来详细介绍一下。1. 准备工作首先,要在Delphi中安装安卓开发环境,包括了安卓 SDK和Java JDK,为安装方案提供基础。然后,在Delphi中新建一个安卓项目,并添加一个TTimer组件(用作定时器)。接着,从安卓 App Center获取安卓串口调试助手 应用程序(或者从其他渠道下载)。安卓串口调试助手在安卓端既可以测试串口通讯,也可以充当数据的 发送者和接受者。在这里,它将作为测试工具。2. 实现串口通讯在Delphi中实现串口通讯需要利用安卓系统提供的串口 API。串口 API的关键是安卓的串口管理器,该管理器主要包含下面的几个步骤1) 获取串口设备2) 设置串口参数3) 打开串口4) 发送和接受数据下面,我们将详细讲解如何一步一步实现这个功能。2.1 获取串口设备获取串口设备最容易的方法是使用安卓系统的File I/O API。通过遍历/dev/下的文件来获取串口设备。串口设备的设备文件通常命名为/dev/ttyS
0. /dev/ttyS
1. /dev/ttyUSB0。获取串口设备的代码片段如下```function GetSerialList:TStrings;var f:TJavaFile; dirlist:TJavaObjectArray; i:Integer;begin Result:=TStringList.Create; try f:=TJavaFile.JavaClass.Create('/dev'); dirlist:=f.listFiles; for i:=0 to dirlist.Length - 1 do begin if Pos('ttyS',TJFile.Wrap(dirlist.Items[i]).getName)>0 then Result.Add(TJFile.Wrap(dirlist.Items[i]).getName); if Pos('ttyUSB',TJFile.Wrap(dirlist.Items[i]).getName)>0 then Result.Add(TJFile.Wrap(dirlist.Items[i]).getName); end; finally f.Free; end;end;```2.2 设置串口参数在调用串口设备前,需要先将串口的通讯参数设置为正确的状态。包括波特率、数据位、停止位、校验位。当然了,你也能够依据需要,不设置校验位,比如不设置奇偶校验。最后通过串口的管理器,设置参数。下面是设置串口参数的完整代码```procedure T安卓Serial.SetSerialParam(port: String; baudrate: Integer; databits: Integer; stopbits: Integer; parity: Integer);var fd: Integer; speed: LongInt;begin fd := open(StringToPansiChar('/dev/'+port), O,RDWR);//打开串口设备 if (fd <0) then exit; tcgetattr(fd,@options);//读取串口设备参数//初始化options结构体,这应该被做到打开设备之后,然后就是用的操作应该都是老调重弹的。 options.c,cflag := TCSAFLUSH or TCSANOW; options.c,cflag := options.c,cflag or CLOCAL or CREAD;//忽略掉接收中断、成为本地串口,不许任何进程占用串口 case baudrate of//设置波特率 9600:speed:=B9600; 19200:speed:=B19200; 38400:speed:=B38400; 57600:speed:=B57600; 115200:speed:=B115200; 230400:speed:=B230400; end; cfsetispeed(@options, speed); cfsetospeed(@options, speed); options.c,cflag := options.c,cflag or CS8;//数据位 case stopbits of//停止位 1: options.c,cflag:=options.c,cflag and not CSTOPB; 2: options.c,cflag:=options.c,cflag or CSTOPB; end; case parity of//偶校验/奇校验 0:begin//无校验 options.c,cflag:=options.c,cflag and not PARENB; end; 1:begin//奇校验 options.c,cflag:=options.c,cflag or PARENB; options.c,cflag:=options.c,cflag or PARODD; options.c,iflag:=options.c,iflag or INPCK; end; 2:begin//偶校验 options.c,cflag:=options.c,cflag or PARENB; options.c,cflag:=options.c,cflag and not PARODD; options.c,iflag:=options.c,iflag or INPCK; end; 3:begin//Mark校验 options.c,cflag:=options.c,cflag or PARENB; options.c,cflag:=options.c,cflag or PARODD; options.c,cflag:=options.c,cflag or CMSPAR; options.c,iflag:=options.c,iflag or INPCK; end; 4:begin//Space校验 options.c,cflag:=options.c,cflag or PARENB; options.c,cflag:=options.c,cflag and not PARODD; options.c,cflag:=options.c,cflag or CMSPAR; options.c,iflag:=options.c,iflag or INPCK; end; end; tcflush(fd,TCIFLUSH); tcsetattr(fd, TCSANOW, @options); Close(fd);end;```2.3 打开串口在设置好串口参数后,就可以打开串口了。调用fcntl()函数来打开串口设备,并设置为非堵塞模式。同时,将串口数据实时输出到退出时调用的函数。这样就可以在代码中通过读取串口接收缓冲区的数据来判断串口接收到数据了。在这里,使用的是重绘主窗口的方法来实现读取串口接收缓冲区的数据。下面是打开串口的代码```function T安卓Serial.OpenSerial(port: String; baudrate: Integer; databits: Integer; parity: Integer; stopbits: Integer; hwfc:Boolean):Boolean;var fd: Integer;begin try fd := open(StringToPansiChar('/dev/'+port), O,RDWR); if (fd < 0) then begin exit(False); end; options.c,cc[VMIN] := 0; //防止阻塞 options.c,cc[VTIME] := 30; //等待过时时间,单位10ms tcflush(fd,TCIOFLUSH); if fcntl(fd, F,SETFL, O,NONBLOCK) < 0 then begin exit(False); end; isStop:=false; TThread.CreateAnonymousThread( procedure var n:Integer; mstr:UTF8String; begin while not isStop do begin n := Read(fd, mbufferJS[0], BUFFER,SIZE - 1); if (n > 0) then begin mbufferJS[n] := #0; mstr:=UTF8Encode(Trim(mbufferJS)); ShowMsg(mstr);//这里实现重绘主窗口,可以读取缓冲区中的数据 end; Sleep(10);//过快的读取会让进程崩溃 end; end).Start; Result := True; except Result := False; end;end;```2.4 发送和接收数据现在,我们已经将串口端口打开了,这样的话如何发送和接收数据呢?最简单的方法是使用Delphi中的Write和Read函数。但在本例中,使用System.IOUtils库的TBytesStream来创建一个缓冲区缓存数据包。在写入数据时,将需要发送的数据写入到流中,然后将流输出到端口。在读取数据时,读取端口的缓冲区中的字节并存储在TBytesStream中,然后从流中读取收到的数据。下面是发送和接收数据的完整代码函数SendData(将byte类型的数据报文直接发送)```procedure T安卓Serial.SendData(Data: TBytes);begin TThread.CreateAnonymousThread( procedure begin while isOpen do begin try TMonitor.Enter(FSerialLock); try if Write(fd, Data[0], Length(Data))<=0 then break; finally TMonitor.Exit(FSerialLock); end; except break;//发生错误时退出该线程 end; break;//只发送一次 end; end).Start;end;```函数ReadData:(读取缓存区的数据,放入数据缓存TBytesStream中并返回读取的字节数)```function T安卓Serial.ReadData(var Data: TBytes): Integer;var stream: TBytesStream; c: byte; i : integer;begin stream := TBytesStream.Create; try i:=0; while i < BUFFER,SIZE do begin TMonitor.Enter(FSerialLock); try if (Read(fd, c, 1) > 0) then begin stream.Write(c, 1); Inc(i); end; finally TMonitor.Exit(FSerialLock); end; end; SetLength(Data, stream.Size); stream.Position := 0; stream.ReadBuffer(Data[0], stream.Size); finally stream.Free; end; Result := Length(Data);end;```到此,安卓串口通讯的实现已经全部完成。这样实现后,你就可以很轻松地实现安卓的串口通讯了。
2024-01-10
54 次阅读