Java和51單片機串口通信(Java發送數據到單片機,單片機反饋數據到電腦)


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


 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM