目录

第1章串行通讯之UARTLoopback    2

1 USB转串口    2

2 USB Accessory    2

3 连入手机    3

4 代码改进    4

5 打开串口    4

6 写串口数据    4

7 主动读取串口数据    5

8 被动读取串口数据    5

9 关闭串口    6

第1章串行通讯之UARTLoopback

1 USB转串口

这两天在做Android手机上的串行通讯程序。手机没有串口,所以使用了USB转串口,如下图所示:

图1 USB转串口

上图中,红色的USB A型插头用来给此设备供电;黑色的Micro USB插头用来连接Android手机;粉红色的9针插头用来连接串口设备。

购买此产品时,附带了Java源代码,也就是工程UARTLoopback。本文对其进行说明及改进。

2 USB Accessory

USB设备分为两大类:USB Host、USB Accessory(USB 附件)。USB键盘、鼠标连入手机后,由手机给其供电,它们属于USB Host;上面的USB转串口连入手机后,会给自己、手机供电,它属于USB Accessory。

查看UARTLoopback的代码可知:访问USB转串口的实质是访问USB Accessory。

关于USB Accessory的更多信息请参考如下博客:

http://blog.csdn.net/yingzhao80/article/details/45511351

3 连入手机

Android 手机上安装UARTLoopbackActivity.apk后,将USB转串口接入手机,就会弹出如下界面:

图2

这是如何实现的呢?请查看UARTLoopback的AndroidManifest.xml文件。下面是精简后的内容,重点是红色字体部分:

... ... ...

<uses-feature android:name="android.hardware.usb.accessory"/>

... ... ...

<intent-filter>

<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"/>

</intent-filter>

<meta-data

android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"

android:resource="@xml/accessory_filter">

</meta-data>

... ... ...

4 代码改进

串行通讯的核心类就是FT311UARTInterface,笔者对其进行了改进。改进版的下载网址为:http://download.csdn.net/detail/hanford/9686781

下文的说明以改进版为准。

5 打开串口

打开串口的代码如下

com.UARTLoopback.FT311UARTInterface m_Comm = new com.UARTLoopback.FT311UARTInterface(this);

if(m_Comm.open(9600,'N',8,1,0))

{//成功打开串口

}

else if(m_Comm.isExist())

{//打开串口失败,可能是权限不够,申请权限

m_Comm.requestPermission();

}

else

{//说明手机未连接USB转串口

}

m_Comm.open 用来打开串口

m_Comm.isExist 用来判断USB转串口是否已经插入手机

m_Comm.requestPermission 用来申请权限

打开串口的时候就设置通讯参数,为什么这么设计呢?因为:从USB转串口插入手机到拔出手机这段时间内,只能配置一次通讯参数。

6 写串口数据

请参考下面的代码

if(m_Comm.isOpen()) {

byte[] data = m_txtSend.getText().toString().getBytes();

m_Comm.write(data,data.length);

}

m_Comm.isOpen 判断串口是否已经打开

m_txtSend.getText().toString().getBytes() 获取文本框m_txtSend内的文本,然后转换为二进制数据

m_Comm.write 发送二进制数据

7 主动读取串口数据

请参考下面的代码

if(m_Comm.isOpen()) {

byte[] data = new byte[1024];

int nRead=m_Comm.read(data, data.length);

try {

m_txtRecv.setText(new String(data, 0, nRead, "UTF-8"));

} catch (UnsupportedEncodingException ex) {

}

}

m_Comm.read用来读取串口数据,返回读取到的字节数。接下来的代码,将读取到的二进制数据转换为字符串,并显示到文本框m_txtRecv里。

8 被动读取串口数据

被动读取串口数据,就是一旦获得了串口数据就通知程序。其代码有点多:

m_Comm.setEventDataReceived(m_EventDataReceived);

com.UARTLoopback.FT311UARTInterface.EventDataReceived m_EventDataReceived = new com.UARTLoopback.FT311UARTInterface.EventDataReceived(){

public void onEvent(byte[] data,int nBytes)

{//接收到串口数据,就调用此函数

try {

m_sRecv += new String(data, 0, nBytes, "UTF-8");

} catch (UnsupportedEncodingException ex) {

}

m_Handler.sendEmptyMessage(1); //更新界面显示

}

};

private Handler m_Handler = new Handler() {

public void handleMessage(Message msg) {

switch (msg.what) {

case 1: m_txtRecv.setText(m_sRecv); break;

}

super.handleMessage(msg);

}

};

代码m_Comm.setEventDataReceived(m_EventDataReceived);表示一旦接收到串口数据,马上调用m_EventDataReceived对象的onEvent函数。

onEvent函数中,将串口数据(保存在数组byte[] data里,字节数为 nBytes)转换为文本,然后加到字符串变量m_sRecv的右边。

因为onEvent函数不在主线程里,所以需要代码m_Handler.sendEmptyMessage(1);通知m_Handler更新主界面。其实就是handleMessage函数中的m_txtRecv.setText(m_sRecv)被执行。

总结:

1)m_Comm.setEventDataReceived指定事件处理对象,一旦读取到串口数据,将调用该对象的onEvent函数;

2)onEvent函数是被多线程调用的,更新主界面请使用Handler、sendEmptyMessage;

3)如果m_Comm.setEventDataReceived的参数不是null,那么就无法主动读取串口数据了。也就是说,此时m_Comm.read始终返回0。

9 关闭串口

关闭串口的代码很简单,如下所示:

m_Comm.close();

不过,它的问题最严重:

调用上述代码,读取串口数据的线程(FT311UARTInterface.ThreadRead.run)将被阻塞在如下代码行:

nRead = FileInputStream_read(m_InputStream,data,data.length);

上面的代码调用了FileInputStream.read函数,这是一个同步函数——没有读取到串口数据,就不会返回。这个时候,如果串口设备发送过来数据,线程将正常退出;如果串口设备一直未发送数据过来,那么这个线程将永远阻塞在这一行上。

线程ThreadRead阻塞后,m_Comm.open将无法再打开串口。解决办法就是:拔下USB转串口,重新插入。

总结:关闭串口会极大概率的导致一个僵尸线程的产生,不够完美的解决办法就是重新拔、插USB转串口。

串行通讯之UARTLoopback的更多相关文章

  1. 【Arduino】使用C#实现Arduino与电脑进行串行通讯

    在给Arduino编程的时候,因为没有调试工具,经常要通过使用串口通讯的方式调用Serial.print和Serial.println输出Arduino运行过程中的相关信息,然后在电脑上用Arduin ...

  2. 串行通讯之.NET SerialPort

    第1章串行通讯之.NET SerialPort    2 1 枚举串口    2 2 打开/关闭串口    2 3 写数据    3 3.1 写二进制数据    3 3.2 写文本数据    4 4 ...

  3. 串行通讯之Qt

    目录 第1章 Qt 串行通讯    1 1.1 配置.pro文件    1 1.2 查询串口信息    1 1.3 配置.打开串口    3 1.4 setRequestToSend在Windows上 ...

  4. COM口,串行通讯端口,RS-232接口 基础知识

    COM口即串行通讯端口. COM口的接口标准规范和总线标准规范是RS-232,有时候也叫做RS-232口.电脑上的com口多为9针,最大速率115200bps.通常用于连接鼠标(串口)及通讯设备(如连 ...

  5. STM32L476应用开发之三:串行通讯实验

    在我们的项目需求中,有两个串口应用需求,一个是与炭氢传感器的通讯,另一个是与显示屏的通讯.鉴于此,我们需要实验串行通讯. 1.硬件设计 串行通讯一个采用RS232接口,另一个直接采用TTL方式.我们在 ...

  6. 基于51的串行通讯原理及协议详解(uart)

    串行与并行通讯方式并行:控制简单,传输速度快.线多,长距离成本较高且同时接受困难.串行:将数据字节分成一位一位的行驶在一条传输线上进行传输.如图:   同步与异步串行通讯方式同步串行通讯方式:同步通讯 ...

  7. STM32学习笔记——SPI串行通讯(向原子哥学习)

    一.SPI  简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在  EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...

  8. boost库在工作(40)串行通讯

    现代的计算机技术进步很快,各种的通讯也日新月异,像USB.网络.蓝牙.WIFI等通讯技术飞速地出现,改变了整个计算机的通讯能力,速度已经达到GBit级别.但是有一种最原始的通讯方式,还是保留了30年, ...

  9. 串行通讯协议--起止式异步通讯协议(UART)

    起止式异步通讯协议: 特点与格式: 起止式异步协议的特点是一个字符一个字符传输,并且传送一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求.其格式如图3 所示.每一个字符的前面都有 ...

随机推荐

  1. reactjs入门到实战(七)---- React的组件的生命周期

    React的组件的生命周期有三个状态分别是:挂载(生产组件示例化.准备挂载到页面.挂载到页面).更新(更新值.更新DOM).和卸载(卸载后). >>>其他     getInitia ...

  2. 为Python添加默认模块搜索路径

    方法一:函数添加1 import sys2 查看sys.path3 添加sys.path.append("c:\\") 方法二:修改环境变量w用户可以修改系统环境变量PYTHONP ...

  3. MUI 页面传值 webview

    我们假设a.html 和b.html a.html 页面代码 <!DOCTYPE html> <html> <head> <meta charset=&quo ...

  4. ldataset 与 list 的使用

    [WebMethod(Description = @"根据时间查询会议项目[时间格式为:2014-01-01] DateTime StartTime , DateTime Endtime & ...

  5. stm32中断服务函数

    你打开stm32的启动文件,例如startup_stm32f10x_hd.s 里面有很多中断跳转的入口.用白话说就是固件库帮你写好了发生什么中断时跳转到哪里,这些名字是一个函数名,你要把这些函数写出来 ...

  6. 单片机特殊功能寄存器(SFR)

    单片机如8051有21个SFR,地址为80H~0FFH的128个字节中,可以直接用寻址方式来操作SFR.(类似于sbit) 为了能直接访问这些SFR,keil提供饿了一种自汉族形式的定义方法.这种方法 ...

  7. WINCE6.0组件选择说明

    WINCE6.0组件选择说明 图1 RAS/PPP组件前面的√标识表示我们手动选择,TAPI2.0前面的■标识表示选组件时根据依赖关系自动选择的,PPPoE前面的□标识组件没有选择.

  8. mysql中bigint、int、mediumint、smallint 和 tinyint的取值范围

    mysql数据库设计,其中,对于数据性能优化,字段类型考虑很重要,搜集了些资料,整理分享出来,这篇为有关mysql整型bigint.int.mediumint.smallint 和 tinyint的语 ...

  9. word 与 endnote 反应慢的小技巧

    使用Word 2007/2010打开含有EndNote标注的文档时,Word反应速度会变慢,甚至出现“假死”状态,要等很长时间才能正常工作.问题出在Word的校正功能上,Word会对EndNote的标 ...

  10. BerkeleyDB 多索引查询

    由于性能原因,我们打算将关系型数据库转移到内存数据库中:在内存数据库产品的选型中,我们确定的候选对象有Redis和Berkeley DB: Redis查询效率不错,并且支持丰富的数据存储结构,但不支持 ...