zoukankan      html  css  js  c++  java
  • PC-PC-单片机(Arduino)通信实例

    请仔细理解相关参数,如端口设置、IP设置、COM口设置......等等.....不要盲目COPY.....这涉及2台电脑和一个单片机,其中一台电脑作为服务器并与单片机相连,负责通过网络与客户端通信(socket)和通过数据线与单片机通过COM口通信(我实验时用的是COM9,其他电脑可能不同需要调整:具体在设备管理器中查看)。

    1、Arduino板待烧入代码:(这里硬件的代码没啥好说的,只要你会写个简单Arduino代码并且自己烧过就知道该怎么做啦)

    //////////////////////////////////////////////////////////
    //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

    2、服务器和客户端代码:

    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并在具体实现中采取措施实现的数据的同步。
    ASerialBuffer
    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是一个进程,它不断的从指定的串口读取
    //数据并将其存放到缓冲区中
    BReadSerial
    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盘编译 && 客户端代码放到另一台电脑编译(如下图)

    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通过网络远程控制单片机啦!

     

  • 相关阅读:
    ES6-11学习笔记--深拷贝与浅拷贝
    ES6-11学习笔记--对象的扩展
    ES6-11学习笔记--箭头函数
    ES6-11学习笔记--扩展运算符与rest参数
    ES6-11学习笔记--函数的参数
    ES6-11学习笔记--数组的扩展
    ES6-11学习笔记--解构赋值
    ES6-11学习笔记--数组遍历
    班课2
    班课1
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3478417.html
Copyright © 2011-2022 走看看