扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
串口通信数据丢失很大一部分原因是:mscomm的inputlen设置设置有问题;
在寻甸等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站设计、成都网站制作 网站设计制作定制制作,公司网站建设,企业网站建设,品牌网站设计,全网整合营销推广,成都外贸网站建设公司,寻甸网站建设费用合理。
解决方案:
mscomm的inputlen设置为0吧(读取整个缓冲区),读完一次,清空一次缓冲区试试;
参考如下:
窗体初始化事件中建议将mscomm的这几个属性做如下设置:
mscomm.inbuffersize=8 '接收缓冲区大小
mscomm.rthreshold=4 '促发oncomm事件的字符数
mscomm.inputlen=0 '默认读取整个缓冲区
mscomm.inputmode=cominputmodetext '以文本方式接收
mscomm.inbuffercount=0 '清空缓冲区
oncomm事件中,建议处理完接收数据后用mscomm.inbuffercount=0清空缓冲区
代码如下:
import com.friendlyarm.AndroidSDK.HardwareControler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class MapGuider_Activity extends Activity{
private int serial_fd=0;
private byte[] serial_RevBuf=new byte[100];
private byte[] serial_SendBuf="fsjajd".getBytes();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.mapguider);
serial_fd=HardwareControler.openSerialPort("/dev/s3c2410_serial1", 115200, 8, 1);
if(serial_fd!=-1)
{
System.out.println("打开串口成功");
HardwareControler.write(serial_fd, serial_SendBuf);
lac_handler.post(RevicePosDataThread);
}
else
{
System.out.println("指定的串口不存在或在其它进程中已被打开");
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
HardwareControler.close(serial_fd);
System.out.println("关闭串口");
lac_handler.removeCallbacks(RevicePosDataThread);
super.onDestroy();
}
Handler lac_handler =new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
Runnable RevicePosDataThread =new Runnable()
{
int err=0;
String s;
public void run() {
// TODO Auto-generated method stub
while(true)
{
//Looper.prepare();
err=HardwareControler.select(serial_fd, 1, 0);
if(err==1)//有数据可读
{
HardwareControler.read(serial_fd, serial_RevBuf, 10);
s=new String(serial_RevBuf);
System.out.println("接收到串口数据"+s);
}
else if(err==0) //无数据可读
{
System.out.println("没有接收到串口数据");
}
else //出错
{
System.out.println("接收到串口数据出错");
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
}
最近有项目需要实现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 是module 对应编译之前的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地址:
如下表不同操作系统的串口地址,Android是基于Linux的所以一般情况下使用Android系统的设备串口地址为/dev/ttyS0...
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(len0){
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("接受完成");
}
}
}
}
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流