Java發送字符串到單片機,單片機返回給電腦
----------------------------------------------------------------------------------------------------
材料:
1. 51單片機
2. Java客戶端
3. Keil程序
----------------------------------------------------------------------------------------------------
一、單片機程序
在Keil中新建工程,編寫程序,生成 .hex 文件(這個文件可以燒錄到單片機中)
/*
串口通信:
1、由PC機通過串行口向單片機發送數據,這個數據是存放在單片機的接收緩沖器SBUF中的;
2、單片機將串行口中的數據存放在一個臨時變量中;
3、單片機將存放在臨時變量中的數據發送到發送緩沖器SBUF中,在PC機上顯示。
*/
#include <reg52.h>
#define u16 unsigned int
#define u8 unsigned char
// 串行口通信初始化函數
void StartInit()
{
/*
1、確定T1的工作方式(編程TMOD寄存器):因為串行口中斷是由定時器T1決定的,
所以,低四位全部為0,高四位中,GATE=0,C/T非=0,選擇工作方式1(8位的自動重裝載),即M1M0=10
所以是:00100000,轉成十六進制數是:0x20
*/
TMOD=0x20;
/*
2、計算T1的初值,裝載TH1、TL1:使用工具生成,設置參數,定時器方式:方式2;晶振頻率:12Mhz;
波特率:4800;SMOD:波特率倍增位,1,即增加1倍;計算結果是:F3H
所以TH1=0xF3,TL1=0xF3,自動重裝載
*/
TH1=0xF3;
TL1=0xF3;
/*
PCON:與串行口工作相關的參數,只有一位SMOD(最高位),在串行口方式1、方式2、方式3時,
波特率與SMOD有關,當SMOD=1時,波特率提高一倍。復位時,SMOD=0,
這里波特率提高一倍,所以SMOD=1,即10000000,轉成十六進制數字是:0x80
*/
PCON=0x80;
/*
4、啟動T1(編程TCON中的TR1位):TR1=1時,定時器T1才開始啟動
*/
TR1=1;
/*
5、確定串行口控制(編程SCON寄存器):選擇工作方式1(10位異步收發器,8位數據,1位起始位,1位停止位),
所以SM0=0,SM1=1;不需要RB8控制RI的激活(就是為了簡單),設置SM2=0(SM2是多機通信控制位);
REN,允許串行接收位,啟動串行口接收數據,REN=1;
TB8,RB8,TI,RI均為0(看資料),所以是:01010000,轉成十六進制數是:0x50
*/
SCON=0x50;
/*
6、中斷位的開啟,總中斷允許位EA=1;串行口中斷允許位ES=1
*/
EA=1;
ES=1;
}
// 主函數
void main()
{
StartInit(); // 串行口通信初始化
while(1); // 等待數據的發送和接收
}
// 發送或接收完一幀數據引起中斷,串行口中斷函數
void Start() interrupt 4
{
u8 receiveData; // 用一個變量存放數據
receiveData=SBUF; // 從單片機的接收緩沖器中獲取數據
RI=0; // 當數據接收完成后,由內部硬件將RI置1,所以這里需要把RI置0,等待下一次繼續接收數據
SBUF=receiveData; // 把變量中的數據放到發送緩沖器中,向PC機發送數據
while(!TI); // 當數據發送完成后(即串行口在發送停止位時,由內部硬件將TI置1,所以數據發送完成時TI=1)
TI=0; // 數據發送完成時,要將TI置0,等待下一次繼續發送數據
}
二、使用USB線連接電腦和單片機(或使用RS232/RS485 + MAX232),下載程序到單片機


三、編寫Java端程序
下載串口通信的 Jar 包, RXTXcomm.jar,下載地址:http://files.cnblogs.com/files/Dreamer-1/mfz-rxtx-2.2-20081207-win-x64.zip

這個文件夾里面需要注意兩點:jar包RXTXcomm需要導入到java工程里面去。另外就是需要將rxtxParallel.dll與rxtxSerial.dll復制在安轉JDK的bin文件下和jre的bin文件夾下面,這樣才能保證能夠正常使用這個jar包。以下是將兩個dll文件復制的位置
新建Java工程:這里只是做一個測試,沒有考慮代碼的結構

package com.lvshitech.java51;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
public class Tools {
/*類方法 不可改變 不接受繼承
* 掃描獲取可用的串口
* 將可用串口添加至list並保存至list
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static final ArrayList<String> uartPortUseAblefind() {
//獲取當前所有可用串口
//由CommPortIdentifier類提供方法
Enumeration<CommPortIdentifier> portList=CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList=new ArrayList();
//添加並返回ArrayList
while(portList.hasMoreElements()) {
String portName=portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
/*
* 串口常見設置
* 1)打開串口
* 2)設置波特率 根據單板機的需求可以設置為57600 ...
* 3)判斷端口設備是否為串口設備
* 4)端口是否占用
* 5)對以上條件進行check以后返回一個串口設置對象new UARTParameterSetup()
* 6)return:返回一個SerialPort一個實例對象,若判定該com口是串口則進行參數配置
* 若不是則返回SerialPort對象為null
*/
public static final SerialPort portParameterOpen(String portName,int baudrate) {
SerialPort serialPort=null;
try { //通過端口名識別串口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打開端口並設置端口名字 serialPort和超時時間 2000ms
CommPort commPort=portIdentifier.open(portName,1000);
//進一步判斷comm端口是否是串口 instanceof
if(commPort instanceof SerialPort) {
System.out.println("該COM端口是串口!串口名稱是:" + portName);
//進一步強制類型轉換
serialPort=(SerialPort)commPort;
//設置baudrate 此處需要注意:波特率只能允許是int型 對於57600足夠
//8位數據位
//1位停止位
//無奇偶校驗
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8,SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//串口配制完成 log
System.out.println("串口參數設置已完成,波特率為"+baudrate+",數據位8bits,停止位1位,無奇偶校驗");
} else { //不是串口
System.out.println("該com端口不是串口,請檢查設備!");
//將com端口設置為null 默認是null不需要操作
}
} catch (NoSuchPortException e) {
e.printStackTrace();
} catch (PortInUseException e) {
e.printStackTrace();
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
}
return serialPort;
}
/*
* 串口數據發送以及數據傳輸作為一個類
* 該類做主要實現對數據包的傳輸至下單板機
*/
/*
* 上位機往單板機通過串口發送數據
* 串口對象 seriesPort
* 數據幀:dataPackage
* 發送的標志:數據未發送成功拋出一個異常
*/
public static void uartSendDatatoSerialPort(SerialPort serialPort,byte[] dataPackage) {
OutputStream out=null;
try {
out=serialPort.getOutputStream();
out.write(dataPackage);
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//關閉輸出流
if(out!=null) {
try {
out.close();
out=null;
//System.out.println("數據已發送完畢!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
* 上位機接收數據
* 串口對象seriesPort
* 接收數據buffer
* 返回一個byte數組
*/
public static byte[] uartReceiveDatafromSingleChipMachine(SerialPort serialPort) {
byte[] receiveDataPackage=null;
InputStream in=null;
try {
in=serialPort.getInputStream();
// 獲取data buffer數據長度
int bufferLength=in.available();
while(bufferLength!=0) {
receiveDataPackage=new byte[bufferLength];
in.read(receiveDataPackage);
bufferLength=in.available();
}
} catch (IOException e) {
e.printStackTrace();
}
return receiveDataPackage;
}
public static void main(String[] args) throws Exception {
// 打開串口
SerialPort serialPort = portParameterOpen("COM3", 4800);
// 要發送的數據
String dataSend = "【Java和51單片機串口通信測試,我能吞下玻璃而不傷身體!】";
int i=1;
while(true) {
// 發送數據到單片機
byte []datByte = dataSend.getBytes();
uartSendDatatoSerialPort(serialPort, datByte);
System.out.println("-------------------------------------------------------");
System.out.println((i++) + ". 發送到串口的數據:" + dataSend);
// 休眠300ms,等待單片機反應
Thread.sleep(500);
// 從單片機接收到的數據
byte[] dat = uartReceiveDatafromSingleChipMachine(serialPort);
if(dat != null && dat.length > 0) {
String dataReceive = new String(dat, "GB2312");
System.out.println((i++) + ". 從串口接收的數據:" + dataReceive);
} else {
System.out.println("接收到的數據為空!");
}
}
}
}
四、測試
插上USB,右鍵“我的電腦” - “管理” - “設備管理器” - “端口”,可以看到單片機的串口號

(1)打開單片機
(2)運行Java程序

以上實現了Java和單片機的串口通信,擴展:
(1)控制單片機的功能模塊,比如 LED燈的亮滅,蜂鳴器,跑馬燈,數碼管,電機轉動等等。
(2)在(1)的基礎上,使用Web工程做其他擴展實驗,通過點擊頁面的按鈕。
(3)點擊單片機上的按鈕,向電腦串口(Java端)發送數據,在頁面上顯示數據。
(4)使用C或者GUI開發客戶端進行(1)(2)(3)的實驗,還可以進行餅圖、柱狀圖、折線圖等形式展現數據規律。
