Android串口开发及读取完整数据的解决方法
Android串口通信解决方案
Android串口全面解决方案武汉波仕电子公司串口(RS-232/RS-485)主要用于工业测量和控制,计算机以及Windows正在部分被平板和Android代替,计算机串口也在逐步被Android串口取代。
本文介绍了在Android下的几种串口解决方案。
从连接方式上来分,分为无线和有线,无线又分为蓝牙和WiFi,有线分为主板自带和USB口扩展。
从实现方式上来分,分为自带串口的专用设备、对通用设备进行串口扩展。
如果是用于高可靠性要求的工业测控,有线串口是必须的。
因为有线的抗干扰能力远远强于无线。
如果用于日常的测控,无线则更加方便,因为无需布线。
1、蓝牙串口转换器BLU232型蓝牙/串口转换器只有DB-9/DB-9转接头大小,将android智能手机或者平板电脑的蓝牙信号转换出RS-232/RS-485口,无线通信距离10米。
BLU232可以为带蓝牙的Android设备扩展出一个无线串口。
1、将BLU232接上电源,LED灯亮。
2、蓝牙——“添加蓝牙设备”,无线扫描找到蓝牙BOLUTEK,输入配对密码:1234。
3、BLU232默认为从机状态、波特率等格式为(9600,n,8,1)。
在ANDROID下可以使用“蓝牙串口.apk”等软件进行智能手机的串口通信。
2、WiFi串口转换器波仕AP232L型WiFi串口转换器实现无线WiFi与RS-232/RS-485/422串口的转换,这样Android智能设备可以用无线WiFi进行串口通信,无线通信距离50米。
产品本身可通过浏览器进行设置,无须其它任何专用软件或装置。
由于AP232L本身是通过TCP/IP协议来虚拟串口通信的,所以Android智能手机或者平板电脑也可以直接用TCP/IP通信。
先安装TCP-TEST.APK(TCP网络助手),并连接到AP232L 的无线信号。
运行TCP网络助手,选中“tcp client”,键入AP232L默认的IP地址(192.168.1.1)和端口(2001),按“增加”即可。
串口发送和接收数据的一般方法
串口发送和接收数据的一般方法串口通信是一种用于在计算机或嵌入式系统之间传输数据的常用通信方式。
它使用串行连接,并遵循一定的通信协议。
在串口通信中,通常涉及到发送和接收数据的步骤。
下面是串口发送和接收数据的一般方法的详细解释。
1.打开串口:在发送和接收数据之前,需要首先打开串口连接。
打开串口可以通过相应的串口库函数实现。
常用的串口库函数有SerialPort in C/C++和pyserial in Python。
这些库函数提供了用于打开和控制串口的功能。
2.配置串口参数:打开串口后,需要配置一些串口参数,例如波特率、数据位、停止位和校验位等。
这些参数的配置通常由串口库函数提供的设置函数完成。
根据实际需求,可以选择不同的参数配置。
3.发送数据:发送数据是通过调用串口库函数提供的发送函数实现的。
发送函数通常需要传入一个数据缓冲区和要发送的数据长度作为参数。
在发送数据之前,需要将要发送的数据存储到数据缓冲区中。
发送函数会将数据从缓冲区发送到串口。
4.接收数据:接收数据是通过调用串口库函数提供的接收函数实现的。
接收函数通常需要传入一个数据缓冲区和要接收的数据长度作为参数。
在接收数据之前,需要定义一个足够大的缓冲区来存储接收到的数据。
接收函数会将数据从串口读取并存储到缓冲区中。
5.数据处理:接收到的数据可以进行进一步的处理。
例如,可以将数据解析为具体的信息,或者根据接收到的数据执行特定的操作。
数据处理的方法取决于应用需求。
6.关闭串口:在数据的发送和接收任务完成之后,应该关闭串口连接。
关闭串口可以通过调用串口库函数提供的关闭函数实现。
关闭串口将释放相关的资源。
需要注意的是,在进行串口通信时,要确保发送和接收端的串口参数配置一致。
否则,可能导致通信失败或数据解析错误。
上述是关于串口发送和接收数据的一般方法的基本介绍。
具体的实现方法和细节会因为不同的编程语言和串口库函数而有所差异。
因此,在实际应用中可以根据具体情况选择适合的编程语言和库函数,以实现串口通信。
读取串口数据
读取串口数据方法一:使用VC++提供的串行通信控件MSComm 首先,在对话框中创建通信控件,若Control工具栏中缺少该控件,可通过菜单Project --> Add to Project --> Components and Control插入即可,再将该控件从工具箱中拉到对话框中。
此时,你只需要关心控件提供的对Windows 通讯驱动程序的 API 函数的接口。
换句话说,只需要设置和监视MSComm控件的属性和事件。
在ClassWizard中为新创建的通信控件定义成员对象(CMSComm m_Serial),通过该对象便可以对串口属性进行设置,MSComm 控件共有27个属性,这里只介绍其中几个常用属性: CommPort 设置并返回通讯端口号,缺省为COM1。
Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
PortOpen 设置并返回通讯端口的状态,也可以打开和关闭端口。
Input 从接收缓冲区返回和删除字符。
Output 向发送缓冲区写一个字符串。
InputLen 设置每次Input读入的字符个数,缺省值为0,表明读取接收缓冲区中的全部内容。
InBufferCount 返回接收缓冲区中已接收到的字符数,将其置0可以清除接收缓冲区。
InputMode 定义Input属性获取数据的方式(为0:文本方式;为1:二进制方式)。
RThreshold 和 SThreshold 属性,表示在 OnComm 事件发生之前,接收缓冲区或发送缓冲区中可以接收的字符数。
以下是通过设置控件属性对串口进行初始化的实例:BOOL CSampleDlg:: PortOpen(){BOOL m_Opened;......m_Serial.SetCommPort(2); // 指定串口号m_Serial.SetSettings("4800,N,8,1"); // 通信参数设置m_Serial.SetInBufferSize(1024); // 指定接收缓冲区大小m_Serial.SetInBufferCount(0); // 清空接收缓冲区m_Serial.InputMode(1); // 设置数据获取方式m_Serial.SetInputLen(0); // 设置读取方式m_Opened=m_Serail.SetPortOpen(1); // 打开指定的串口return m_Opened;}打开所需串口后,需要考虑串口通信的时机。
c 读取串口中大量数据的方法
c 读取串口中大量数据的方法在C语言中,读取串口中大量数据的方法主要依赖于操作系统的API。
下面是一种在Linux系统下使用termios API来读取串口中大量数据的方法。
首先,你需要包含一些必要的头文件:```cinclude <>include <>include <>include <>include <>include <>include <>```然后,你可以使用open函数打开串口:```cint fd = open("/dev/ttyS0", O_RDWR O_NOCTTY O_NDELAY);if (fd == -1) {perror("open_port: Unable to open /dev/ttyS0 - ");} else {fcntl(fd, F_SETFL, 0);}```接下来,你可以使用tcgetattr和tcsetattr函数来获取和设置串口的属性:```cstruct termios options;tcgetattr(fd, &options);// Set the speed of the serial portcfsetispeed(&options, B9600);cfsetospeed(&options, B9600);// Enable the receiver and set local mode_cflag = (CLOCAL CREAD);_cflag &= ~PARENB; // No parity bit_cflag &= ~CSTOPB; // 1 stop bit_cflag &= ~CSIZE; // clear data size bits_cflag = CS8; // set 8 data bits_lflag &= ~(ICANON ECHO ECHOE ISIG); // Raw input mode_iflag &= ~(IXON IXOFF IXANY); // Turn off s/w flow ctrl_oflag &= ~OPOST; // Prevent special interpretation of output fields ( newline chars)_cc[VMIN] = 1; // read at least 1 character from port when there is available data_cc[VTIME] = 0; // no timeout (wait forever)tcsetattr(fd, TCSANOW, &options);```现在你可以使用read函数来读取数据:```cchar buf[1024]; // 用于存储从串口读取的数据的缓冲区,你可以根据实际情况调整大小。
串口接收数据流程
串口接收数据流程
串口接收数据流程是指从串口接收数据时的一系列步骤。
其流程可分为如下步骤:
1.串口初始化:首先需要初始化串口,即设置串口的波特率、校验位、数据位、停止
位等参数。
2.等待数据:接下来程序需要等待请求数据到来,可通过串口中断来实现。
3.接收数据:当有数据到达时,串口会触发相应中断,程序会在中断处理函数中接收
数据。
一般每次只接收一个字节。
4.数据处理:接收到的数据需要进行相应处理,包括校验、解码等等。
5.数据存储:处理完数据后,将其存储到相应的存储器中,如内存、缓冲区等。
6.数据通知:当数据存储完毕后,程序需要通过相关标志位或事件通知上层处理程序,让其进行相应的处理。
上述步骤是常见的串口接收数据流程,具体实现可参考如下代码:
```c
#include <stdio.h>
#include <string.h>
#include <Windows.h>
#define PORT "COM1"
上述代码主要实现了串口的初始化、等待数据、接收数据等操作,可供参考。
总结来说,串口接收数据流程包括初始化、等待数据、接收数据、数据处理、数据存储和数据通
知等步骤。
串口接收数据包(协议带帧头帧尾且帧头帧尾都为两个字节)的编程实现方法
串口接收数据包(协议带帧头帧尾且帧头帧尾都为两个字节)的编程实现方法要实现串口接收带有帧头和帧尾的数据包,可以按照以下步骤进行编程:1. 配置串口通信参数:设置串口的波特率、数据位、停止位和奇偶校验位等参数。
2. 初始化接收缓冲区:创建一个缓冲区用于存储接收到的数据包。
3. 等待接收数据:通过串口的接收中断或者轮询方式等待接收数据。
当接收到数据时,将数据保存到接收缓冲区中。
4. 解析数据包:从接收缓冲区中读取数据,并根据帧头和帧尾进行解析。
可以使用状态机或者字符串匹配等方法,找到完整的数据包。
5. 处理数据:对解析得到的完整数据包进行处理。
根据协议的要求,可以提取或者操作数据包的各个字段。
下面是一个示例代码,利用状态机实现串口接收带有帧头和帧尾的数据包解析:```c#define FRAME_HEAD1 0xAA#define FRAME_HEAD2 0xBB#define FRAME_TAIL1 0xCC#define FRAME_TAIL2 0xDD#define BUFFER_SIZE 100enum State {STATE_IDLE,STATE_HEAD1,STATE_HEAD2,STATE_DATA,STATE_TAIL1,STATE_TAIL2};unsigned char buffer[BUFFER_SIZE];unsigned int bufferIndex = 0;enum State currentState = STATE_IDLE;void processPacket(unsigned char *packet, unsigned int length) { // 处理接收到的完整数据包// ...}void receiveData(unsigned char data) {switch(currentState) {case STATE_IDLE:if(data == FRAME_HEAD1) {currentState = STATE_HEAD1;}break;case STATE_HEAD1:if(data == FRAME_HEAD2) {currentState = STATE_HEAD2;} else {currentState = STATE_IDLE; // 未匹配到帧头,返回初始状态}break;case STATE_HEAD2:buffer[bufferIndex++] = data;currentState = STATE_DATA;break;case STATE_DATA:buffer[bufferIndex++] = data;if(data == FRAME_TAIL1) {currentState = STATE_TAIL1;}break;case STATE_TAIL1:if(data == FRAME_TAIL2) {currentState = STATE_TAIL2;} else {currentState = STATE_DATA; // 未匹配到帧尾,返回数据状态}break;case STATE_TAIL2:processPacket(buffer, bufferIndex); // 处理完整数据包bufferIndex = 0; // 重置缓冲区索引currentState = STATE_IDLE;break;}}void receiveSerialData() {if(Serial.available()) {unsigned char data = Serial.read();receiveData(data);}}void setup() {Serial.begin(9600);}void loop() {receiveSerialData();}```以上是一个简单的示例代码,根据实际需求可能需要进行适当修改。
串口读取数据的方法
串口读取数据的方法1.打开串口:首先需要打开串口,通过设备文件或串口号来指定要打开的串口。
```c++#include <stdio.h>#include <fcntl.h>#include <termios.h>int openSerialPort(const char* portName)int fd = open(portName, O_RDWR , O_NOCTTY);if (fd < 0)printf("Failed to open serial port\n");return -1;}//配置串口参数struct termios options;tcgetattr(fd, &options);cfsetispeed(&options, B9600);cfsetospeed(&options, B9600);options.c_cflag ,= (CLOCAL , CREAD);tcsetattr(fd, TCSANOW, &options);return fd;}```2.读取串口数据:打开串口之后,可以通过读取文件描述符来读取串口数据。
```c++int readSerialData(int fd, unsigned char* buffer, int bufferSize)int bytesRead = read(fd, buffer, bufferSize);if (bytesRead < 0)printf("Failed to read serial data\n");}return bytesRead;}```3.解析串口数据:读取到的数据可能是原始的字节流,需要根据具体的协议和数据格式进行解析。
```c++void parseData(unsigned char* buffer, int bufferSize)//解析数据的逻辑}```4.循环读取数据:可以使用循环来不断读取串口数据,并进行解析和处理。
串口数据实事处理方案
串口数据实事处理方案串口数据实时处理方案串口数据处理是指在计算机通过串口接收到数据时,对该数据进行处理和操作。
串口是一种常见的数据通信接口,可以用来连接计算机与其他设备(如传感器、电机等)之间进行数据传输。
在实时处理串口数据时,我们可以采取以下方案:1. 选择合适的串口库:在使用串口进行数据通信时,可以选择一款合适的串口库来简化数据处理的过程。
常用的串口库包括pyserial(Python)、SerialPort(C#)等,它们提供了丰富的接口和函数,可以方便地实现数据的接收和发送。
2. 设计数据协议:在串口通信中,数据的传输需要遵守一定的协议。
设计合适的数据协议可以保证数据的正确传输和解析。
协议的设计可以包括数据帧的结构、校验位的添加、数据格式的编码等。
通过合理的协议设计,可以提高串口数据处理的效率和稳定性。
3. 实时数据处理:在串口接收到数据后,需要对数据进行实时处理。
这包括数据的解析、处理和存储等。
可以根据需要,使用合适的算法对数据进行处理,比如滤波、数据压缩等。
处理完的数据可以存储到数据库中或者实时展示在界面上,方便后续的数据分析和使用。
4. 异常处理和错误纠正:在串口通信过程中,可能会遇到各种异常。
比如数据丢失、传输错误等。
此时需要对异常进行处理和纠正,以确保数据的完整性和准确性。
可以通过合理的异常处理策略,如重新发送数据、纠正错误等,提高数据处理的可靠性和稳定性。
5. 调试和优化:在实时处理串口数据的过程中,需要不断进行调试和优化,以提高程序的性能和稳定性。
可以通过日志输出、性能监控等手段,定位和解决潜在的问题,进一步优化处理流程和算法。
综上所述,实时处理串口数据需要选择合适的串口库、设计合理的数据协议,并进行实时数据处理、异常处理和错误纠正等。
只有在不断的调试和优化下,才能提高串口数据处理的效率和稳定性。
抓取串口打印数据的方法
抓取串口打印数据的方法正文:要捕获串口打印数据,可以使用以下几种方法:1. 使用串口调试助手软件:可以使用第三方串口调试助手软件,例如Tera Term、PuTTY或者RealTerm等工具。
这些软件可以连接到串口并监视数据的传输。
通过设置正确的串口参数(如波特率、数据位、停止位、奇偶校验等),可以捕获并显示串口打印数据。
2. 使用串口库进行编程:如果需要在自己的程序中捕获串口打印数据,可以使用串口库进行编程。
例如,在Python中可以使用pySerial 库,而在C/C++中可以使用WinAPI或者POSIX的串口相关函数来实现。
通过打开串口、设置串口参数并读取数据,可以将串口打印数据读取到程序中进行处理。
3. 使用逻辑分析仪:逻辑分析仪是一种专门用于捕获和分析串口通信的硬件设备。
逻辑分析仪可以连接到电脑上,并通过软件来捕获串口打印数据。
通过设置正确的串口参数和触发条件,可以捕获特定的串口打印数据,以供后续分析和处理。
需要注意的是,无论使用哪种方法,都需要正确设置串口参数,包括波特率、数据位、停止位、奇偶校验等。
此外,还要确保串口连接正常,并且接收端的程序或设备正在发送数据。
如果想要进一步拓展该功能,可以考虑以下几点:1. 数据保存:可以将捕获的串口打印数据保存到文件中,以便后续查看和分析。
可以将数据保存为文本文件或者其他格式,以满足不同的需求。
2. 数据处理与分析:可以对捕获的串口打印数据进行处理和分析。
可以提取关键信息、进行数据统计、绘制图表等,以帮助理解和优化串口通信过程。
3. 实时监控与通知:可以实时监控串口打印数据,并根据特定条件发送通知。
例如,可以检测某些特定的关键字或错误信息,并在满足条件时发送邮件或者触发其他操作,以及时处理问题。
4. 跨平台支持:可以编写跨平台的串口捕获程序,以便在不同的操作系统上运行。
可以使用跨平台的编程语言或者框架来实现,如Python、Java或者Electron等。
串口调试步骤范文
串口调试步骤范文串口调试是指通过串口通信接口对设备进行调试和通信。
本文将介绍串口调试的步骤和方法。
一、串口调试的准备工作1.选择串口调试软件:常用的串口调试软件有SecureCRT、Putty、RealTerm等,根据具体需求选择合适的软件。
2.确定串口参数:包括波特率、数据位、停止位和校验位等。
根据实际需求,选择相应的参数。
二、串口调试的步骤1.打开串口调试软件:运行选择的串口调试软件。
2.连接串口:通过串口线将设备与电脑连接起来,并插入电源。
3.选择串口:在串口调试软件中选择正确的串口号。
一般来说,串口号为COM1、COM2等,可以在设备管理器中查看或者通过串口调试软件自动检测。
4.设置串口参数:在串口调试软件中设置正确的串口参数,包括波特率、数据位、停止位和校验位等。
5.打开串口:点击软件中的“打开串口”按钮,即可打开串口并开始通信。
6.发送数据:在串口调试软件中的发送区输入需要发送的数据,并点击“发送”按钮发送出去。
7.接收数据:在串口调试软件中的接收区可以查看到从设备接收到的数据。
三、串口调试常用的工具和方法1.发送和接收ASCII码:串口调试软件一般支持发送和接收ASCII码,可以直接输入需要发送的字符,或者输入ASCII码。
2.十六进制发送和接收:通过将数据转换为十六进制的形式发送和接收,可以方便地查看和分析数据。
3.循环发送和接收:可以设置串口调试软件循环发送和接收数据,用于测试串口的稳定性。
4.自动重连:有些串口调试软件支持自动重连功能,当串口连接中断后可以自动重新连接。
四、串口调试注意事项1.正确选择串口号:根据具体情况选择正确的串口号,避免发生连接错误。
2.设置正确的串口参数:根据设备的要求设置正确的串口参数,确保数据传输的正确性。
3.注意数据的发送顺序:有些设备对数据的发送顺序有要求,需要按照规定的顺序发送数据。
4.注意数据的格式:确保发送和接收的数据格式一致,避免发生接收错误。
android studio编译short read of der length
在Android Studio编译时出现"short read of der length" 错误,通常涉及到证书或密钥相关问题。
这个错误信息提示DER编码的长度读取不完整。
以下是一些可能的解决方案:
1. 检查证书和密钥文件:确保使用正确的证书和密钥文件进行编译和签名。
检查文件路径和文件格式是否正确。
2. 检查证书和密钥的完整性:确保证书和密钥文件没有被损坏或篡改。
如果文件有问题,可以尝试重新生成或获取正确的证书和密钥。
3. 清除Gradle缓存:尝试清除Gradle缓存并重新构建项目。
可以在命令行中使用以下命令清除Gradle缓存:
./gradlew cleanBuildCache
4. 更新Android Studio:确保使用最新版本的Android Studio。
有时旧版本的Android Studio可能存在一些已知的BUG,更新到最新版本可能能够解决该问题。
5. 更新Gradle版本:如果项目中使用了Gradle构建系
统,尝试更新Gradle版本。
在项目的build.gradle文件中进行更新,例如:
classpath 'com.android.tools.build:gradle:4.0.1'
6. 重新导入证书:如果以上方法都没有解决问题,可以尝试重新导入证书。
首先删除导入的证书,然后再次导入并确保正确配置。
如果以上方法仍然无法解决问题,建议参考相关文档和论坛来了解更多关于 "short read of der length" 错误的解决方案。
android串口调试
android串⼝调试在Androidstudio调试安卓串⼝的⼀个demo⼯程,第⼀次接触安卓串⼝,记录⼀下调试过程的坑。
⾸先,需要编译出串⼝的so。
打开⼯程,在AndroidSerialPort-master\app\src\main\jni可以看到源代码SerialPort.c。
电脑已经配置过ndk的话,打开cmd,cd到这个⽂件夹,运⾏ndk-build就可以编译出so。
需要注意的是,SerialPort.c中函数的包名需要和你的android⼯程的包名⼀致。
android⼯程:SerialPort.c:编译:直接这样编译的话,在api⼤于19的时候可能会出现tcsetattr failed,需要替换termios.h。
下载新的termios.h放⼊jni⽬录,修改SerialPort.c中#include <termios.h> ---> include "termios.h",再编译。
app⽬录下,新建⼀个libs⽬录,libs内新建armeabi⽬录,编译得到的so放在armeabi⽬录。
安卓⼯程的build.grandle修改如下:apply plugin: 'com.android.application'android {compileSdkVersion 23buildToolsVersion "29.0.2"defaultConfig {applicationId "com.android.serialport"minSdkVersion 15targetSdkVersion 23}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'}}sourceSets {main {jniLibs.srcDirs = ['libs']}}compileOptions {sourceCompatibility = 1.7targetCompatibility = 1.7}//⾃定义apk安装包名android.applicationVariants.all {variant ->variant.outputs.all {//这⾥修改apk⽂件名outputFileName = "AndroidSerial.apk"}}}dependencies {//noinspection GradleCompatibleimplementation 'com.android.support:appcompat-v7:23.4.0'implementation files('libs/portlibrary.jar')}其次,编译得到apk,使⽤模拟器和虚拟串⼝测试。
android串口通信实例分析
android串口通信实例分析置顶] android串口通信实例分析分类: android 2012-05-21 23:31 118人阅读评论(4) 收藏举报android 串口通信实例分析,用的时开源的android-serialport-api这个是用android ndk实现的串口通信,我把他做了一个简化,适合于一般的程序的串口通信移植,欢迎拍砖~~~~~~~~~先说jni接口吧,原本文件太多,其实只需要SerialPort.c和Android.mk就可以实现Serialport.c[java]view plaincopy?1.#include <stdio.h>2.#include <stdlib.h>3.#include <unistd.h>4.#include <sys/types.h>5.#include <sys/stat.h>6.#include <fcntl.h>7.#include <termios.h>8.#include <errno.h>9.#include <jni.h>10.#include <android/log.h>11.12.#define LOGI(...) ((void)__android_log_print(ANDROID_ LOG_INFO, "", __VA_ARGS__))//在logcat上打印信息用13.//#define LOGD(fmt, args...) __android_log_print(ANDR OID_LOG_DEBUG, TAG, fmt, ##args)14.//#define LOGE(fmt, args...) __android_log_print(ANDR OID_LOG_ERROR, TAG, fmt, ##args)15.16.static speed_t getBaudrate(jint baudrate)17.{18.switch(baudrate) {19.case 0: return B0;20.case 50: return B50;21.case 75: return B75;22.case 110: return B110;23.case 134: return B134;24.case 150: return B150;25.case 200: return B200;26.case 300: return B300;27.case 600: return B600;28.case 1200: return B1200;29.case 1800: return B1800;30.case 2400: return B2400;31.case 4800: return B4800;32.case 9600: return B9600;33.case 19200: return B19200;34.case 38400: return B38400;35.case 57600: return B57600;36.case 115200: return B115200;37.case 230400: return B230400;38.case 460800: return B460800;39.case 500000: return B500000;40.case 576000: return B576000;41.case 921600: return B921600;42.case 1000000: return B1000000;43.case 1152000: return B1152000;44.case 1500000: return B1500000;45.case 2000000: return B2000000;46.case 2500000: return B2500000;47.case 3000000: return B3000000;48.case 3500000: return B3500000;49.case 4000000: return B4000000;50.default: return -1;51.}52.}53.54./*55.* Class: com.huangcheng.serial.SerialPort56.* Method: open57.* Signature: (Ljava/lang/String;II)Ljava/io/FileDescripto r;58.*59.* 用于打开串口,配置串口参数,包括的参数有path(需要打开的串口设备文件路径),baudrate(波特率),flags(打开串口的参数,如O_NONBLOCK之类的,可以随不同情况设置)60.* 其串口数据的读取是用FileDescriptor来实现的61.*62.*/63.JNIEXPORT jobject JNICALL Java_com_huangcheng_se rial_SerialPort_open64.(JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)65.{66.int fd;67.speed_t speed;68.jobject mFileDescriptor;69.70./* Check arguments */71.{72.speed = getBaudrate(baudrate);73.if (speed == -1) {74./* TODO: throw an exception */75.LOGI("Invalid baudrate");76.return NULL;77.}78.}79.80./* Opening device */81.{82.jboolean iscopy;83.const char *path_utf = (*env)->GetStringUTFChars(env , path, &iscopy);84.LOGI("Opening serial port %s with flags 0x%x", path_u tf, O_RDWR | flags);85.fd = open(path_utf, O_RDWR | flags);86.LOGI("open() fd = %d", fd);87.(*env)->ReleaseStringUTFChars(env, path, path_utf);88.if (fd == -1)89.{90./* Throw an exception */91.LOGI("Cannot open port");92./* TODO: throw an exception */93.return NULL;94.}95.}96.97./* Configure device */98.{99.struct termios cfg;100.LOGI("Configuring serial port");101.if (tcgetattr(fd, &cfg))102.{103.LOGI("tcgetattr() failed");104.close(fd);105./* TODO: throw an exception */106.return NULL;107.}108.109.cfmakeraw(&cfg);110.cfsetispeed(&cfg, speed);111.cfsetospeed(&cfg, speed);112.113.if (tcsetattr(fd, TCSANOW, &cfg))114.{115.LOGI("tcsetattr() failed");116.close(fd);117./* TODO: throw an exception */118.return NULL;119.}120.}121.122./* Create a corresponding file descriptor */123.{124.jclass cFileDescriptor = (*env)->FindClass(env, "java/io /FileDescriptor");125.jmethodID iFileDescriptor = (*env)->GetMethodID(en v, cFileDescriptor, "<init>", "()V");126.jfieldID descriptorID = (*env)->GetFieldID(env, cFileDe scriptor, "descriptor", "I");127.mFileDescriptor = (*env)->NewObject(env, cFileDescri ptor, iFileDescriptor);128.(*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);129.}130.131.return mFileDescriptor;132.}133.134./*135.* Class: com.huangcheng.serial.SerialPort136.* Method: close137.* Signature: ()V138.*139.* 用于串口关闭140.*/141.JNIEXPORT void JNICALL Java_com_huangcheng_serial _SerialPort_close142.(JNIEnv *env, jobject thiz)143.{144.jclass SerialPortClass = (*env)->GetObjectClass(env, th iz);145.jclass FileDescriptorClass = (*env)->FindClass(env, "jav a/io/FileDescriptor");146.147.jfieldID mFdID = (*env)->GetFieldID(env, SerialPortCla ss, "mFd", "Ljava/io/FileDescriptor;");148.jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");149.150.jobject mFd = (*env)->GetObjectField(env, thiz, mFdID );151.jint descriptor = (*env)->GetIntField(env, mFd, descrip torID);152.153.LOGI("close(fd = %d)", descriptor);154.close(descriptor);155.}Android.mk[plain]view plaincopy?1.LOCAL_PATH := $(call my-dir)2.3.include $(CLEAR_VARS)4.5.LOCAL_MODULE := serial_port6.LOCAL_SRC_FILES := SerialPort.c7.8.LOCAL_LDLIBS := -llog9.include $(BUILD_SHARED_LIBRARY)然后,直接在目录下ndk-build一下,便可得到我们需要的lib库文件。
详解AndroidUSB转串口通信开发基本流程
详解AndroidUSB转串⼝通信开发基本流程好久没有写⽂章了,年前公司新开了⼀个项⽬,是和usb转串⼝通信相关的,需求是⽤安卓平板通过usb转接后与好⼏个外设进⾏通信,⼀直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串⼝通信开发的基本流程。
我们开发使⽤的是usb主机模式,即:安卓平板作为主机,usb外设作为从机进⾏数据通信。
整个开发流程可以总结为以下⼏点:1.发现设备UsbManager usbManager = (UsbManager) context.getSystemService(B_SERVICE);Map<String, UsbDevice> usbList = usbManager.getDeviceList();通过UsbManager这个系统提供的类,我们可以枚举出当前连接的所有usb设备,我们主要需要的是UsbDevice对象,关于UsbDevice这个类,官⽅是这样注释的:This class represents a USB device attached to the android device with the android deviceacting as the USB host.是的,这个类就代表了Android所连接的usb设备。
2.打开设备接下来,我们需要打开刚刚搜索到的usb设备,我们可以将平板与usb外设之间的连接想象成⼀个通道,只有把通道的门打开后,两边才能进⾏通信。
⼀般来说,在没有定制的android设备上⾸次访问usb设备的时候,默认我们是没有访问权限的,因此我们⾸先要判断对当前要打开的usbDevice是否有访问权限:if (!usbManager.hasPermission(usbDevice)) {usbPermissionReceiver = new UsbPermissionReceiver();//申请权限Intent intent = new Intent(ACTION_DEVICE_PERMISSION);PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, intent, 0);IntentFilter permissionFilter = new IntentFilter(ACTION_DEVICE_PERMISSION);context.registerReceiver(usbPermissionReceiver, permissionFilter);usbManager.requestPermission(usbDevice, mPermissionIntent);}这⾥我们声明⼀个⼴播UsbPermissionReceiver,当接受到授权成功的⼴播后做⼀些其他处理:private class UsbPermissionReceiver extends BroadcastReceiver {public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (ACTION_DEVICE_PERMISSION.equals(action)) {synchronized (this) {UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device.getDeviceName().equals(usbDevice.getDeviceName()) {if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {//授权成功,在这⾥进⾏打开设备操作} else {//授权失败}}}}}}接下来,我们要找到具有数据传输功能的接⼝UsbInterface,从它⾥边⼉找到数据输⼊和输出端⼝UsbEndpoint,⼀般情况下,⼀个usbDevice有多个UsbInterface,我们需要的⼀般是第⼀个,所以:usbInterface=usbDevice.getInterface(0);同样的,⼀个usbInterface有多个UsbEndpoint,有控制端⼝和数据端⼝等,因此我们需要根据类型和数据流向来找到我们需要的数据输⼊和输出两个端⼝:for (int index = 0; index < usbInterface.getEndpointCount(); index++) {UsbEndpoint point = usbInterface.getEndpoint(index);if (point.getType() == B_ENDPOINT_XFER_BULK) {if (point.getDirection() == B_DIR_IN) {usbEndpointIn = point;} else if (point.getDirection() == B_DIR_OUT) {usbEndpointOut = point;}}}最后,才是真正的打开usb设备,我们需要和usb外设建⽴⼀个UsbDeviceConnection,它的注释很简介的说明了它的⽤途:This class is used for sending and receiving data and control messages to a USB device.它的获取也很简单,就⼀句代码:usbDeviceConnection = usbManager.openDevice(usbDevice);到这⾥,理论上平板和usb外设之间的连接已经建⽴了,也可以⾸发数据了,但是,我们⼤部分情况下还需要对usb串⼝进⾏⼀些配置,⽐如波特率,停⽌位,数据控制等,不然两边配置不同,收到的数据会乱码。
Android串口通信解决方案
Android串口全面解决方案武汉波仕电子公司串口(RS-232/RS-485)主要用于工业测量和控制,计算机以及Windows正在部分被平板和Android代替,计算机串口也在逐步被Android串口取代。
本文介绍了在Android下的几种串口解决方案。
从连接方式上来分,分为无线和有线,无线又分为蓝牙和WiFi,有线分为主板自带和USB口扩展。
从实现方式上来分,分为自带串口的专用设备、对通用设备进行串口扩展。
如果是用于高可靠性要求的工业测控,有线串口是必须的。
因为有线的抗干扰能力远远强于无线。
如果用于日常的测控,无线则更加方便,因为无需布线。
1、蓝牙串口转换器BLU232型蓝牙/串口转换器只有DB-9/DB-9转接头大小,将android智能手机或者平板电脑的蓝牙信号转换出RS-232/RS-485口,无线通信距离10米。
BLU232可以为带蓝牙的Android设备扩展出一个无线串口。
1、将BLU232接上电源,LED灯亮。
2、蓝牙——“添加蓝牙设备”,无线扫描找到蓝牙BOLUTEK,输入配对密码:1234。
3、BLU232默认为从机状态、波特率等格式为(9600,n,8,1)。
在ANDROID下可以使用“蓝牙串口.apk”等软件进行智能手机的串口通信。
2、WiFi串口转换器波仕AP232L型WiFi串口转换器实现无线WiFi与RS-232/RS-485/422串口的转换,这样Android智能设备可以用无线WiFi进行串口通信,无线通信距离50米。
产品本身可通过浏览器进行设置,无须其它任何专用软件或装置。
由于AP232L本身是通过TCP/IP协议来虚拟串口通信的,所以Android智能手机或者平板电脑也可以直接用TCP/IP通信。
先安装TCP-TEST.APK(TCP网络助手),并连接到AP232L 的无线信号。
运行TCP网络助手,选中“tcp client”,键入AP232L默认的IP地址(192.168.1.1)和端口(2001),按“增加”即可。
从串口读取数据的几个问题
从串口读取数据的几个问题VC/MFC讨论共有1719位成员人气指数 - 最新排名 -【话题】从串口读取数据的几个问题2009-04-09 17:13:51 来自:lovelyhee 浏览数:74次使用重叠方式来读写串口数据。
对方是个工控机,返回的数据的长度是不可知的,而且有可能超出设的缓存区的大小。
ReadFile读取串口的数据的时候,会要求设一个要读取的数据的数量,但在数据长度不可知,且可能超出预设缓存区的情况下,有什么办法可以在重叠的方式下,取到所有的数据吗?另外,串口读写缓存区的大小最大可以设到多大?之前,我是用阻塞方式来读写串口的,设了超时,以单字节的方式读取,这样能保证读到所有的数据。
但这种方式有两个弊端,对于那些返回数据很少的命令,执行时间太长了;对于那些要等待较长的时间,才能收到第一个字符的命令,这种方式往往取不到返回值。
更多相关的话题小管子回复于10日07点08分这种接收的数据没有什么识别码,所以一般都是发命令,然后收数据,接收完了,再发下一条命令,再收数据......所以主程序也没有办法来判断。
我想了一个办法,不知是否可行,把太大的数据分几次接收,每一次ReadFile要接收数据的大小都设为缓存区的大小,直到接收到的数据大小小于这个设定值,就认为数据接收完了。
就是不知道使用分次接收的方式,会不会导致数据丢失。
系统对于这种数量大于缓存区的数据,是怎样处理的:满了以后,等待程序读取,读完后,清空缓存区,再输入数据吗?xuelian回复于10日15点46分那首先要假设你的接收缓存足够大梅一丁回复于11日06点43分读完数据返回如果该时间内没读到认为是超时庞淇尹回复于11日16点30分什么条件也没有?那样理论上就只剩下超时判断了,那岂不是没有标准了。
hbj1013351回复于12日09点16分比如我的串口程序中,有5个字节的命令头,串口线程死读,分析线程不停判断是否收到了命令头,再根据命令头判断后续数据是否完全了,如果全了的话,分析线程将完整的数据拷贝到主程序的缓冲中,然后通知主程序完整数据到达。
C#解决串口接收数据不完整
C#解决串⼝接收数据不完整C# 解决串⼝接收数据不完整使⽤缓存机制完成。
⾸先通过定义⼀个成员变量List<byte> buffer = new List<byte> (4096);⽤来存放所有的数据,在接收函数⾥,通过buffer.AddRange()⽅法不断地将接收到的数据加⼊到buffer中,并同时对 buffer中的数据进⾏检验,如果达到⼀定的长度并且校验结果正确(校验⽅法在发送⽅和接收⽅⼀致),再进⾏处理。
具体代码如下:代码1. private List<byte> buffer = new List<byte>(4096); 1. private void sp_DataReceived(objectsender, EventArgs e) //sp是串⼝控件 1. {<!-- --> 1. int n =sp.BytesToRead; 1. byte[] buf = new byte[n]; 1. sp.Read(buf, 0, n); 1. 1. //1.缓存数据 1. buffer.AddRange(buf); 1. //2.完整性判断 1. while (buffer.Count >= 4) //⾄少包含帧头(2字节)、长度(1字节)、校验位(1字节);根据设计不同⽽不同 1. {<!-- --> 1. //2.1 查找数据头 1. if (buffer[0] == 0x01) //传输数据有帧头,⽤于判断 1. {<!-- --> 1. int len = buffer[2]; 1. if (buffer.Count < len + 4) //数据区尚未接收完整 1. {<!-- --> 1. break; 1. } 1. //得到完整的数据,复制到ReceiveBytes 中进⾏校验 1. buffer.CopyTo(0, ReceiveBytes, 0, len + 4); 1. byte jiaoyan; //开始校验 1. jiaoyan = this.JY(ReceiveBytes); 1. if (jiaoyan != ReceiveBytes[len+3]) //校验失败,最后⼀个字节是校验位 1. {<!-- --> 1. buffer.RemoveRange(0, len + 4); 1. MessageBox.Show("数据包不正确!"); 1. continue; 1. } 1.buffer.RemoveRange(0, len + 4); 1. /执⾏其他代码,对数据进⾏处理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android串口开发及读取完整数据的解决方法
串口发送实质就是向串口设备写入、读取字节流,和文件的操作很相似,安卓官方已经提供了android-serialport-api,在开源社区上也有很多衍生项目可以
借鉴,本文介绍其中一种用法。
一、添加依赖
在Module下的 build.gradle 中添加:
implementation 'com.aill:AndroidSerialPort:1.0.8'
二、检测权限
首先要有ROOT权限,而且打开串口时,检测读写权限,当没有权限时,会尝试对其进行授权,默认su路径是/system/bin/su,有些设备su路径是/system/xbin/su:
SerialPort.setSuPath("/system/xbin/su");
三、串口打开及关闭
/**
* @param 1 串口路径
* @param 2 波特率
*@param 3 flags 给0就好
*/
SerialPort serialPort = new SerialPort(new File("/dev/ttyS1"), 9600, 0);
//关闭串口
serialPort.close();
四、往串口中写入数据
//从串口对象中获取输出流
OutputStream outputStream = serialPort.getOutputStream();
//定义需要发送的数据
byte[] data = new byte[2];
data[0] = 0x01;
data[1] = 0x02;
//写入数据
outputStream.write(data);
outputStream.flush();
五、读取串口数据
读取数据时候会遇到不能一次性读取正确的完整的数据,可以这样解决:
1、在开始读取数据前,让读取数据的线程先睡眠一段时间,等待数据都准备好,再开始读取出来,这样应该可以避免大部分的分包情况
2、如果是固定的数据长度,循环读取完固定长度的字节数据再退出
//从串口对象中获取输入流
InputStream inputStream = serialPort.getInputStream();
//循环读取数据,放到子线程去,避免堵塞主线程
boolean readContinue=true;
new Thread(new Runnable() {
@Override
public void run() {
while (readContinue) {
if (inputStream.available() > 0) {
//等待一段时间再读取数据,基本上大部分情况下都是完整的数据
Thread.sleep(50);
byte[] buffer = new byte[12];
int readCount=0;
int availableCount=inputStream.available();
//每次接收都是固定长度的字节
while (readCount < 12 && availableCount > 0) {
readCount += inputStream.read(buffer, readCount, 12 -readCount);
Thread.sleep(5);
availableCount = inputStream.available();
}
}
}
}
}).start();
3、在实际开发中,有一种应用场景是先发送数据到开发板,开发板再响应返回数据,而且是循环发送读取数据,时间间隔要求极其短,很可能出现了数据错乱情况,可以先在发送数据前判断输入流中有无数据,有数据时先读取完流中的数据。
while (readContinue) {
//先判断输入流中有无数据,有数据先读取完清空缓冲
while (inputStream.available() > 0) {
byte[] buffer = new byte[12];
inputStream.read(buffer);
Thread.sleep(5);
}
//写入数据
outputStream.write(data);
outputStream.flush();
//读数据及其他操作
……
Thread.sleep(100); }。