串行通讯之UARTLoopback
目录
第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的更多相关文章
- 【Arduino】使用C#实现Arduino与电脑进行串行通讯
在给Arduino编程的时候,因为没有调试工具,经常要通过使用串口通讯的方式调用Serial.print和Serial.println输出Arduino运行过程中的相关信息,然后在电脑上用Arduin ...
- 串行通讯之.NET SerialPort
第1章串行通讯之.NET SerialPort 2 1 枚举串口 2 2 打开/关闭串口 2 3 写数据 3 3.1 写二进制数据 3 3.2 写文本数据 4 4 ...
- 串行通讯之Qt
目录 第1章 Qt 串行通讯 1 1.1 配置.pro文件 1 1.2 查询串口信息 1 1.3 配置.打开串口 3 1.4 setRequestToSend在Windows上 ...
- COM口,串行通讯端口,RS-232接口 基础知识
COM口即串行通讯端口. COM口的接口标准规范和总线标准规范是RS-232,有时候也叫做RS-232口.电脑上的com口多为9针,最大速率115200bps.通常用于连接鼠标(串口)及通讯设备(如连 ...
- STM32L476应用开发之三:串行通讯实验
在我们的项目需求中,有两个串口应用需求,一个是与炭氢传感器的通讯,另一个是与显示屏的通讯.鉴于此,我们需要实验串行通讯. 1.硬件设计 串行通讯一个采用RS232接口,另一个直接采用TTL方式.我们在 ...
- 基于51的串行通讯原理及协议详解(uart)
串行与并行通讯方式并行:控制简单,传输速度快.线多,长距离成本较高且同时接受困难.串行:将数据字节分成一位一位的行驶在一条传输线上进行传输.如图: 同步与异步串行通讯方式同步串行通讯方式:同步通讯 ...
- STM32学习笔记——SPI串行通讯(向原子哥学习)
一.SPI 简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在 EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...
- boost库在工作(40)串行通讯
现代的计算机技术进步很快,各种的通讯也日新月异,像USB.网络.蓝牙.WIFI等通讯技术飞速地出现,改变了整个计算机的通讯能力,速度已经达到GBit级别.但是有一种最原始的通讯方式,还是保留了30年, ...
- 串行通讯协议--起止式异步通讯协议(UART)
起止式异步通讯协议: 特点与格式: 起止式异步协议的特点是一个字符一个字符传输,并且传送一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求.其格式如图3 所示.每一个字符的前面都有 ...
随机推荐
- Android中XML解析
package com.example.thebroadproject; public class Book { private int id; private String name; privat ...
- 15款开源PHP类库
PHP库给开发者提供了一个标准接口,它帮助开发者在PHP里充分利用面向对象编程.这些库为特定类型的内置功能提供了一个标准的API,允许类可以与PHP引擎进行无缝的交互.此外,开发者使用这些类库还可以简 ...
- SqlSever基础 rtrim函数 除去字符串的右边的空格,左边中间的不管
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- 异常详细信息: System.Web.Hosting.HostingEnvironmentException: 访问 IIS 元数据库失败 解决方法
访问IIS元数据库失败 同理,给操作系统的新建用户赋予IIS操作权限同样可以采用该命令来处理 说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错 ...
- .Net母版页
母版页:MasterPage 母版页不是独立的,它是与用户控件一起来使页面结构更加优化. 从粗到细,逐步细化各级页面的模板结构.到页面中只需完善其不同之处即可,相同之处都放在各级母版页中实现了. We ...
- 主框架搭建demo
- (void)viewDidLoad { [super viewDidLoad]; [self setUpAllChildViewController]; } /** ...
- ps aux 查看进程信息
[root@localhost Desktop]# ps auxUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.3 ...
- NPO与X7R、X5R、Y5V、Z5U神马的有啥区别
主要是介质材料不同.不同介质种类由于它的主要极化类型不一样,其对电场变化的响应速度和极化率亦不一样. 在相同的体积下的容量就不同,随之带来的电容器的介质损耗.容量稳定性等也就不同.介质材料划按容量的温 ...
- Photoshop CS6 快捷键
1.工具箱 移动工具 [V]矩形.椭圆选框工具 [M]套索.多边形套索.磁性套索 [L]快速选择工具.魔棒工具 [W] 裁剪.透视裁剪.切片.切片选择工具 [C]吸管.颜色取样器.标尺.注释.12 ...
- Codeforces Round #237 (Div. 2) B题模拟题
链接:http://codeforces.com/contest/404/problem/B B. Marathon time limit per test 1 second memory limit ...