惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Exploit Database - CXSecurity.com
F
Fortinet All Blogs
U
Unit 42
F
Full Disclosure
雷峰网
雷峰网
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
罗磊的独立博客
D
DataBreaches.Net
C
Check Point Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
O
OpenAI News
C
CXSECURITY Database RSS Feed - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
S
Security @ Cisco Blogs
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Hacker News
The Hacker News
Webroot Blog
Webroot Blog
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
N
News | PayPal Newsroom
P
Proofpoint News Feed
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
Google Online Security Blog
Google Online Security Blog
H
Help Net Security
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
M
MIT News - Artificial intelligence
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
MyScale Blog
MyScale Blog
腾讯CDC

博客园 - 简单飞扬-

vim个人配置 Docker 开发线程安全的Spring Web应用(转) 1 游戏外挂原理和技术分析(关于魔力宝贝) 关于java使用javacomm20-win32实践总结 (转) 有几件事情 C#开发ActiveX可行性研究 动态编译 利用Java动态编译计算数学表达式 - 简单飞扬- - 博客园 mysql存储过程学习及java调用存储过程 将数据库操作封装MAP 宁静 会一直存在么 java 项目中遇到的错误 toncat配置文件 - 简单飞扬- - 博客园 struts分页 - 简单飞扬- - 博客园 用户中心 - 博客园 自动递归删除 数据库连接
Java 串口编程
简单飞扬- · 2009-03-23 · via 博客园 - 简单飞扬-

Javax.comm简介
    Javax.comm是Sun公司提供的,用于开发平台独立的通讯应用程序的扩展API。(ps:这里javax的x很准确地表明了它是一个扩展包,而不是核心包(core package),但由于历史原因,javax下的并不都是扩展包,比如swing包已经是Java核心架构的一部分了,不过为了与Java1.1编码兼容,仍使用javax.swing。)javax.comm可以访问RS232接口(串口)及有限制地访问IEEE-1284(并口)。

下载
    http://mdubuc.freeshell.org/Jolt/javacomm20-win32.zip和(完整的2.0版本,还有 examples)。

安装
    这里的所谓安装就是把三个重要的文件放到指定的目录下。In summary it says:
     comm.jar                     should go in the ..\jre\lib\ext folder
     javax.comm.properties  should go in the ..\jre\lib folder

     win32comm.dll              should go in c:\windows folder (I put it in c:\WINNT folder in my case.)

API
在javax.comm下有13个类和接口,分别是

4个接口
CommDriver 可负载设备(the loadable device)驱动程序接口的一部分
CommPortOwnershipListener 传递各种通讯端口的所有权事件
ParallelPortEventListener 传递并行端口事件
SerialPortEventListener 传递串行端口事件

6个类
CommPort 通讯端口
CommPortIdentifier通讯端口管理
ParallelPort 并行通讯端口
ParallelPortEvent 并行端口事件
SerialPort RS-232串行通讯端口
SerialPortEvent 串行端口事件

3个异常类
NoSuchPortException 当驱动程序不能找到指定端口时抛出
PortInUseException 当碰到指定端口正在使用中时抛出
UnsupportedCommOperationException 驱动程序不允许指定操作时抛出

实例
    同API一起下载的还有一个examples文件,里面有6个程序。首先看最简单的读、写程序。

读串口的例程
import java.io.*;
import java.util.*;
import javax.comm.*;

public class SimpleRead implements Runnable, SerialPortEventListener {

    static CommPortIdentifier portId;
    static Enumeration portList;//枚举类

    InputStream inputStream;
    SerialPort serialPort;
    Thread readThread;

    public static void main(String[] args) {

        portList = CommPortIdentifier.getPortIdentifiers();/*不带参数的getPortIdentifiers方法获得一个枚举对象,该对象又包含了系统中管理每个端口的CommPortIdentifier对象。注意这里的端口不仅仅是指串口,也包括并口。这个方法还可以带参数。getPortIdentifiers(CommPort)获得与已经被应用程序打开的端口相对应的CommPortIdentifier对象。 getPortIdentifier(String portName)获取指定端口名(比如“COM1”)的CommPortIdentifier对象。*/

        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)/*getPortType方法返回端口类型*/ {
                // if (portId.getName().equals("COM1"))/* 找Windows下的第一个串口*/ {
                if (portId.getName().equals("/dev/term/a"))/*找Unix-like系统下的第一个串口*/ {
                    SimpleRead reader = new SimpleRead();
                }
            }
        }
    }

    public SimpleRead() {
        try {
            serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);/* open方法打开通讯端口,获得一个CommPort对象。它使程序独占端口。如果端口正被其他应用程序占用,将使用 CommPortOwnershipListener事件机制,传递一个PORT_OWNERSHIP_REQUESTED事件。每个端口都关联一个 InputStream 何一个OutputStream。如果端口是用open方法打开的,那么任何的getInputStream都将返回相同的数据流对象,除非有close 被调用。有两个参数,第一个为应用程序名;第二个参数是在端口打开时阻塞等待的毫秒数。*/
        } catch (PortInUseException e) {}
        try {
            inputStream = serialPort.getInputStream();/*获取端口的输入流对象*/
        } catch (IOException e) {}
    try {
            serialPort.addEventListener(this);/*注册一个SerialPortEventListener事件来监听串口事件*/
    } catch (TooManyListenersException e) {}

        serialPort.notifyOnDataAvailable(true);/*数据可用*/

        try {
            serialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);/*设置串口初始化参数,依次是波特率,数据位,停止位和校验*/
        } catch (UnsupportedCommOperationException e) {}

        readThread = new Thread(this);
        readThread.start();
    }

    public void run() {
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {}
    }

//串口事件
    public void serialEvent(SerialPortEvent event) {

        switch(event.getEventType()) {
        case SerialPortEvent.BI:/*Break interrupt,通讯中断*/
        case SerialPortEvent.OE:/*Overrun error,溢位错误*/
        case SerialPortEvent.FE:/*Framing error,传帧错误*/
        case SerialPortEvent.PE:/*Parity error,校验错误*/
        case SerialPortEvent.CD:/*Carrier detect,载波检测*/
        case SerialPortEvent.CTS:/*Clear to send,清除发送*/
        case SerialPortEvent.DSR:/*Data set ready,数据设备就绪*/
        case SerialPortEvent.RI:/*Ring indicator,响铃指示*/
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty,输出缓冲区清空*/
            break;

        case SerialPortEvent.DATA_AVAILABLE:/*Data available at the serial port,端口有可用数据。读到缓冲数组,输出到终端*/
            byte[] readBuffer = new byte[20];

            try {
                while (inputStream.available() > 0) {
                    int numBytes = inputStream.read(readBuffer);
                }
                System.out.print(new String(readBuffer));
            } catch (IOException e) {}
            break;
        }
    }
}
(PS:不推荐Thread的这种用法,详见《Core Java VolumeII》)

写串口的例程
    把字符串"Hello, world!\n"写到系统的第一个串口

import java.io.*;
import java.util.*;
import javax.comm.*;

public class SimpleWrite {
    static Enumeration portList;
    static CommPortIdentifier portId;
    static String messageString = "Hello, world!\n";
    static SerialPort serialPort;
    static OutputStream outputStream;

    public static void main(String[] args) {
        portList = CommPortIdentifier.getPortIdentifiers();

        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                // if (portId.getName().equals("COM1")) {
                if (portId.getName().equals("/dev/term/a")) {
                    try {
                        serialPort = (SerialPort)
                            portId.open("SimpleWriteApp", 2000);
                    } catch (PortInUseException e) {}
                    try {
                        outputStream = serialPort.getOutputStream();
                    } catch (IOException e) {}
                    try {
                        serialPort.setSerialPortParams(9600,
                            SerialPort.DATABITS_8,
                            SerialPort.STOPBITS_1,
                            SerialPort.PARITY_NONE);
                    } catch (UnsupportedCommOperationException e) {}
                    try {
                        outputStream.write(messageString.getBytes());
                    } catch (IOException e) {}
                }
            }
        }
    }
}

    上面两个例程都经过了简化,在打开端口,并且传输结束后没有关闭数据流和串口。在例程中我们看到CommPortIdentifier提供了打开通讯端口的方法open,但却没有相应关闭端口的方法,关闭端口需要调用javax.comm.CommPort类的close()。CommPort是这个包中的一个高级抽象,它定义了端口可作的各种事情:获取I/O数据流对象,控制缓冲区大小,调整输入的处理