APP同过ESP8266与51单片机通信

APP通过ESP8266与单片机通信

简述

本项目中是用ESP8266作为热点,工作在MODE2模式,手机作为station接入ESP8266的网络进行数据传输,同时,ESP8266与52单片机之间通过串口进行数据传输。
本项目中只需要APP向WIFI发送数据,所以在APP的程序中没有接收WIFI数据的程序。在文章最后,则是笔者在写代码的过程中遇到的一个问题,51单片机不能接收WIFI数据,但能向WIFI发送AT指令的问题。

手机端实现

建立连接线程

以下为APP与ESP8266建立连接的线程,建立连接时只要获取其对象即可。其中的IP和port为ESP8266的IP地址和端口号,IP一般默认为192.168.0.1,端口号默认为8080,端口号可以自己设置。

private class ConnectThred extends  Thread{
        private  String ip;
        private  int port;
        public ConnectThred(String ip,int port){
            this.ip = ip;
            this.port = port;
        }
        public void run(){
            //接收数据可用子线程也可直接在此线程操作
            char[] buffer=new char[256];//定义数组接收输入流数据
            String bufferString="";//定义一个字符接收数组数据
            int conut =0;//初始化buffer数组长度为0
            int tag=0;//初时写入数组的位置
            try {
                //建立连接
                socket = new Socket(ip,port);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("Controler","runOnUI");
                        bt_link.setText("断开连接");
                        bt_link.setBackgroundColor(Color.GREEN);
                        Toast.makeText(Controler.this,"连接成功",Toast.LENGTH_LONG).show();
                    }
                });
                //读取输入流
                bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //获取输出流
                OutputStream=socket.getOutputStream();
                //获取socket的输出流,接收数据
                InputStream = socket.getInputStream();
                while (true) {
                    //当输入流写入buffer数组的长度大于0时即接收到数据时
                    while ((conut=bufferedReader.read(buffer))>0) {
                        //将buffer数组的数据全部写入bufferString字符类型
                        while ( tag<buffer.length) {
                            bufferString=bufferString+buffer[tag];
                            tag++;
                        }
                        //将数据给messageHandler刷新UI界面
                        Message msgMessage =new Message();
                        msgMessage.obj=bufferString;
                        msgMessage.what=1;
                        messageHandler.sendMessage(msgMessage);
                        //初始化数据,以便处理下一条输入流信息
                        tag=0;
                        bufferString="";
                    }
                }

            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(Controler.this,"连接错误",Toast.LENGTH_LONG).show();
                    }
                });
            }
        }
    }

发送数据线程

以下是APP向ESP8266发送数据的代码,同样在一个子线程中执行。需要发送数据时通过对象调用此方法即可。

 //向服务器发送数据子程序
    public class Send extends Thread{
        public void run(){
            if(socket != null){
                try{
                    if (msg_send != null && msg_send.length()>0){
                        OutputStream.write(msg_send.getBytes("utf-8"));
                        OutputStream.flush();
                        msg_send="";
                    }
                    else{
                        Looper.prepare();
                        Toast.makeText(Controler.this,"发送的数据不能为空",Toast.LENGTH_LONG).show();
                        Looper.loop();
                    }
                }
                catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

通过按钮建立或断开连接

定义相关变量

private static final String IP = "192.168.4.1";//服务端IP
    private static final int PORT = 8080;         //端口号
    Socket socket;     //创建一个socket
    Boolean IsConnected = false;       //连接标志
    ConnectThred mConnectThread;  //TCP连接线程

    //输入输出流
    OutputStream OutputStream = null;//数据输出流,发送数据
    BufferedReader bufferedReader;//声明输入流对象
    InputStream InputStream = null;//定义数据输入流,用于接收数据

通过按钮实现连接:

 bt_link.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {  //连接按钮,点击与ESP8266芯片连接或断开
                    if (socket ==null || !socket.isConnected()){
                        mConnectThread = new ConnectThred(IP,PORT);
                        mConnectThread.start();
                    }
                    if (socket!=null && socket.isConnected()){
                        try {
                            socket.close();
                            socket = null;
                            bt_link.setText("点击连接");
                            bt_link.setBackgroundColor(Color.GRAY);
                            Toast.makeText(Controler.this,"连接已断开",Toast.LENGTH_LONG).show();
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
            }
        });

通过按钮发送数据:
通过new一个发送数据线程的对象,调用start方法启动发送数据线程即可发送数据。

select_mode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mode_count++;
                if (mode_count > 4)
                    mode_count=0;
                mode = mode_arr[mode_count];

                msg_send = "mod"+Integer.toString(mode_count)+"/n";
                new Send().start();

                tempmode.setText(mode);                   //设置模式
            }
        });

下位机端接收WIFI数据

下位机端使用51单片机实现,下位机端与ESP8266之间通过串口进行通信,传输数据。所以下位机接收WIFI数据时使用的是串口接收程序。

void UartConfiguration()
{
  TMOD=0x20;      // 设置计数器1工作模式2
	TH1=0xfd;			//计数器1初值
	TL1=0xfd;			//计数器1初值  两个初值决定波特率,此处设置波特率9600
	PCON=0x00;      //波特率倍增0x00不加倍,0x80加倍
	SCON=0x50;		// 
	EA=1;		    //
	ES=1;			//
	TR1=1;			//
	TI=1;
}

将接收到的数据存入一个数组中然后进行处理

void ESP_UART() interrupt 4
{
	static uchar i=0;
// 	led1=~led1;
	if(RI==1)
	{
		 RI=0;       //½ÓÊÕ±êÖ¾
		 Recive_table[i]=SBUF;
		 sendByte(Recive_table[i]);   
		 i++;         
		 if((Recive_table[i-1]=='\n'))
		 {
				Recive_table[i]='\0';
				i=0; 
		 }
	}
	else
		TI=0;
}

处理接收到的数据

void getData()
{
	if(Recive_table[0]=="+")
			sendString(Recive_table);
		if((Recive_table[0]=='+')&&(Recive_table[1]=='I')&&(Recive_table[2]=='P'))
		{
			if((Recive_table[3]=='D')&&(Recive_table[6]==','))
			{   
				if(Recive_table[9]=='0')//&& Recive_table[10]=='0'     //
				{
					Shutdown();
				}
				else if(Recive_table[9]=='1')//&& Recive_table[10]=='1'   //
				{
					
					MakeNum(Recive_table[10],Recive_table[11]);
					Startup();
				}
				else if(Recive_table[9]=='d')//&& Recive_table[10]=='1'   //
				{
					MakeNum(Recive_table[10],Recive_table[11]);
				}
				else if(Recive_table[9]=='e')//&& Recive_table[10]=='1'   //
				{
					MakeNum(Recive_table[10],Recive_table[11]);
				}
				else if(Recive_table[9]=='o'&& Recive_table[10]=='d')    //
				{
					m_index=Recive_table[11]-'0';
					SetMode(m_index);
				}
				else if(Recive_table[9]=='f')//&& Recive_table[10]=='1'   //
				{
					SetSweep(Recive_table[10]-'0');
				}
				else if(Recive_table[9]=='p')//&& Recive_table[10]=='1'   //
				{
					SetSpeed(Recive_table[10]-'0');
				}
				else if(Recive_table[9]=='i')//&& Recive_table[10]=='1'   //
				{
					SetDirect(Recive_table[10]-'0');
				}
				memset(Recive_table,0,50);
			}   
		}
}

注意

当ESP8266与51单片机通信时,51单片机不能使用CH340芯片进行串口数据的传输,不然会出现ESP8266发送的数据51单片机接收不到的情况。