① 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來等待信號量
讀取串口數據的線程應該在讀取完成後通知等待在信號量上的線程,以繼續運行。