PC-PC-單片機(Arduino)通訊實例

請仔細理解相關參數,如端口設置、IP設置、COM口設置......等等.....不要盲目COPY.....這涉及2臺電腦和一個單片機,其中一臺電腦做爲服務器並與單片機相連,負責經過網絡與客戶端通訊(socket)和經過數據線與單片機經過COM口通訊(我實驗時用的是COM9,其餘電腦可能不一樣須要調整:具體在設備管理器中查看)。java

一、Arduino板待燒入代碼:(這裏硬件的代碼沒啥好說的,只要你會寫個簡單Arduino代碼而且本身燒過就知道該怎麼作啦)git

//////////////////////////////////////////////////////////
//Arduino 1.0.x-----Arduino Uno----COM9
//使用3-10號引腳鏈接8個LED
//////////////////////////////////////////////////////////
int incomingByte = 0;   //輸入的數據存儲變量
int count=1;
void setup() {
    Serial.begin(9600);// opens serial port, sets data rate to 9600 bps
    for(int i=3;i<=10;i++)//打開3-10號引腳
        pinMode(i,OUTPUT);
}

void loop() {
    while(count){
        Serial.println("please input 0 1 2 3 4 5 6 7 8 9 a");
        count=0;
    }//第一次操做說明,count爲了第一次限制
    if (Serial.available() > 0){
        incomingByte = Serial.read();//讀取
        Serial.println(incomingByte, DEC);//寫入
    }//從COM口讀取數據
    
    switch (incomingByte)//數據處理並對引腳進行調控
    {
    case 48://輸入0時將3-10號引腳設爲高電位,使全部的燈滅
        for(int i=3;i<=10;i++){
            digitalWrite(i,HIGH);
        }break;
    case 49://輸入1從3-10號引腳電位依次設低電位維持0.5s,而後設爲高電位,實現流水燈效果
        for(int i=3;i<=10;i++){
            digitalWrite(i,LOW);
            delay(500);
            digitalWrite(i,HIGH);
        }break;
    case 50://輸入2流水燈,和輸入1時方向相反
        for(int i=10;i>=3;i--){
            digitalWrite(i,LOW);
            delay(500);
            digitalWrite(i,HIGH);
        }break;    
    case 51: digitalWrite(3,LOW);break;//輸入3,將3號電位調低,只讓3號引腳的燈亮
    case 52: digitalWrite(4,LOW);break; //.....
    case 53: digitalWrite(5,LOW);break; //.....
    case 54: digitalWrite(6,LOW);break; //.....
    case 55: digitalWrite(7,LOW);break; //.....
    case 56: digitalWrite(8,LOW);break; //.....
    case 57: digitalWrite(9,LOW);break; //.....
    case 97: digitalWrite(10,LOW);break;//.....
    default: 
        for(int i=3;i<=10;i++){
            digitalWrite(i,HIGH);
        }break;//將所電位調高關閉全部燈
    }
}
View Code

二、服務器和客戶端代碼:服務器

package serial;
   
public class SerialBuffer{
    private String Content = "";
    private String CurrentMsg, TempContent;
    private boolean available = false;
    private int LengthNeeded = 1;
       
    public synchronized String GetMsg(int Length){
        LengthNeeded = Length;
        notifyAll();
        if (LengthNeeded > Content.length()){
            available = false;
            while (available == false){
                try{
                    wait();
                } catch (InterruptedException e) {}
            }
        }
        CurrentMsg = Content.substring(0, LengthNeeded);
        TempContent = Content.substring(LengthNeeded);
        Content = TempContent;
        LengthNeeded = 1;
        notifyAll();
        return CurrentMsg;
    }//本函數從串口(緩衝區)中讀取指定長度的一個字符串。
     //參數Length指定所返回字符串的長度。 
       
    public synchronized void PutChar(int c){
        Character d = new Character((char) c);
        Content = Content.concat(d.toString());
        if (LengthNeeded < Content.length()){
            available = true;
        }
        notifyAll();
    }
}
//SerialBuffer.java (用來保存從串口所接收數據的緩衝區)
//在往緩衝區寫入數據或者是從緩衝區讀取數據的時候,必須保證數據的同步,
//所以GetMsg和PutChar函數均被聲明爲synchronized並在具體實現中採起措施實現的數據的同步。
A\SerialBuffer
package serial;
import java.io.*;
    
public class ReadSerial extends Thread
{
    private SerialBuffer ComBuffer;
    private InputStream ComPort;
        
    public ReadSerial(SerialBuffer SB, InputStream Port){
        ComBuffer = SB;
        ComPort = Port;
    }//本函數構造一個ReadSerial進程,
     //參數SB指定存放傳入數據的緩衝區,
     //參數Port指定從串口所接收的數據流
    public void run(){
        int c;
        try{
            while (true){
                c = ComPort.read();
                ComBuffer.PutChar(c);
            }
        } catch (IOException e) {}
    }
}
//ReadSerial.java (從串口讀取數據的程序)
//ReadSerial是一個進程,它不斷的從指定的串口讀取
//數據並將其存放到緩衝區中
B\ReadSerial
package serial;
import java.io.*;
import java.util.*;
import gnu.io.*;

public class SerialBean
{
    static String PortName;
    CommPortIdentifier portId;
    SerialPort serialPort;
    static OutputStream out;
    static InputStream in;
    SerialBuffer SB;
    ReadSerial   RT;
       
    public SerialBean(int PortID){
        PortName = "COM" + PortID;
    }// 本函數構造一個指向特定串口的SerialBean
    //該串口由參數PortID所指定。PortID = 1 表示COM1
       
    public int Initialize(){
        int InitSuccess = 1;
        int InitFail    = -1;
          try{
              portId = CommPortIdentifier.getPortIdentifier(PortName);
              try{
                  serialPort = (SerialPort)portId.open("Serial_Communication", 2000);
              } catch (PortInUseException e){
                  return InitFail;
              }//打開一個串口
              
              try{
                  in = serialPort.getInputStream();
                  out = serialPort.getOutputStream();
              } catch (IOException e){
                  return InitFail;
              }//讀寫流實例化
             
              try{
                   serialPort.setSerialPortParams(9600,
                              SerialPort.DATABITS_8,
                              SerialPort.STOPBITS_1,
                              SerialPort.PARITY_NONE);
              } catch (UnsupportedCommOperationException e){
                  return InitFail;
              }//設置串行端口通信參數
              
          } catch (NoSuchPortException e){
              return InitFail;
          }
        
          SB = new SerialBuffer();
          RT = new ReadSerial(SB, in);
          RT.start();
          // return success information
          return InitSuccess;
    }//本函數初始化所指定的串口並返回初始化結果。若是初始化成功返回1,不然返回-1。
    //初始化的結果是該串口被SerialBean獨佔性使用,其參數被設置爲9600, N, 8, 1。
    //若是串口被成功初始化,則打開一個進程讀取從串口傳入的數據並將其保存在緩衝區中。
   
    public String ReadPort(int Length){
        String Msg;
        Msg = SB.GetMsg(Length);
        if(Msg==null)Msg="ssdfsdf";
        return Msg;
    }//本函數從串口(緩衝區)中讀取指定長度的一個字符串。參數Length指定所返回字符串的長度
   
    public void WritePort(String Msg){
        int c;
        try{
            for (int i = 0; i < Msg.length(); i++)
                out.write(Msg.charAt(i));
        } catch (IOException e) {}
    }//本函數向串口發送一個字符串。參數Msg是須要發送的字符串
   
    public void ClosePort(){
        RT.stop();
        serialPort.close();
    }//本函數中止串口檢測進程並關閉串口
}
//SerialBean是本類庫與其餘應用程序的接口。
//該類庫中定義了SerialBean的構造方法以及初始化串口
//從串口讀取數據,往串口寫入數據以及關閉串口的函數
C\ SerialBean

分別把這3個文件放在D盤中而後分別編譯:以下(必定要注意-d後面有一個空格+一個點+一個空格).網絡

三個java文件編譯好以後,你將在D盤看到一個serial文件夾,裏面有相應的3個class文件。而後把原來的java文件刪除或者移到別的地方(很是重要,否則會在編譯服務器和客戶端時報錯)。而後把服務器代碼放到剛纔的D盤編譯 && 客戶端代碼放到另外一臺電腦編譯(以下圖)socket

import java.util.Scanner;
import java.io.*;
import java.net.*;
import serial.*;
import serial.ReadSerial;

public class EchoServer{
    private int port = 8000;
    private ServerSocket serverSocket;
    
    public EchoServer()throws IOException{
        serverSocket = new ServerSocket(port);
        System.out.println("服務器啓動");
    }//構造函數
    
    private PrintWriter getWriter(Socket socket)throws IOException{
        OutputStream socketOut=socket.getOutputStream();
        return new PrintWriter(socketOut,true);
    }//write函數

    private BufferedReader getReader(Socket socket)throws IOException{
        InputStream socketIn=socket.getInputStream();
        return new BufferedReader(new InputStreamReader(socketIn));
    }//read函數

    public void service(){
        Scanner scanner=new Scanner(System.in);
    SerialBean SB = new SerialBean(9);
    SB.Initialize();
    
        while(true){
            Socket socket=null;
            try{
                socket=serverSocket.accept();
                System.out.println("New connection accepted"+
                   socket.getInetAddress()+":"+socket.getPort());
                BufferedReader br=getReader(socket);
                PrintWriter pw=getWriter(socket);
                
                String clientMsg=null,portMsg=null;
                while((clientMsg=br.readLine())!=null){
                    System.out.println(clientMsg);
                    pw.println("~!:"+clientMsg);
                    if(clientMsg.equals("bye"))break;
                 
              portMsg = SB.ReadPort(9);
              System.out.println(portMsg);
              SB.WritePort(clientMsg);
                }
                SB.ClosePort();
                
            }catch(IOException e){
                e.printStackTrace();
            }finally{
                try{
                    if(socket!=null)socket.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
    }//服務函數

    public static void main(String args[])throws IOException{
        new EchoServer().service();
    }
}

                
服務器代碼    (這裏我用的是port=8000,COM9)若是硬件的com口不同要作相應調整
//網絡通訊客戶端實現
import java.net.*;
import java.io.*;
import java.util.*;

public class EchoClient{
    private String host="localhost";
    private int port=8000;
    private Socket socket;

    public EchoClient()throws IOException{
        InetAddress addr=InetAddress.getByName("192.168.16.101");socket =new Socket(addr,port);//採用網絡
        //socket = new Socket(host,port);//本地通訊,就是服務器和客戶端在同一個電腦(一臺電腦測試時用)
    }//構造函數

    public static void main(String args[])throws IOException{
        new EchoClient().talk();
    }//main函數

    private PrintWriter getWriter(Socket socket)throws IOException{
        OutputStream socketOut=socket.getOutputStream();
        return new PrintWriter(socketOut,true);
    }//重寫write函數

    private BufferedReader getReader(Socket socket)throws IOException{
        InputStream socketIn=socket.getInputStream();
        return new BufferedReader(new InputStreamReader(socketIn));
    }//重寫read函數

  public void talk()throws IOException{
        try{
            BufferedReader br=getReader(socket);
            PrintWriter    pw=getWriter(socket);
            BufferedReader localReader=new BufferedReader(
                new InputStreamReader(System.in));
            String msg=null;
            while((msg=localReader.readLine())!=null){
                
                pw.println(msg);
                System.out.println(br.readLine());
                if(msg.equals("bye"))break;
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                socket.close();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }//對話函數
}
                
        
















        
客戶端代碼    (這裏我用的網絡IP爲192.168.16.101,port和服務器一製爲8000,若是你在作測試時對應網絡IP要改成主機IP(網絡-詳細信息-IPv4)

 

 

 接着分別啓動主機和服務器就能夠實現PC經過網絡遠程控制單片機啦!ide

 

相關文章
相關標籤/搜索