一、实验目的
(1)了解串口的通信方式。
(2)掌握串口通信的原理,了解串口通信的编程的初步概念和相应函数,掌握一个具体开
发平台下的串口编程。
二、实验内容
这一部分将是我们的重点,要与串口通信首先要在项目添加RXTXcomm.jar包(放在项目中的lib目录下,并添加到build Path中);
另外,还需要将解压后的rxtxParallel.dll和rxtxSerial.dll两个文件放在%JAVA_HOME%/jre/bin目录下,这样该包才能被正常的加载和调用。
由于笔记本或台式机上基本上都没有成对的串口提供给我们调试使用,我们就需要下载虚拟串口软件来实现串口调试。
- 下载虚拟串口软件。
- 打开软件添加虚拟串口vspd,一般都是成对添加的(添加COM6、COM9)
- 添加完成后到设备管理器中查看,发现多了两个虚拟串口
- 下载串口调试软件sscom32
- 可以直接先打开两个调试窗口,分别用来表示COM6和COM9串口。两个串口的参数一定要设置的一样才可以正常的收发数据。(若调试可以正常收发数据后,可以关掉一个调试器,而用java程序代替)
三、实验结果及分析
串口通信在很多地方都要用到,特别是嵌入式开发、短信模块开发以及为各种硬件产品定制软件等都需要用到。
其中最经常用的通信协议为RS-232通信协议,要想成为真正的串口通信开发高手就需要全面的了解串口的通信协议(本人还是菜鸟一枚。。。希望高手指点)。
串口通信的另一个重点在于接收到数据后,如何判断数据的类型以及有效数据的提取等,这些都需要根据相应的协议进行代码编写。
四、实验小结、问题讨论
(1)串口有两种
1.PC上的COM口
COM口即串行通讯端口。微机上的com口多为9针,最大速率115200bps。
通常用于连接鼠标(串口)及通讯设备(如连接外置式MODEM进行数据通讯)等。
但目前主流的主板一般都只带1个串口,甚至不带。
机箱后面,梯形的,两排,一排5个孔,一排4个孔
一般有两个,就是com1 com2,背板上应该都标明的
反正要么上1下2,要么左1右2
可以转接USB
2.设备上的Serial口
专为广域网设计,它可以做ISDN,PPP,帧中继等网络类型的连接可以接很多网络类型,要使用它必须设置时钟频率(DCE、DTE),路由表的算法也在此接口上形成。
以太网口是对局域网内的,它只有拥有局域网所需要的所有功能。
没有广域网接口所需要的功能,而广域网串口也没有局域网以太网口接口的功能,所以两个接口是不能对调的。
路由器连接路由器就要用路由器上的Serial端口连接,不过现在的路由器都没有这些,都用光口代替了。
ethernet口:以太网口,现在可以说是百兆口,交换机间连在一起用的。
以太口(eth)是接RJ45水晶头的,串口(ser) 是远距离连接 使用的!可以是电缆也可以是光纤!
串口是串行口通讯协议,以太网口是以太网通讯协议。
(2)
- 读出寄存器数据
- 将读出的数据转换成可计算的数据类型(两个char类型转换成一个short或int或float类型)
- 根据公式计算
根据公式计算
不用union的函数也可以用sprintf实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | package com.test; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.TooManyListenersException; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; /** * @项目名称 :DSerialPort * @文件名称 :SerialPort.java * @所在包 :org.serial * @功能描述 : 串口类 * @修改记录 : */ public class DSerialPort implements Runnable, SerialPortEventListener { private String appName = "串口通讯测试" ; private int timeout = 2000 ; // open 端口时的等待时间 private int threadTime = 0 ; private CommPortIdentifier commPort; private SerialPort serialPort; private InputStream inputStream; private OutputStream outputStream; /** * @方法名称 :listPort * @功能描述 :列出所有可用的串口 * @返回值类型 :void */ @SuppressWarnings ( "rawtypes" ) public void listPort() { CommPortIdentifier cpid; Enumeration en = CommPortIdentifier.getPortIdentifiers(); System.out.println( "now to list all Port of this PC:" + en); while (en.hasMoreElements()) { cpid = (CommPortIdentifier) en.nextElement(); if (cpid.getPortType() == CommPortIdentifier.PORT_SERIAL) { System.out.println(cpid.getName() + ", " + cpid.getCurrentOwner()); } } } /** * @方法名称 :selectPort * @功能描述 :选择一个端口,比如:COM1 * @返回值类型 :void * @param portName */ @SuppressWarnings ( "rawtypes" ) public void selectPort(String portName) { this .commPort = null ; CommPortIdentifier cpid; Enumeration en = CommPortIdentifier.getPortIdentifiers(); while (en.hasMoreElements()) { cpid = (CommPortIdentifier) en.nextElement(); if (cpid.getPortType() == CommPortIdentifier.PORT_SERIAL && cpid.getName().equals(portName)) { this .commPort = cpid; break ; } } openPort(); } /** * @方法名称 :openPort * @功能描述 :打开SerialPort * @返回值类型 :void */ private void openPort() { if (commPort == null ){ log(String.format( "无法找到名字为'%1$s'的串口!" , commPort.getName()));} else { log( "端口选择成功,当前端口:" + commPort.getName() + ",现在实例化 SerialPort:" ); try { serialPort = (SerialPort) commPort.open(appName, timeout); log( "实例 SerialPort 成功!" ); } catch (PortInUseException e) { throw new RuntimeException(String.format( "端口'%1$s'正在使用中!" , commPort.getName())); } } } /** * @方法名称 :checkPort * @功能描述 :检查端口是否正确连接 * @返回值类型 :void */ private void checkPort() { if (commPort == null ){ throw new RuntimeException( "没有选择端口,请使用 " + "selectPort(String portName) 方法选择端口" );} if (serialPort == null ) { throw new RuntimeException( "SerialPort 对象无效!" ); } } /** * @方法名称 :write * @功能描述 :向端口发送数据,请在调用此方法前 先选择端口,并确定SerialPort正常打开! * @返回值类型 :void * @param message */ public void write(String message) { checkPort(); try { outputStream = new BufferedOutputStream(serialPort.getOutputStream()); } catch (IOException e) { throw new RuntimeException( "获取端口的OutputStream出错:" + e.getMessage()); } try { outputStream.write(message.getBytes( "GBK" ), 0 , message.getBytes( "GBK" ).length); //outputStream.write(message.getBytes()); log( "信息发送成功:" + new String(message.getBytes())); } catch (IOException e) { throw new RuntimeException( "向端口发送信息时出错:" + e.getMessage()); } finally { try { outputStream.close(); } catch (Exception e) { } } } /** * @方法名称 :startRead * @功能描述 :开始监听从端口中接收的数据 * @返回值类型 :void * @param time * 监听程序的存活时间,单位为秒,0 则是一直监听 */ public void startRead( int time) { checkPort(); try { inputStream = new BufferedInputStream(serialPort.getInputStream()); } catch (IOException e) { throw new RuntimeException( "获取端口的InputStream出错:" + e.getMessage()); } try { serialPort.addEventListener( this ); } catch (TooManyListenersException e) { throw new RuntimeException(e.getMessage()); } serialPort.notifyOnDataAvailable( true ); log(String.format( "开始监听来自'%1$s'的数据--------------" , commPort.getName())); if (time > 0 ) { this .threadTime = time * 1000 ; Thread t = new Thread( this ); t.start(); log(String.format( "监听程序将在%1$d秒后关闭。。。。" , threadTime)); } } /** * @方法名称 :close * @功能描述 :关闭 SerialPort * @返回值类型 :void */ public void close() { serialPort.close(); serialPort = null ; commPort = null ; } public void log(String msg) { System.out.println(appName + " --> " + msg); } /** * 数据接收的监听处理函数 */ @Override public void serialEvent(SerialPortEvent arg0) { switch (arg0.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 [ 1024 ]; String readStr = "" ; String s2 = "" ; try { while (inputStream.available() > 0 ) { inputStream.read(readBuffer); readStr += new String(readBuffer).trim(); } s2 = new String(readBuffer).trim(); log( "接收到端口返回数据(长度为" + readStr.length() + "):" + readStr); log(s2); } catch (IOException e) { } } } @Override public void run() { try { Thread.sleep(threadTime); serialPort.close(); log(String.format( "端口''监听关闭了!" , commPort.getName())); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { DSerialPort dp = new DSerialPort(); dp.listPort(); dp.selectPort( "COM6" ); dp.write( "tdgfg!" ); dp.startRead( 30 ); } } |
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持IT俱乐部。