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)的實驗,還可以進行餅圖、柱狀圖、折線圖等形式展現數據規律。