前言
最近项目中需要加一个体温检测的模块 需要用到android的串口通信知识点 
遇到的问题
之前没有深入了解过 串口通信 在查询知识点的时候 查到了google的demo Google公司在2011年开源的Google官方源代码 说实话 研究google这个demo 很简单没有什么难度 但是我遇到一个问题
在向串口发送指令后 却收不到串口返回的数据 这个问题我百思不得其解 一直查资料 查到一个和我遇到一样问题的 Android与单片机通过串口通信,收不到返回数据

看到这个答案时 内心是多么的激动 但是这个回答却让我无从下手 找不到切入点
茫茫排错之路 才刚刚开始
在无限翻阅博客的时候 我注意到这样一篇关于 USB转ch340串口 的文章 讲述的是CH340的一个usb转串口模块的知识点 我在查看我手上的这个usb设备时 恰巧也是ch340 我当时就觉得这就是我要的资料 
在仔细研究之后我找到了ch340的生成厂商 南京沁恒微电子官方网址 在他们提供的demo中我成功的打通了Android 串口通过usb传输数据的方法
所以在这里记录一下过程 让遇到的人少走弯路 也加深自己的记忆
实现过程
在官方的demo中我们首先要下载官方提供的jar包 —CH34xUARTDriver.jar jar包及demo下载地址 没有积分的朋友可以留言发邮箱 我看到后 给你发邮箱里
按照观点demo一步一步调试 最后还需要单片机的厂商提供的文档哦 比如这些参数 
CH340DEMO
public class MainActivity extends Activity {
public static final String TAG = "MainActivity";
private static final String ACTION_USB_PERMISSION = "cn.wch.wchusbdriver.USB_PERMISSION";
public readThread handlerThread;
protected final Object ThreadLock = new Object();
private EditText readText;
private EditText writeText;
private Spinner baudSpinner;
private Spinner stopSpinner;
private Spinner dataSpinner;
private Spinner paritySpinner;
private Spinner flowSpinner;
private boolean isOpen;
private Handler handler;
private int retval;
private MainActivity activity;
private Button writeButton, configButton, openButton, clearButton;
public byte[] writeBuffer;
public byte[] readBuffer;
public int actualNumBytes;
public int numBytes;
public byte count;
public int status;
public byte writeIndex = 0;
public byte readIndex = 0;
public int baudRate;
public byte baudRate_byte;
public byte stopBit;
public byte dataBit;
public byte parity;
public byte flowControl;
public boolean isConfiged = false;
public boolean READ_ENABLE = false;
public SharedPreferences sharePrefSettings;
public String act_string;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApp.driver = new CH34xUARTDriver(
(UsbManager) getSystemService(Context.USB_SERVICE), this,
ACTION_USB_PERMISSION);
initUI();
if (!MyApp.driver.UsbFeatureSupported())// 判断系统是否支持USB HOST
{
Dialog dialog = new AlertDialog.Builder(MainActivity.this)
.setTitle("提示")
.setMessage("您的手机不支持USB HOST,请更换其他手机再试!")
.setPositiveButton("确认",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0,
int arg1) {
System.exit(0);
}
}).create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 保持常亮的屏幕的状态
writeBuffer = new byte[512];
readBuffer = new byte[512];
isOpen = false;
configButton.setEnabled(false);
writeButton.setEnabled(false);
activity = this;
//打开流程主要步骤为ResumeUsbList,UartInit
openButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (!isOpen) {
int retval = MyApp.driver.ResumeUsbPermission();
if (retval == 0) {
//Resume usb device list
retval = MyApp.driver.ResumeUsbList();
if (retval == -1)// ResumeUsbList方法用于枚举CH34X设备以及打开相关设备
{
Toast.makeText(MainActivity.this, "Open failed!",
Toast.LENGTH_SHORT).show();
MyApp.driver.CloseDevice();
} else if (retval == 0) {
if (MyApp.driver.mDeviceConnection != null) {
if (!MyApp.driver.UartInit()) {//对串口设备进行初始化操作
Toast.makeText(MainActivity.this, "Initialization failed!",
Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, "Device opened",
Toast.LENGTH_SHORT).show();
isOpen = true;
openButton.setText("关闭");
configButton.setEnabled(true);
writeButton.setEnabled(true);
new readThread().start();//开启读线程读取串口接收的数据
} else {
Toast.makeText(MainActivity.this, "Open failed!",
Toast.LENGTH_SHORT).show();
}
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setIcon(R.mipmap.ic_launcher);
builder.setTitle("未授权限");
builder.setMessage("确认退出吗?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
builder.setNegativeButton("返回", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
builder.show();
}
}
} else {
openButton.setText("Open");
configButton.setEnabled(false);
writeButton.setEnabled(false);
isOpen = false;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MyApp.driver.CloseDevice();
}
}
});
configButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
//配置串口波特率,函数说明可参照编程手册
if (MyApp.driver.SetConfig(baudRate, dataBit, stopBit, parity,flowControl)) {
Toast.makeText(MainActivity.this, "Config successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Config failed!", Toast.LENGTH_SHORT).show();
}
}
});
writeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
byte[] to_send = toByteArray(writeText.getText().toString()); //以16进制发送
// byte[] to_send = toByteArray2(writeText.getText().toString()); //以字符串方式发送
int retval = MyApp.driver.WriteData(to_send, to_send.length);//写数据,第一个参数为需要发送的字节数组,第二个参数为需要发送的字节长度,返回实际发送的字节长度
if (retval < 0)
Toast.makeText(MainActivity.this, "Write failed!", Toast.LENGTH_SHORT).show();
}
});
handler = new Handler() {
public void handleMessage(Message msg) {
// 截取返回值中的体温数据
String num = (String) msg.obj;
Log.e(TAG, "num ------- " + num.replace(" ", ""));
String temp = num.replace(" ", "");
String humidity = temp.substring(12, 16);
//将截取的返回体温数据由16进制转换为10进制
int t = TcnUtility.hexToInt(humidity);
readText.append("体温:" + t);
}
};
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onDestroy() {
isOpen = false;
MyApp.driver.CloseDevice();
super.onDestroy();
}
//处理界面
private void initUI() {
readText = findViewById(R.id.ReadValues);
writeText = findViewById(R.id.WriteValues);
configButton = findViewById(R.id.configButton);
writeButton = findViewById(R.id.WriteButton);
openButton = findViewById(R.id.open_device);
clearButton = findViewById(R.id.clearButton);
baudSpinner = findViewById(R.id.baudRateValue);
ArrayAdapter<CharSequence> baudAdapter = ArrayAdapter
.createFromResource(this, R.array.baud_rate,
R.layout.my_spinner_textview);
baudAdapter.setDropDownViewResource(R.layout.my_spinner_textview);
baudSpinner.setAdapter(baudAdapter);
baudSpinner.setGravity(0x10);
baudSpinner.setSelection(9);
/* by default it is 9600 */
baudRate = 115200;
/* stop bits */
stopSpinner = findViewById(R.id.stopBitValue);
ArrayAdapter<CharSequence> stopAdapter = ArrayAdapter
.createFromResource(this, R.array.stop_bits,
R.layout.my_spinner_textview);
stopAdapter.setDropDownViewResource(R.layout.my_spinner_textview);
stopSpinner.setAdapter(stopAdapter);
stopSpinner.setGravity(0x01);
/* default is stop bit 1 */
stopBit = 1;
/* data bits */
dataSpinner = findViewById(R.id.dataBitValue);
ArrayAdapter<CharSequence> dataAdapter = ArrayAdapter
.createFromResource(this, R.array.data_bits,
R.layout.my_spinner_textview);
dataAdapter.setDropDownViewResource(R.layout.my_spinner_textview);
dataSpinner.setAdapter(dataAdapter);
dataSpinner.setGravity(0x11);
dataSpinner.setSelection(3);
/* default data bit is 8 bit */
dataBit = 8;
/* parity */
paritySpinner = findViewById(R.id.parityValue);
ArrayAdapter<CharSequence> parityAdapter = ArrayAdapter
.createFromResource(this, R.array.parity,
R.layout.my_spinner_textview);
parityAdapter.setDropDownViewResource(R.layout.my_spinner_textview);
paritySpinner.setAdapter(parityAdapter);
paritySpinner.setGravity(0x11);
/* default is none */
parity = 0;
/* flow control */
flowSpinner = findViewById(R.id.flowControlValue);
ArrayAdapter<CharSequence> flowAdapter = ArrayAdapter
.createFromResource(this, R.array.flow_control,
R.layout.my_spinner_textview);
flowAdapter.setDropDownViewResource(R.layout.my_spinner_textview);
flowSpinner.setAdapter(flowAdapter);
flowSpinner.setGravity(0x11);
/* default flow control is is none */
flowControl = 0;
/* set the adapter listeners for baud */
baudSpinner.setOnItemSelectedListener(new MyOnBaudSelectedListener());
/* set the adapter listeners for stop bits */
stopSpinner.setOnItemSelectedListener(new MyOnStopSelectedListener());
/* set the adapter listeners for data bits */
dataSpinner.setOnItemSelectedListener(new MyOnDataSelectedListener());
/* set the adapter listeners for parity */
paritySpinner
.setOnItemSelectedListener(new MyOnParitySelectedListener());
/* set the adapter listeners for flow control */
flowSpinner.setOnItemSelectedListener(new MyOnFlowSelectedListener());
clearButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
readText.setText("");
}
});
return;
}
public class MyOnBaudSelectedListener implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
baudRate = Integer.parseInt(parent.getItemAtPosition(position)
.toString());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
public class MyOnStopSelectedListener implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
stopBit = (byte) Integer.parseInt(parent
.getItemAtPosition(position).toString());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
public class MyOnDataSelectedListener implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
dataBit = (byte) Integer.parseInt(parent
.getItemAtPosition(position).toString());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
public class MyOnParitySelectedListener implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
String parityString = new String(parent.getItemAtPosition(position)
.toString());
if (parityString.compareTo("None") == 0) {
parity = 0;
}
if (parityString.compareTo("Odd") == 0) {
parity = 1;
}
if (parityString.compareTo("Even") == 0) {
parity = 2;
}
if (parityString.compareTo("Mark") == 0) {
parity = 3;
}
if (parityString.compareTo("Space") == 0) {
parity = 4;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
public class MyOnFlowSelectedListener implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
String flowString = new String(parent.getItemAtPosition(position)
.toString());
if (flowString.compareTo("None") == 0) {
flowControl = 0;
}
if (flowString.compareTo("CTS/RTS") == 0) {
flowControl = 1;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
private class readThread extends Thread {
public void run() {
byte[] buffer = new byte[4096];
while (true) {
Message msg = Message.obtain();
if (!isOpen) {
break;
}
int length = MyApp.driver.ReadData(buffer, 4096);
if (length > 0) {
String recv = toHexString(buffer, length); //以16进制输出
// String recv = new String(buffer, 0, length); //以字符串形式输出
msg.obj = recv;
handler.sendMessage(msg);
}
}
}
}
/**
* 将byte[]数组转化为String类型
*
* @param arg 需要转换的byte[]数组
* @param length 需要转换的数组长度
* @return 转换后的String队形
*/
private String toHexString(byte[] arg, int length) {
String result = new String();
if (arg != null) {
for (int i = 0; i < length; i++) {
result = result
+ (Integer.toHexString(
arg[i] < 0 ? arg[i] + 256 : arg[i]).length() == 1 ? "0"
+ Integer.toHexString(arg[i] < 0 ? arg[i] + 256
: arg[i])
: Integer.toHexString(arg[i] < 0 ? arg[i] + 256
: arg[i])) + " ";
}
return result;
}
return "";
}
/**
* 将String转化为byte[]数组
*
* @param arg 需要转换的String对象
* @return 转换后的byte[]数组
*/
private byte[] toByteArray(String arg) {
if (arg != null) {
/* 1.先去除String中的' ',然后将String转换为char数组 */
char[] NewArray = new char[1000];
char[] array = arg.toCharArray();
int length = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] != ' ') {
NewArray[length] = array[i];
length++;
}
}
/* 将char数组中的值转成一个实际的十进制数组 */
int EvenLength = (length % 2 == 0) ? length : length + 1;
if (EvenLength != 0) {
int[] data = new int[EvenLength];
data[EvenLength - 1] = 0;
for (int i = 0; i < length; i++) {
if (NewArray[i] >= '0' && NewArray[i] <= '9') {
data[i] = NewArray[i] - '0';
} else if (NewArray[i] >= 'a' && NewArray[i] <= 'f') {
data[i] = NewArray[i] - 'a' + 10;
} else if (NewArray[i] >= 'A' && NewArray[i] <= 'F') {
data[i] = NewArray[i] - 'A' + 10;
}
}
/* 将 每个char的值每两个组成一个16进制数据 */
byte[] byteArray = new byte[EvenLength / 2];
for (int i = 0; i < EvenLength / 2; i++) {
byteArray[i] = (byte) (data[i * 2] * 16 + data[i * 2 + 1]);
}
return byteArray;
}
}
return new byte[]{};
}
/**
* 将String转化为byte[]数组
*
* @param arg 需要转换的String对象
* @return 转换后的byte[]数组
*/
private byte[] toByteArray2(String arg) {
if (arg != null) {
/* 1.先去除String中的' ',然后将String转换为char数组 */
char[] NewArray = new char[1000];
char[] array = arg.toCharArray();
int length = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] != ' ') {
NewArray[length] = array[i];
length++;
}
}
byte[] byteArray = new byte[length];
for (int i = 0; i < length; i++) {
byteArray[i] = (byte) NewArray[i];
}
return byteArray;
}
return new byte[]{};
}
}
MyApp
public class MyApp extends Application {
// 需要将CH34x的驱动类写在APP类下面,使得帮助类的生命周期与整个应用程序的生命周期是相同的
public static CH34xUARTDriver driver;
}
TcnUtility 进制转换类
package com.app.serialportdemo;
//
//
import java.math.BigInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TcnUtility {
/**
* 十六进制String转bytes
*
* @param hexString
* @return
*/
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
/**
* 把字节数组转换成16进制字符串
*
* @param bArray
* @return
*/
public static String bytesToHexString(byte[] bArray, int byteCount) {
String stmp = "";
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < byteCount; i++) {
stmp = Integer.toHexString(bArray[i] & 0xFF);
sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
}
return sb.toString().toUpperCase().trim();
}
/**
* 十六进制转换字符串
*
* @param (:[616C6B])
* @return String 对应的字符串
*/
public static String hexStr2Str(String hexStr) {
String str = "0123456789ABCDEF";
char[] hexs = hexStr.toCharArray();
byte[] bytes = new byte[hexStr.length() / 2];
int n;
for (int i = 0; i < bytes.length; i++) {
n = str.indexOf(hexs[2 * i]) * 16;
n += str.indexOf(hexs[2 * i + 1]);
bytes[i] = (byte) (n & 0xff);
}
return new String(bytes);
}
//清除无数据byte
public static byte[] byteTrim(byte[] butes) {
int count = getBytesNoNull(butes);
byte[] buf = new byte[count];
for (int i = 0; i < count; i++) {
buf[i] = butes[i];
}
return buf;
}
public static int getBytesNoNull(byte[] bytes) {
int i = 0;
for (; i < bytes.length; i++) {
if (bytes[i] == (byte) 0) {
break;
}
}
return i;
}
/**
* 验证是否正确的手机号码
*
* @param mobile
* @return
*/
public static boolean isMobile(String mobile) {
if (mobile == null) {
return false;
}
Pattern pattern = Pattern.compile("^((\\+86)|(86)|\\(\\+86\\)|\\(86\\))?1[3|4|5|7|8]\\d{9}$");
Matcher matcher = pattern.matcher(mobile);
return matcher.matches();
}
//判断是否是网址
public static boolean isUrl(String url) {
if ((url == null) || (url.trim().equals(""))) {
return false;
}
Pattern p = Pattern.compile("[a-zA-z]+://[^\\s]*");
Matcher m = p.matcher(url);
return m.matches();
}
//判断是否是号码
public static boolean isPhoneNumberValid(String mobiles) {
if ((mobiles == null) || (mobiles.trim().equals(""))) {
return false;
}
if (mobiles.startsWith("+86")) {
mobiles = mobiles.substring(3);
}
if (mobiles.length() != 11) {
return false;
}
// Pattern p = Pattern.compile("^([1][3-9])\\d{9}$");
Pattern p = Pattern.compile("^(0|86|17951)?(13[0-9]|15[012356789]|17[0-9]|18[0-9]|14[57])[0-9]{8}$");
Matcher m = p.matcher(mobiles);
return m.matches();
}
/**
* 计算CRC16校验码
*
* @param bytes
* @return
*/
public static String getCRC(byte[] bytes) {
int CRC = 0x0000ffff;
int POLYNOMIAL = 0x0000a001;
int i, j;
for (i = 0; i < bytes.length; i++) {
CRC ^= ((int) bytes[i] & 0x000000ff);
for (j = 0; j < 8; j++) {
if ((CRC & 0x00000001) != 0) {
CRC >>= 1;
CRC ^= POLYNOMIAL;
} else {
CRC >>= 1;
}
}
}
//高低位转换,看情况使用(譬如本人这次对led彩屏的通讯开发就规定校验码高位在前低位在后,也就不需要转换高低位)
CRC = ((CRC & 0x0000FF00) >> 8) | ((CRC & 0x000000FF) << 8);
return TcnUtility.dese(Integer.toHexString(CRC), 4);
}
/**
* len个字节 补全
*
* @param s
* @return
*/
public static String dese(String s, int len) {
int count = s.length();
count = len - count;
String buf = s;
for (int i = 0; i < count; i++) {
buf = "0" + buf;
}
return buf;
}
static byte[] crc8_tab = {(byte) 0, (byte) 94, (byte) 188, (byte) 226, (byte) 97, (byte) 63, (byte) 221, (byte) 131, (byte) 194, (byte) 156, (byte) 126, (byte) 32, (byte) 163, (byte) 253, (byte) 31, (byte) 65, (byte) 157, (byte) 195, (byte) 33, (byte) 127, (byte) 252, (byte) 162, (byte) 64, (byte) 30, (byte) 95, (byte) 1, (byte) 227, (byte) 189, (byte) 62, (byte) 96, (byte) 130, (byte) 220, (byte) 35, (byte) 125, (byte) 159, (byte) 193, (byte) 66, (byte) 28, (byte) 254, (byte) 160, (byte) 225, (byte) 191, (byte) 93, (byte) 3, (byte) 128, (byte) 222, (byte) 60, (byte) 98, (byte) 190, (byte) 224, (byte) 2, (byte) 92, (byte) 223, (byte) 129, (byte) 99, (byte) 61, (byte) 124, (byte) 34, (byte) 192, (byte) 158, (byte) 29, (byte) 67, (byte) 161, (byte) 255, (byte) 70, (byte) 24,
(byte) 250, (byte) 164, (byte) 39, (byte) 121, (byte) 155, (byte) 197, (byte) 132, (byte) 218, (byte) 56, (byte) 102, (byte) 229, (byte) 187, (byte) 89, (byte) 7, (byte) 219, (byte) 133, (byte) 103, (byte) 57, (byte) 186, (byte) 228, (byte) 6, (byte) 88, (byte) 25, (byte) 71, (byte) 165, (byte) 251, (byte) 120, (byte) 38, (byte) 196, (byte) 154, (byte) 101, (byte) 59, (byte) 217, (byte) 135, (byte) 4, (byte) 90, (byte) 184, (byte) 230, (byte) 167, (byte) 249, (byte) 27, (byte) 69, (byte) 198, (byte) 152, (byte) 122, (byte) 36, (byte) 248, (byte) 166, (byte) 68, (byte) 26, (byte) 153, (byte) 199, (byte) 37, (byte) 123, (byte) 58, (byte) 100, (byte) 134, (byte) 216, (byte) 91, (byte) 5, (byte) 231, (byte) 185, (byte) 140, (byte) 210, (byte) 48, (byte) 110, (byte) 237,
(byte) 179, (byte) 81, (byte) 15, (byte) 78, (byte) 16, (byte) 242, (byte) 172, (byte) 47, (byte) 113, (byte) 147, (byte) 205, (byte) 17, (byte) 79, (byte) 173, (byte) 243, (byte) 112, (byte) 46, (byte) 204, (byte) 146, (byte) 211, (byte) 141, (byte) 111, (byte) 49, (byte) 178, (byte) 236, (byte) 14, (byte) 80, (byte) 175, (byte) 241, (byte) 19, (byte) 77, (byte) 206, (byte) 144, (byte) 114, (byte) 44, (byte) 109, (byte) 51, (byte) 209, (byte) 143, (byte) 12, (byte) 82, (byte) 176, (byte) 238, (byte) 50, (byte) 108, (byte) 142, (byte) 208, (byte) 83, (byte) 13, (byte) 239, (byte) 177, (byte) 240, (byte) 174, (byte) 76, (byte) 18, (byte) 145, (byte) 207, (byte) 45, (byte) 115, (byte) 202, (byte) 148, (byte) 118, (byte) 40, (byte) 171, (byte) 245, (byte) 23, (byte) 73, (byte) 8,
(byte) 86, (byte) 180, (byte) 234, (byte) 105, (byte) 55, (byte) 213, (byte) 139, (byte) 87, (byte) 9, (byte) 235, (byte) 181, (byte) 54, (byte) 104, (byte) 138, (byte) 212, (byte) 149, (byte) 203, (byte) 41, (byte) 119, (byte) 244, (byte) 170, (byte) 72, (byte) 22, (byte) 233, (byte) 183, (byte) 85, (byte) 11, (byte) 136, (byte) 214, (byte) 52, (byte) 106, (byte) 43, (byte) 117, (byte) 151, (byte) 201, (byte) 74, (byte) 20, (byte) 246, (byte) 168, (byte) 116, (byte) 42, (byte) 200, (byte) 150, (byte) 21, (byte) 75, (byte) 169, (byte) 247, (byte) 182, (byte) 232, (byte) 10, (byte) 84, (byte) 215, (byte) 137, (byte) 107, 53};
//获取CRC8校验 血氧
public static String getCRC8(byte[] buf) {
byte ret = 0;
for (int i = 0; i < buf.length; ++i) {
ret = crc8_tab[(0x00ff & (ret ^ buf[i]))];
}
return Integer.toHexString(0x00ff & ret);
}
public static String decodeUnicode(String src) {
StringBuffer tmp = new StringBuffer();
tmp.ensureCapacity(src.length());
int lastPos = 0, pos = 0;
char ch;
src = src.replace("&#x", "%u").replace(";", "");
while (lastPos < src.length()) {
pos = src.indexOf("%", lastPos);
if (pos == lastPos) {
if (src.charAt(pos + 1) == 'u') {
ch = (char) Integer.parseInt(src.substring(pos + 2, pos + 6), 16);
tmp.append(ch);
lastPos = pos + 6;
} else {
ch = (char) Integer.parseInt(src.substring(pos + 1, pos + 3), 16);
tmp.append(ch);
lastPos = pos + 3;
}
} else {
if (pos == -1) {
tmp.append(src.substring(lastPos));
lastPos = src.length();
} else {
tmp.append(src.substring(lastPos, pos));
lastPos = pos;
}
}
}
return tmp.toString();
}
/**
* 把字节数组转换成16进制字符串
*
* @param hexs
* @return
*/
public static int hexToInt(String hexs) {
BigInteger bigint = new BigInteger(hexs, 16);
int value = bigint.intValue();
return value;
}
}
注明
在CH34xUARTDriver.jar 使用方法 我们在项目中的build.gradle 中添加这样一句代码即可
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
通信数据
Android 串口通信之驱动CH340实现和单片机串口通信 我用下面一张图来说明拿到的数据 及使用方法! 我拿到的数据 十六进制 是aaa50901010d014f00f25a55 转十进制后 截取中间的数据位 得到365 按照厂商提供的文档 这个数字除以10 就是我们的正常体温!
啊哈哈哈 不经一番寒彻骨 怎得梅花扑鼻香 太难得了 也算是成功的解决了 Android 串口通信的只能发送 不能接受到结果的问题 

共勉
每天进步一点点 2021 从未停止努力 ~!
|