Android下的串口通信实战之控制客显
本文为博主原创文章,未经博主允许不得转载。如有问题,请与我联系( QQ:3290985311)朱小姐。
需求:Android下的控制客显(如图)
1、Android下的串口连接
串口:串行接口,通常指COM接口,是采用串行通信方式的扩展接口。电脑端的接口名称一般是COM1或COM2或SCMO1方式命名,Android下的串口名称一般是ttyS0或ttyS1等。串行接口是指数据一位一位地顺序传送,双向通信。
目前,Android下的串口通信,都是在Google的开源项目的基础上实现的。正常情况下直接导入工程就可以了。不过Google提供的工程是使用eclipse开发的项目。
需要注意的是,Google提供的工程已经生成.so文件了。如果想要在自己的项目中使用,就要用NDK生成自己工程的包名对应的.so文件。至于如何生成自己的应用的.so文件,要先配置ndk环境编译。
Google开源项目结构如下
SerialPort.java和SerialPortFinder.java两个文件用于打开、关闭串口和查找串口。
Android.mk文件是用来生成.so文件的配置文件。文件内容如下所示
include $(BUILD_SHARED_LIBRARY):表示生成动态链接库.so文件,文件名的命名格式是lib*.so,*的值就是LOCAL_MODULE的值。
在这个配置文件下,生成的.so文件的名称是libserial_port.so。
LOCAL_SRC_FILES:生成.so文件的源文件。在这个配置文件里,生成.so文件的源文件是SerialPort.c
LOCAL_PATH:是用来查找LOCAL_SRC_FILES指定的文件的路径,是基于当前路径的相对路径。并且这个变量必须放在所有的include $(CLEAR_VARS)的前面,至于为什么一定要放在所有的include $(CLEAR_VARS)的前面,可以参考官方文档的解释。
TARGET_PLATFORM:构建api最低版本
Application.mk文件是描述程序正常运行所需要的模块列表。项目中Application.mk文件内容如下
默认情况下,NDK编译系统会默认生成支持“armeabi” CPU的机器码。在上图Application.mk文件中列出了三种ABI即三种CPU。NDK编译之后,会在lib文件夹下生成指定的ABI文件夹及相应的动态库.so文件。Android下目前支持7中CPU,文件中只列了三种CPU,一个CPU关联一个ABI。Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起)。
gen_SerialPort_h.sh:文件内容如下。意思是将当前工程路径下的src下的android_serialport_api包里的SerialPort文件的.class文件编译成SerialPort.h文件。需要注意的是,使用javah文件需要在cmd命令模式下进入bin文件目录。所以在使用.class文件编译成.h文件要先输入命令 #!/bin/sh
2、如何在自己项目中使用串口通信
流程:使用串口路径和波特率打开串口、传输数据、关闭串口。
a、将Google开源项目中的SerialPort类、SerialPortFinder.java类、Application.java中获取和jni文件夹下的所有文件copy入自己的项目中,
b、通过设置串口路径和波特率打开串口
private SerialPort mSerialPort = null;
mSerialPort = new SerialPort(new File("/dev/ttyS3"), 9600, 0);
public class Sending01010101Activity extends SerialPortActivity {private EditText e1; byte[] mBuffer; byte[] mBuffer1; byte[] mBuffer2; byte[] mBuffer3; SendingThread mSendingThread; String strPrint; public static byte[] byteMerger(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2) { byte[] arrayOfByte = new byte[paramArrayOfByte1.length + paramArrayOfByte2.length]; System.arraycopy(paramArrayOfByte1, 0, arrayOfByte, 0, paramArrayOfByte1.length); System.arraycopy(paramArrayOfByte2, 0, arrayOfByte, paramArrayOfByte1.length, paramArrayOfByte2.length); return arrayOfByte; } public void DisplayData(String paramString, byte[] paramArrayOfByte) { this.mBuffer = new byte[1]; this.mBuffer[0] = 12; SendStr(this.mBuffer); this.mBuffer = new byte[3]; this.mBuffer[0] = 27; this.mBuffer[1] = 115; this.mBuffer[2] = paramArrayOfByte[0]; if (this.mSerialPort != null) SendStr(this.mBuffer); this.mBuffer = new byte[10]; this.mBuffer[0] = 27; this.mBuffer[1] = 81; this.mBuffer[2] = 65; this.mBuffer[3] = 49; this.mBuffer[4] = 50; this.mBuffer[5] = 46; this.mBuffer[6] = 49; this.mBuffer[7] = 13; if (this.mSerialPort == null) return; SendStr(this.mBuffer); } public void SendStr(byte[] paramArrayOfByte) { try { if (this.mOutputStream != null) this.mOutputStream.write(paramArrayOfByte); return; } catch (IOException localIOException) { localIOException.printStackTrace(); } } protected void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(R.layout.sending); e1 = (EditText) findViewById(R.id.e1); ((Button)findViewById(R.id.b1)).setOnClickListener(new View.OnClickListener() {//单价亮 public void onClick(View paramView) { Sending01010101Activity.this.mBuffer = new byte[1]; Sending01010101Activity.this.mBuffer[0] = 49; if (Sending01010101Activity.this.mSerialPort == null) return; Sending01010101Activity.this.DisplayData(e1.getText().toString(), Sending01010101Activity.this.mBuffer); } }); ((Button)findViewById(R.id.b2)).setOnClickListener(new OnClickListener() {//总计亮@Overridepublic void onClick(android.view.View arg0) {// TODO Auto-generated method stub Sending01010101Activity.this.mBuffer = new byte[1]; Sending01010101Activity.this.mBuffer[0] = 50; if (Sending01010101Activity.this.mSerialPort == null) return; Sending01010101Activity.this.DisplayData(e1.getText().toString(), Sending01010101Activity.this.mBuffer);} }); ((Button)findViewById(R.id.b3)).setOnClickListener(new View.OnClickListener() {//收款亮 public void onClick(View paramView) { Sending01010101Activity.this.mBuffer = new byte[1]; Sending01010101Activity.this.mBuffer[0] = 51; if (Sending01010101Activity.this.mSerialPort == null) return; Sending01010101Activity.this.DisplayData(e1.getText().toString(), Sending01010101Activity.this.mBuffer); } }); ((Button)findViewById(R.id.b4)).setOnClickListener(new View.OnClickListener() {//找零亮 public void onClick(View paramView) { Sending01010101Activity.this.mBuffer = new byte[1]; Sending01010101Activity.this.mBuffer[0] = 52; if (Sending01010101Activity.this.mSerialPort == null) return; Sending01010101Activity.this.DisplayData(e1.getText().toString(), Sending01010101Activity.this.mBuffer); } }); ((Button)findViewById(R.id.b5)).setOnClickListener(new View.OnClickListener() {//全灭 public void onClick(View paramView) { Sending01010101Activity.this.mBuffer = new byte[1]; Sending01010101Activity.this.mBuffer[0] = 48; if (Sending01010101Activity.this.mSerialPort != null) Sending01010101Activity.this.DisplayData(e1.getText().toString(), Sending01010101Activity.this.mBuffer); Sending01010101Activity.this.mBuffer = new byte[1]; Sending01010101Activity.this.mBuffer[0] = 12; if (Sending01010101Activity.this.mSerialPort == null) return; Sending01010101Activity.this.SendStr(Sending01010101Activity.this.mBuffer); } }); } protected void onDataReceived(byte[] paramArrayOfByte, int paramInt) { } private class SendingThread extends Thread { private SendingThread() { } public void run() { while (true) { if (isInterrupted()) return; try { if (Sending01010101Activity.this.mOutputStream != null); Sending01010101Activity.this.mOutputStream.write(Sending01010101Activity.this.mBuffer); } catch (IOException localIOException) { localIOException.printStackTrace(); } } } }}
“单价”亮的指令是ESC n 1 这个是ASCII码,转成十进制就是要发送的字节数组是{27,73,49}
“总价”亮的指令是ESC n 2 转成十进制要发送的字节数组就是{27,73,50}
“收款”亮的指令是ESC n 3 转成十进制,{27,73,51}
“找零”亮的指令是ESC n 4 转成十进制{27,73,52}
所有灯全灭的指令是ESC n 0 转成十进制{27,73,48}
d、关闭串口
if (mSerialPort != null) {mSerialPort.close();mSerialPort = null;}
注意:硬件接收的指令是ASCII码值,注意转换。
附上客显指令和ASCII码表对照表
附上本篇文章例子源码demo。源码串口是ttyS1,波特率2400
附上Google开源项目源码
本篇实战篇是串口通信,手机端发送指令给外接设备。但是在文章的开头说过,串口通信是双向的,所以下一篇实战篇
Android下的串口通信实战之电子秤交互
总结:只要是串口连接,对串口的操作都是一样的。不同的硬件之间只有识别的指令不一样,即发送的数据不同。
Google开源地址:
https://code.google.com/archive/p/android-serialport-api/issues
参考文章:
http://blog.csdn.net/u011625768/article/details/53337177
更多相关文章
- Android中的R.java文件你知多少
- 如何给你的Android 安装文件(APK)瘦身(一)
- 在Android使用XML文件控制按钮文字在各种状态下的颜色
- Android中自定义MultipartEntity实现文件上传以及使用Volley库实
- Android串口开发之使用JNI实现ANDROID和串口通信详解
- android http通过post上传文件和提交参数(通过拼装协议)