① android串口通讯
1.打开串口。
2.串口处于监听状态
3.想串口写入数据,串口接收到数据返回数据
SerialPort类所在的包一定要和上图包名一直,因为串口通讯需要使用jni中的函数。
package android_serialport_api;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.fx.serialporttest.L;
public class SerialPort {
/*
* Do not remove or rename the field mFd: it is used by native method
* close();
*/
private FileDescriptor mFd;
private FileInputStream mFileInputStream;
private FileOutputStream mFileOutputStream;
/**
* 构造方法
* @param device 串口地址
* @param baurate 波特率
* @param flags
* @throws IOException
* @throws InterruptedException
*/
public SerialPort(File device,int baudrate,int flags) {
/*
* 检测是否有访问权限
*/
if(!device.canRead()||!device.canWrite()){
//如果没有读写权限,尝试chmod命令这个文件
L.tag("没有读写权限");
Process su;
try {
su = Runtime.getRuntime().exec("/system/bin/su");//获取root读写权限
String cmd = "chmod 777"+device.getAbsolutePath()+"\n"+"exit\n";
su.getOutputStream().write(cmd.getBytes()); //向此路径文件写入命令
if((su.waitFor()!=0||!device.canRead()||!device.canWrite())){
throw new SecurityException();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mFd = open(device.getAbsolutePath(),baudrate,flags);
if(mFd==null){
mFd = open(device.getAbsolutePath(),baudrate,flags);
L.tag("native open return null");
}
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
}
public FileInputStream getmFileInputStream() {
return mFileInputStream;
}
public void setmFileInputStream(FileInputStream mFileInputStream) {
this.mFileInputStream = mFileInputStream;
}
public FileOutputStream getmFileOutputStream() {
return mFileOutputStream;
}
public void setmFileOutputStream(FileOutputStream mFileOutputStream) {
this.mFileOutputStream = mFileOutputStream;
}
//JNI
private native static FileDescriptor open(String path,int baudrate,int flags);
public native void close();
static {
System.loadLibrary("serial_port");
}
}
package android_serialport_api;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.fx.serialporttest.L;
public class SerialPortFinger {
private static ReadThread readThread;
private static FileInputStream mFileInputStream;
private static FileOutputStream mFileOutputStream;
static String path = "/dev/ttyS0";//设备主板的串口地址,地址有所不同
public void startListener(){
SerialPort serialPort = new SerialPort(new File(path), 9600, 0);//9600是波特率,这个也是有所不同,具体要看设备
mFileInputStream = serialPort.getmFileInputStream();
mFileOutputStream = serialPort.getmFileOutputStream();//获取串口写入流
readThread = new ReadThread();
readThread.start();//开启监听
}
/**
* 发送指令到串口
*
* @param cmd
* @return
*/
public boolean sendCmds(String cmd) {
boolean result = true;
byte[] mBuffer = (cmd+"\r\n").getBytes();
try {
if (mFileOutputStream != null) {
mFileOutputStream.write(mBuffer);
} else {
result = false;
}
} catch (IOException e) {
e.printStackTrace();
result = false;
}
return result;
}
static class ReadThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
int len;
StringBuffer sb = new StringBuffer("");
while(true){ //循环监听串口,读取返回的数据
byte[] buffer = new byte[1024];
if(mFileInputStream==null){
return;
}
try {
len = mFileInputStream.read(buffer);
if(len>0){
sb.append(new String(buffer, 0, len));
}
if(!sb.toString().equals(""))
{
L.tag(sb.toString());//收到串口的返回数据,在日志中打印出来
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
L.tag("接受完成");
}
}
}
}
② android虚拟机串口通信
工具:Virtual Serial Port Driver.
用这个工具虚拟出一对串口。
下载地址
2.用串口调试助手,测试串口通信。
3.用这个命令启动虚拟机:emulator @2.2 -scale auto -qemu -serial COM3 &
说明:
2.2:是虚拟机的名称。
COM3是你要选择的串口。
ps:在cmd中使用这个命令有两种方式:1)将安卓的sdk的tools文件夹加入到path环境变量中,2)在安卓的sdk的tools文件夹下打开cmd。
4.虚拟机中测试串口通信用谷歌的一个开源项目:android_serialport_api
5.在虚拟机中运行项目。
说明:运行前要获取设备的权限
1)在cmd中用adb shell命令,进入虚拟机命令行环境。
2)打开dev文件夹:cd dev
3)获取权限:chmod 777 ttyS2
6.谷歌的开源项目不能导入进eclipse,我整理了一下,调通了。
③ 求教Android蓝牙串口开发OutputStream发送数据失败的问题
1、首先确保你发送的数据是正确的,串口接收到这个数据后他能识别,并返回你想要的数据,如果你发送的命令本身不要求返回数据,inputstream是读取不到数据的。 2、其次,要确保发送数据的格式正确,比如一段16进制数据,你定义为String="01230545"类型,然后发送的时候out.write(str.getBytes());这样发送的数据是不对的,应该定义一个byte型的数组,然后发送这个数组 3、以上你都确保没问题了,你可以用循环去读取数据,当读到的内容大于0时停止读取。用循环读取你要确保你已经设置读取的超时时间了,不然程序有可能阻塞。
④ Android UART 串口通信
最近有项目需要实现windows机器和Android开发版进行UART串口通信,经过3天查找尝试,特记录一下最终方案,希望之后的同行少走弯路,最后在git上回开源我最终的方案希望大家支持。
Android 3.0.1
Gradle 4.1
ARM开发版 : RK3399
PC机器:Win10
开发机器:MAC 10.13.3
先上图
由于 android-serialport-api 项目中的so使用较old的ndk编译,所以在对于Android 6.0 以上版本兼容的时候会报错 dlopen failed: "has text relocations" 。且使用的mk进行编译,特升级为用cmake编译。
升级 android-serialport-api
项目结构:
app对应原项目中的各个Activity, androidserial 是mole 对应编译之前的so,还有API的封装。可以直接引用androidserial,调用方法参考app目录下的activity。
注意 关于权限!
当接入开发板后如果发现 Error You do not have read/write permission to the serial port 需要root 权限 ,在开发者模式中开启root 权限 adb和应用
使用一下命令开启Android对串口的读写权限
setenforce 0 : 关闭防火墙,有人说关键是这,但是我的环境不用关闭,只要给权限就可以
注意 关于ttyS1 - 6 ttyS1 - 6 对应的是 UART 串口1-6 一般都是一一对应的。这个具体要看一下开发板的说明。
记录的比较糙,还请见谅,如有问题请留言,我看到后肯定回复。项目主要看结构,剩下的都是复制黏贴的事。 git地址:https://github.com/braincs/AndroidSerialLibrary
⑤ android OTA升级会不会导致串口无法打开
你是不是把o t a想成otg,其实安卓系统ota升级就跟电脑在硬盘升级系统一样简单,会改变某些硬件比如手机机存空间,有时你发现你的手机突然间少了一g的存,有时会出问题的都是系统,系统会影响到串口驱动,有时会导致otg连接U盘打开得慢或者识别比较困难,并不会无法打开,当然这是极个别的,出现的问题就把之前的系统直接下载到本机上的内存上再直接降级,要记得双清,像我魅族mx3的flyme3系统识别不了的U盘,在4都可以识别,现在我都升到4.5了,这期间我降级3系统降了两遍只因为得了强迫症以为3系统音质比较好,又发现四的也不错,但是4.5的界面字体又比较美观,所以又升上来了
⑥ Android读串口数据阻塞怎么办
另一设备也是你可以修改开发的吗 弄跳停止命令或者空命令,发下去之后,有特定数据上来给你读,读到之后,就别在读就可以了 再研究研究 PC上的话,好像没遇到阻塞情况,或者真的有数据上来给读,忘记了,USB阻塞倒是遇到过,最后就是弄了个停止命令,这种硬件阻塞的最NB了,蓝屏,各种无法结束进程,呵呵 安卓平台的,不了解 等大神
⑦ android应用程序开发,为串口接收数据创建的子线程问题,急!
找Bug应该要有条理,我们首先不能确定"每次都去执行while(value2 != 1)以外的代码",因为程序执行的很快,可能收发很快,循环每妙执行多少次不确定,而且你的阻塞时间还是0,最好循环内外加上输出判断是不是每次都执行循环体外的代码。
再就是你创建的是两个循环,开头
fd = HardwareControler.openSerialPort("/dev/ttyUSB0", buaterate, 8, 1);
每次读取完数据都会给fd重新赋值, 不确定打开串口是否有应答数据,如果有的话
打开串口->应答数据->有数据,执行第二个循环->读数据->重新第一个循环
这样可能会一直有数据,可把fd = HardwareControler.openSerialPort("/dev/ttyUSB0", buaterate, 8, 1);放到第一个循环外面。
这些只是推测,需要你根据自己代码慢慢调试。
⑧ 串口ReadFile读取数据一直有阻塞,即使有数据上来,该怎么解决
串口同步读写数据,ReadFile会一直阻塞,但是用串口调试助手可以接受到数据。 不过之后再启动程序就正常了,很郁闷,不知道问题出现在哪里,下面把代码贴出来: 以同步方式打开串口: bool CSerialIO::openSerialPort(char* szSerial){HANDLE hSerial=CreateFileA(szSerial, GENERIC_READ|GENERIC_WRITE,0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if(INVALID_HANDLE_VALUE==hSerial) return false; this->hComm=hSerial; memcpy(cComm,szSerial,strlen(szSerial)); cComm[strlen(szSerial)]='\0'; return true;}读串口:unsigned WINAPI RecieveData(void* pProcessData){ProcessData* pPD=(ProcessData*)pProcessData;while(1){if(pPD->bClosePushThread==true) ExitThread(0); byte byteTempBuffer[512]={0}; int iRead=0; if(pPD->pSerialIO->readSerialPort(byteTempBuffer,511,iRead)){if(iRead<=0){Sleep(1000);continue;}else{pPD->critSecData.lock(); pPD->bVectorRawData.insert(pPD->bVectorRawData.end(),byteTempBuffer,byteTempBuffer+iRead); pPD->critSecData.unLock();continue;}}Sleep(1000);}return 0;}这是一个线程入口函数,pPD->pSerialIO->readSerialPort(byteTempBuffer,511,iRead)这句代码实际上就是调用ReadFile来读串口数据,在这里设个断点,每次进入这个线程都会阻塞在这个地方,但是如果我用下串口调试助手后,就不会出现这个问题,也就是说 我要读写的串口必须要先被其他的进程读写过,然后才能正常运行。 ps:不要建议我异步读写串口,因为我现在问题还没解决。不知道是不是还需要对串口的参数进行设置。 再说下重点,我的程序可以正常运行的前提是:程序运行之前,用过串口调试助手之类的,也就是说必须要利用别的程序对串口的参数进行设置我的程序才能正常运行。
⑨ Android读串口数据阻塞怎么办
我这边也在做Android和硬件设备的串口通信。
我的通信方式很简单,我这边发送数据,接收数据(接收数据的内容中有标识位让我判断这次接收到的数据的相应处理动作)
读数据的时候我做的是一个清空的办法,每一次读取数据,如果读到的数据准确则进行处理,如果有误就清空了在读。
如果说接收的数据要对应上发送的数据,你可以在Android这边发送数据后不在发送数据只读取,并开启一个计时器,当这段时间内么有接收到返回值就继续你的发送和读取功能
⑩ 串口通讯接收线程为阻塞方式,怎么关闭串口
另一个线程完全可以运行,是否运行决定权在你。
如果另一个线程需要等待串口的数据,那么它应该调用wait来等待信号量
读取串口数据的线程应该在读取完成后通知等待在信号量上的线程,以继续运行。