在很多应用程序中都需要用到pc机与外部设备如:嵌入式系统、传感器、开关设备等进行数据通讯。其中,最常用的接口就是RS-232串口和并口。SUN的CommAPI分别提供了对常用的RS232串行端口和IEEE1284并行端口通讯的支持。
至于java串口通讯的配置以及通讯模式在sun的demo以及网上都有很多具体的实例。
下面是我在开发一个叫号功能模块时通过串口通信来控制LED显示的实例,由于第一次进行相关的开发,看似一个非常简单的功能在实际开发中却遇到了一些问题,希望本人的解决方式能够对大家有所帮助,也希望大家能够提出更好的解决方式。
先看一下LED显示屏厂商提供的通讯协议:
---遥控单双色、单双行、混合屏
一、 每一次对任一特定地址发送信息由内码帧(7f/7e),数码帧 (6f/6e),定时帧(5f),时间帧(4f)中的一种或多种构成,结束 时发送一结束帧。 二、帧结构:每帧由84字节构成。 1、 内码帧:一幕由一起始帧和零或多个中间帧组成,一次 发送可有多幕。 1) 起始帧:地址(1字节)+帧控制7F(1字节) +幕号(1字节)+COMMAND(8字节) +内码/ASCII(73字节) 2) 中间帧:地址(1字节)+帧控制7E(1字节)+ 幕号(1字节)+COMMAND(8字节)+内码/ASCII (73字节) 3)COMMAND: 前4字节未定义,后4字节依次为动画(0~4), 移入及移出(各16种),速度(0~255),追加 (D3连续、D2停止、D0闪烁、D4时间、D6暂停、 D7动画) 4)内码/ASCII结构: a、 内码4字节,依次为控制字节(D7宽体/正常体、 D4绿色、D5红色、D3粗体、D2细体反白、D1 粗体反白、D0细体),内码高位,内码低位,未用 b、ASCII 2字节,依次为控制字节(D7宽体/正常体、 D5绿色、D4红色、D3粗体、D2细体反白、D1粗体 反白、D0细体),ASCII码 2、数码帧:由一起始帧和零或多中间帧组成。 1) 起始帧:地址(1字节)+帧控制6F(1字节)+ 数据(82字节) 2) 间帧:地址(1字节)+帧控制6E(1字节)+ 数据(82字节) 3、定时帧:由一帧组成。 起始帧:地址(1字节)+帧控制5F(1字节)+ 数据(48字节)+无效数据 包括8个定时器,每个6字节,结构如下: 开/关(0为OFF、1为ON),日期(0~6为 sunday~satday、7为每一天),小时(0~23), 分钟(0~59),起始幕,结束幕。 4、时间帧:由一帧组成。 地址(1字节)+帧控制4F(1字节)+年高二位 (1字节)+年低二位(1字节)+月(1字节)+日 (1字节) +时(1字节)+分(1字节)+星期(1字节) +无效数据 日期都用十进制表示,星期部分0为星期日。 4、结束帧:由一帧组成。 地址(1字节)+帧控制7D(1字节)+无效数据(82 字节) 3)移入,移出模式:各16种模式,可任意组合。
三、 移入模式: 移出模式: 模式0:移入← 移出← 模式1:移入→ 移出→ 模式2:移入↑ 移出↑ 模式3:移入↓ 移出↓ 模式4:跳入← 跳出← 模式5:展开→ 展开→ 模式6:展开← 展开← 模式7:展开↑ 展开↑ 模式8:展开↓ 展开↓ 模式9:展开←→ 展开←→ 模式10:展开→← 展开→← 模式11:展开↑↓ 展开↑↓ 模式12:展开↓↑ 展开↓↑ 模式13:即入 即出 模式14:预备 预备 模式15:随机(已设为循环)随机(已设为循环) 四、通讯卡接口: 1)初始化通讯卡: a、将0xFF写入地址211H b、从211H读入一字节,判断D3是否为‘1’,如为 ‘0’则重复此步骤 c、将0x00写入地址211H d、从211H读入一字节,判断D3是为‘0’,如为 ‘1’则重复此步骤 e、初始化完成 2)写入数据地址:210H 3)读状态地址:211H 状态标志:D0写允许,高电平有效
注:未使用字节必须置为0X00.
232口: 8位数据位, 1位停止位, 无效验位, 波特率为9600.
* 每帧84字节, 每幕发一个7F帧, 超过18个字的条屏, 每幕需加发一个7E帧, 所有幕发完后,发7D帧(结束帧) |
串口通讯涉及到的部分主要代码:
import java.io.*;
import javax.comm.*;
public class SerialBean {
static SerialBean bean;
String PortName;
CommPortIdentifier portId;
SerialPort serialPort;
OutputStream out;
InputStream in;
public String getPortName() {
return PortName;
}
public void setPortName(String portName) {
PortName = portName;
}
private SerialBean(int PortID) {
PortName = "COM" + PortID;
}
public static SerialBean getInstance() {
if (bean == null) {
if (!portInit(1))
return null;
}
return bean;
}
public static boolean portInit(int port) {
if (bean != null) {
bean.ClosePort();
}
bean = new SerialBean(port);
return bean.initialize();
}
public boolean initialize() {
try {
portId = CommPortIdentifier.getPortIdentifier(PortName);
try {
serialPort = (SerialPort)
portId.open("SerialBean", 3000);
} catch (PortInUseException e) {
e.printStackTrace();
return false;
}
try {
in = serialPort.getInputStream();
out = serialPort.getOutputStream();
} catch (IOException e) {
return false;
}
try {
serialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
return false;
}
} catch (NoSuchPortException e) {
e.printStackTrace();
return false;
}
return true;
}
public void writePort(byte[] bytes) {
for(byte b:bytes){
writePort(b);
}
}
public void writePort(byte b) {
try {
out.write(b);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public void ClosePort() {
if (out != null) {
try {
out.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
serialPort.close();
}
}
向LED发送数据代码,以下测试代码将大部分涉及到通讯协议中的模式以及指令都写死在程序中,有必要可以进行重构
static int number = 0;
static byte target = 0x00;
static byte font = (byte) 0; //默认字体
static int LED_LENGTH = 16; //默认LED显示字体数目(汉字)
static byte MODULE=0x00; //默认模式
static byte[] beg = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte[] end = new byte[]{0x7D,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
public void display(String meg) {
SerialBean sb = SerialBean.getInstance();
int bytes = LED_LENGTH * 4;
writeNext(sb);
//汉字在LED中显示所占的宽度是字母或者数字的2倍,以下进行区分
for (int i = 0; i < meg.length(); i++) {
String s = meg.substring(i, i + 1);
byte[] b = s.getBytes();
if (b.length == 2) {
if (bytes < 4) {
for (int n = 0; n < bytes + 73 - LED_LENGTH * 4; n++) {
sb.writePort(0x00);
}
bytes = LED_LENGTH * 4;
writeNext(sb);
}
sb.writePort(font);
sb.writePort(s.getBytes());
sb.writePort(0x00);
bytes -= 4;
} else if (b.length == 1) {
if (bytes < 2) {
for (int n = 0; n < bytes + 73 - LED_LENGTH * 4; n++) {
sb.writePort(0x00);
}
bytes = LED_LENGTH * 4;
writeNext(sb);
}
sb.writePort(font);
sb.writePort(meg.charAt(i));
bytes -= 2;
}
}
for (int n = 0; n < bytes + 73 - LED_LENGTH * 4; n++) {
sb.writePort(0x00);
}
sb.writePort(target);
sb.writePort(end);
sb.ClosePort();
}
private void writeNext(SerialBean sb) {
sb.writePort(target);
sb.writePort(0x7F);
sb.writePort((byte) number++);
sb.writePort(beg);
sb.writePort(MODULE);
}
以上代码刚开始写完后进行测试认为基本上没有问题,但是一测试却发现LED上没有任何反应,刚开始以为没有将数据发送过去,采用一些串口监测工具却发现数据已经发送成功;在网上也没有查到任何资料,后来折腾了半天突然想到是不是电脑数据发送太快导致LED中处理数据时导致丢失数据帧,于是立马在发送每个字节后加了一个时间延迟,结果立马有反应,后来适当调节延迟时间一切ok。
public void writePort(byte b) {
try {
out.write(b);
out.flush();
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
(后来想了一下,LED处理数据时可能采用缓存操作,当pc向其发送信息时首先发送至缓存区域,LED此时读取缓存开始处理数据,但是如果pc发送信息太快以致led还没有处理完数据并且数据的大小超出了LED的缓存区域,那么此时可能就会出现将早先的数据进行覆盖的问题,以上只是猜测,后来程序调试好了也没有再理会)
分享到:
相关推荐
JAVA串口通信包Comm2.0.3是Java平台上的一个开源库,专门用于实现串行端口(Serial Port)的通信功能。在Linux环境下,这个包提供了与硬件设备进行串口交互的能力,例如连接Arduino、GPS模块或者任何其他通过串行...
- Java串口通信可以用于创建监测和控制程序,比如远程控制机器人、读取传感器数据、控制LED灯等。 7. **其他库**: - 除了RXTX,还有其他的Java串口通信库,如JSSC(Java Simple Serial Connector)和JTermios,...
LED8N收银客户显示屏幕是一种常见的用于商业收银系统中的设备,主要用于显示交易金额、商品信息等关键数据。在本文中,我们将深入探讨LED8N收银客显屏的开发示例,以及如何利用这些示例进行实际应用。 首先,LED8N...
单片机与PC机串口通讯是电子工程和嵌入式系统开发中的一个重要环节,它允许单片机设备与个人计算机进行数据交换,为各种应用提供了便利,如远程监控、数据采集、设备控制等。本资源"最新单片机仿真 单片机与PC机串口...
6. **ControlKit.java**:这个名字暗示了一个控制工具包,可能包含一系列方法用于操作LED屏幕,如显示文本、动画等。它可能提供了设置字体、颜色、位置等界面元素的方法,并负责将接收到的车牌信息转换为适合LED屏幕...
通过Java与Arduino的串行通信,你可以控制Arduino执行各种任务,如控制LED灯、读取传感器数据等。在JavaArduino项目中,可能还包含了更高级的特性,如事件驱动的通信、数据解析、异常处理等,这些都是进一步学习和...
压缩包中可能包含了各种实例,如LED灯控制、串口通信、温度传感器读取、电机控制等。这些实例可以帮助学习者理解如何将理论知识应用到实际项目中: 1. LED灯控制:通过I/O口控制LED灯的亮灭,理解单片机对硬件的...
标题中的“基于stm32 WiFi控制多功能LED程序、电路图、PCB、手机APP程序”表明这是一个关于使用STM32微控制器实现通过WiFi控制LED灯的项目,该项目涵盖了硬件设计和软件开发的多个方面。STM32是一款基于ARM Cortex-M...
标题中的“EQ2013/2023一卡通开发实例”可能指的是一个关于智能一卡通系统的开发案例集,涵盖了从2013年到2023年的技术发展和应用。一卡通系统通常指的是集成了门禁、消费、考勤等多种功能的智能卡系统,广泛应用于...
总结来说,"超级点阵,上位机发送单片机显示资料.zip"的资源为学习者提供了一个完整的点阵显示解决方案,涵盖了从上位机编程到单片机控制,再到硬件接口设计的各个环节。通过深入研究和实践,开发者能够掌握点阵显示...
对于ESP8266的控制,开发者可能需要一个串口通信工具(如Arduino IDE或ESP8266 AT Command测试工具)来发送和接收数据。 5. **硬件控制**:在硬件层面,51单片机通过GPIO(通用输入/输出)引脚控制LED灯。当接收到...
在IT领域,16*16点阵滚动显示是一种常见的显示技术,主要应用于电子显示屏、LED屏幕、LCD显示器等设备中。这种技术涉及到图形处理、显示驱动和动态刷新等多个方面,是数字信息可视化的重要手段。下面我们将深入探讨...
综上所述,"Bluetooth_LEDs_android.rar"项目是一个使用Delphi进行跨平台开发的实例,目标是创建一个Android应用,通过蓝牙连接控制LED灯。项目涉及的技能包括Android应用开发、蓝牙通信、UI设计、设备驱动程序编写...
它的命名中包含了“串口”一词,这意味着它可能通过串行通信接口(如RS-232)与电子围棋设备连接。串口通信是计算机与其他设备间常见的通信方式,适合低速数据传输,且在嵌入式系统中广泛应用。 综上所述,这个...
在这个实验中,目标是通过TIMER模块来控制LED灯的闪烁,同时设计一个上位机软件,通过串口通信改变LED灯的闪烁频率。 首先,我们来看STM32中的TIMER模块。STM32提供了多个定时器,包括高级定时器(TIM Advanced)、...
**ArduinoBlinkLED** 是一个基于Android开源硬件开发平台(Android Open Accessory Development Kit, ADK)的项目,用于展示如何使用Android设备控制Arduino板来实现LED灯的闪烁功能。这个简单实例是初学者理解...
在本文中,我们将深入探讨如何使用Android Studio开发一个应用程序,使其能够与单片机通过WiFi进行通信,从而实现对LED灯的远程控制。这个项目名为"Androidwifiled",其核心目标是创建一个Android应用,它能发送指令...
51. **JAVA串口通信管理程序**:使用JAVA编程实现串行通信,常用于设备控制和数据交换。 52. **基于VB技术的CS通信软件**:开发客户端-服务器(C/S)架构的通信应用程序。 53. **编解码技术在数字图像解决中应用**:...
单片机温度控制系统是电子工程领域中一个重要的应用实例,它广泛应用于家用电器、工业生产、环境监测等各个领域。这个“单片机-温度控制系统资料.zip”压缩包可能包含了设计、实现和优化这样一个系统所需的各种资源...