开始学android,在串口上卡了十几个小时后靠GitHub解放了我。
首先是这个库:
https://github.com/mik3y/usb-serial-for-android
按照大佬的指示,第一步添加库引用:
Add jitpack.io repository to your root build.gradle:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Add library to dependencies
dependencies {
implementation 'com.github.mik3y:usb-serial-for-android:3.4.2'
}
使用新版android studio的时候要注意,
maven { url 'https://jitpack.io' }
这段代码要放在setting.gradle里面。。。不然会报错说找不到。
第二步添加程序读写USB的权限。在自己的AndroidManifest.xml里面加如下内容。
<activity
android:name="..."
...>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
然后在studio中新建device_filter.xml文件,如下图
第三步,开始写代码
代码很简单,两按钮,一个打开串口一个关闭串口。打开串口后根据协议读温度显示在TextView上。串口七合一空气采样模块的说明和购买链接见https://item.taobao.com/item.htm?spm=a230r.1.14.24.61c02c16A0NTtD&id=568535232415&ns=1&abbucket=3#detail。
public class MainActivity extends AppCompatActivity {
UsbSerialPort port;
SerialInputOutputManager usbio;
ArrayList<Byte> buffer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_openport=(Button) this.findViewById(R.id.open_port);
TextView tx=(TextView) this.findViewById(R.id.serial_data);
btn_openport.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
if (availableDrivers.isEmpty()) {
return;
}
// Open a connection to the first available driver.
UsbSerialDriver driver = availableDrivers.get(0);
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
if (connection == null) {
// add UsbManager.requestPermission(driver.getDevice(), ..) handling here
return;
}
port = driver.getPorts().get(0); // Most devices have just one port (port 0)
try{
port.open(connection);
port.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
Log.i("port","open success");
buffer=new ArrayList<Byte>();
usbio=new SerialInputOutputManager(port, new SerialInputOutputManager.Listener() {
@Override
public void onNewData(byte[] data) {
Log.i("port read size",String.valueOf(data.length));
if(data.length>0){
for(int i=0;i<data.length;i++){
buffer.add(data[i]);
Log.i("port read",String.valueOf(data[i]));
}
if(buffer.size()>=17){
for(int i=0;i<buffer.size();i++){
if(buffer.get(i)==0x3c && buffer.get(i+1)==0x02 && (i+17)<=buffer.size()){
Log.i("tmp",String.valueOf(buffer.get(i+12)));
String temp=String.valueOf(buffer.get(i+12))+"."+String.valueOf(buffer.get(i+13));
runOnUiThread(() -> {tx.setText(temp);});//把温度显示在UI上,中断函数不允许操作UI,所以要另开一个线程
buffer.clear();
}
}
}
}
}
@Override
public void onRunError(Exception e) {
}
});
usbio.start();
}
catch (IOException e){
}
}
});
Button btn_closeport=(Button) this.findViewById(R.id.close_port);
btn_closeport.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try{
usbio.stop();
port.close();
Log.i("port","close port");
}
catch (IOException e){
}
}
});
}
}
需要注意的就是onNewData基本上每来1个字节就触发一次,因为9600的波特率太低了,1ms来一个字节。。。所以需要自己维护一个数组或者队列,当数组或队列的长度足够大且检测到有一串完整协议数据的时候读出温度值 。
|