Reading serial port data on Android systems is a common requirement, especially when we need to communicate with hardware devices. Through open source projectsCrazy-MT/SerialAssistant, we can quickly learn how to implement this feature on Android. The following are detailed steps and code examples to help you better understand and implement serial communication.
1. Determine the serial number and baud rate
1. Find device files
In Linux systems (Android is based on Linux), serial devices are usually represented as /dev/ttySx or /dev/ttyUSBx, where x is a number. For example, /dev/ttyS0 represents the first serial port, and /dev/ttyUSB0 represents the first USB serial port adapter.
2. View available serial ports through the file system
You can use the ls /dev/tty* command in the terminal of your Android device to view available serial device files. Use ADB (Android Debug Bridge) to connect and access device terminals:
adb shell ls /dev/tty*
2. Determine the baud rate
The baud rate is the rate of serial communication, and the unit is baud. Common baud rates are 9600, 19200, 38400, 57600, 115200, etc. The choice of baud rate is usually determined by the specifications or protocols of the serial port device. You need to consult the equipment manual or confirm with the equipment supplier.
3. Read serial port data
After selecting the correct serial port number and baud rate, the serial port data can be read through the input stream. Here is a sample code for reading a thread:
private class ReadThread extends Thread { @Override public void run() { (); while(!isInterrupted()) { try { if (mInputStream == null) return; int size = (tempBuff); if (size > 0){ onDataReceived((tempBuff, 0, size)); } try { (10);//Delay 10ms } catch (InterruptedException e) { (); } } catch (Throwable e) { (); return; } } } }
4. Data packet processing
Taking a certain brand of electronic scales as an example, its data protocol is as follows:
Take the weight 1、initiative/The data format of the passive mode is the same。 2、Advance computer command(HEX): 1b 01 02 3、Data format:(Total 24 byte) 01 02 000.000kg 000.000kg sta X 03 04 Data header net weight Tare weight state check Data tail SHead1 SOH(01H) 1 byte,Title Begins SHead2 STX(02H) 1 byte,Start the text Weight 1 7 byte,net weight。 Weight Units U1U0 2 byte,Units of weight。like“kg” Weight2 7 byte,Tare weight。 Weight Units U1U0 2 byte,Units of weight。like“kg” Status STA 1 byte,state Check Sum BCC 1 byte,use BCC algorithm,remove SOH STX ETX EOT 及本byte外所有字符的 BCC check。 Tail1 ETX(03H) 1 byte,End of title Tail2 EOT(04H) 1 byte,Transmission ends Weight format(net weight/Tare weight),例like: 123.456kg 23.456kg 12.3456kg 0.012kg -12.345kg -1.234kg -0.0001kg (If there is no data in front, fill it with spaces。like果小数点后面有四位,That is accurate 0.1g) state: bit7:1 Weight overflow;0 Normal weight bit6:1 Not reset to zero after booting(There are heavy objects on the weighing plate when the machine is turned on);0 Reset to zero after booting bit5:1 Currently in peeling mode;0 Not currently Peeling mode bit4:1 The current weight is 0;0 The current weight is not 0 bit3:1 Stable weight;0 Unstable weight bit2~bit0 0
In serial communication, processing data packets and ensuring data integrity is an important task. In this blog, we will explore how to use Java to read data through the serial port and make sure that each read data is complete. We will explain how to design a system to process packets, including the logic of packet parsing and verification.
5. Packet parsing class
Define an abstract packet class Packet:
public abstract class Packet { protected byte[] data; public Packet(byte[] data) { = data; } public byte[] getData() { return data; } public abstract String getNetWeight(); public abstract String getTareWeight(); public abstract byte getStatus(); }
Implement specific data analysis class DefaultPacket:
public class DefaultPacket extends Packet { public DefaultPacket(byte[] data) { super(data); } @Override public String getNetWeight() { return new String(data, 2, 7); } @Override public String getTareWeight() { return new String(data, 11, 7); } @Override public byte getStatus() { return data[20]; } public static String parseStatus(byte status) { StringBuilder sb = new StringBuilder(); ("Weight Overflow: ").append((status & 0x80) != 0).append("\n"); ("Not Zeroed on Power-up: ").append((status & 0x40) != 0).append("\n"); ("Tare Mode: ").append((status & 0x20) != 0).append("\n"); ("Weight is Zero: ").append((status & 0x10) != 0).append("\n"); ("Weight Stable: ").append((status & 0x08) != 0).append("\n"); return (); } }
6. Packet parsing interface and implementation class
Define the packet resolution interface PacketParser:
public interface PacketParser { int getDataLength(); boolean isValid(byte[] data); boolean checkChecksum(byte[] data); Packet parse(byte[] data); }
Specific data packet analysis class
DefaultPacketParser implements specific packet parsing and verification logic:
public class DefaultPacketParser implements PacketParser { @Override public int getDataLength() { return 24; } @Override public boolean isValid(byte[] data) { return data[0] == 0x01 && data[1] == 0x02 && data[22] == 0x03 && data[23] == 0x04; } @Override public boolean checkChecksum(byte[] data) { byte checksum = 0; for (int i = 2; i < 21; i++) { checksum ^= data[i]; } return checksum == data[21]; } @Override public Packet parse(byte[] data) { return new DefaultPacket(data); } }
7. Packet input stream class
The PacketInputStream class uses PacketParser to process the parsing and verification of data packets and accumulates invalid data:
import ; import ; import ; import ; import ; public class PacketInputStream extends FilterInputStream { private PacketParser parser; private byte[] buffer; private int bufferPos = 0; private ByteArrayOutputStream byteArrayBuffer = new ByteArrayOutputStream(); public PacketInputStream(InputStream in, PacketParser parser) { super(in); = parser; = new byte[()]; } public Packet readPacket() throws IOException { // Write the remaining invalid data to the buffer if (() > 0) { byte[] invalidData = (); (invalidData, 0, buffer, 0, ); bufferPos = ; (); } while (bufferPos < ()) { int read = (buffer, bufferPos, () - bufferPos); if (read == -1) { return null; // EOF reached } bufferPos += read; } int start = findPacketStart(buffer); while (start == -1 && bufferPos >= 2) { (buffer, 1, buffer, 0, bufferPos - 1); bufferPos--; int read = (buffer, bufferPos, 1); if (read == -1) { return null; // EOF reached } bufferPos += read; start = findPacketStart(buffer); } if (start != 0) { byte[] remainingData = (buffer, start, bufferPos); (remainingData, 0, buffer, 0, ); bufferPos = ; return null; } if (!(buffer)) { (buffer, 0, bufferPos); bufferPos = 0; return null; // Return null means invalid packet } if (!(buffer)) { (buffer, 0, bufferPos); bufferPos = 0; return null; // Return null to indicate verification failure } Packet packet = ((buffer, ())); bufferPos = 0; return packet; } private int findPacketStart(byte[] data) { for (int i = 0; i < - 1; i++) { if (data[i] == 0x01 && data[i + 1] == 0x02) { return i; } } return -1; } }
8. Read thread class
ReadThread uses PacketInputStream and PacketParser to read and process packets:
import ; private class ReadThread extends Thread { private PacketInputStream packetInputStream; public ReadThread(InputStream inputStream, PacketParser parser) { = new PacketInputStream(inputStream, parser); } @Override public void run() { (); while (!isInterrupted()) { try { Packet packet = (); if (packet != null) { if (packet instanceof DefaultPacket) { onDataReceived((DefaultPacket) packet); } } } catch (IOException e) { (); return; } } } private void onDataReceived(DefaultPacket packet) { ("Net Weight: " + ()); ("Tare Weight: " + ()); ("Status: " + (())); } }
Summarize
Through abstract packet analysis logic, we can better handle the integrity of serial packets. We define the packet classes Packet and DefaultPacket, and use the PacketParser interface to implement the parsing and verification of packets. The PacketInputStream class is responsible for handling the read and accumulation of invalid data of data, while ReadThread is responsible for reading and processing valid data packets. This design makes the code more modular, easy to maintain and scale, and can easily adapt to packets in different formats.
The above is the detailed content of the Android operation guide for reading serial port data. For more information about reading serial port data from Android, please pay attention to my other related articles!