标题: 基于51单片机Android WiFi控制LED开关设计与实现 [打印本页]

作者: bbxyliyang    时间: 2023-7-5 14:13
标题: 基于51单片机Android WiFi控制LED开关设计与实现
一、系统方案
手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯、蜂鸣器的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯、蜂鸣器的开关控制指令,ESP8266将收到的数据发送给单片机,从而实现对LED灯、蜂鸣器进行开关控制。

设计好的实物是这个样子:

二、硬件设计

ESP8266模块作为一个透传模块使用,RXD、TXD分别连接51单片机的TXD和RXD,VCC接3.3V电压,GND接地,只需要连接这些管脚,ESP8266模块就可以正常工作了。在单片机P16口上连接蜂鸣器、P26、P27连接两个3mm的LED灯,我们的目的是通过手机APP上的开关控制着LED灯的亮灭以及蜂鸣器打开与关闭。

原理图如下:

三、单片机软件设计
硬件的连接不复杂,接下来主要是单片机和手机APP代码的编写。
单片机代码主要是串口初始化、串口中断和ESP8266的初始化。首先是串口初始化:
    TMOD=0x20;                //定时器1工作在方式2
        TH1 = 0xfd;                //波特率9600
        TL1 = 0xfd;
        SM0=0;                  //串口工作在方式1
        SM1=1;
        EA = 1;                        //开总中断
        REN = 1;                //使能串口
        TR1 = 1;                //定时器1开始计时
然后是ESP8266初始化:

     delayms(1000);                        //延时
        sendString("AT+CWMODE=2\r\n");        //设置ESP8266工作在AP模式下
        delayms(1000);        
        sendString("AT+CIPMUX=1\r\n");        //允许多连接
        delayms(1000);        
        sendString("AT+CIPSERVER=1,8080\r\n");     //建立服务器
        delayms(1000);        
        ES = 1;                                      //esp8266初始化之后开串口中断
贴上51单片机负责串口发送的两个函数:

//发送一个字节
void sendChar(uchar a)
{
        SBUF = a;
        while(TI==0);
        TI=0;        
}
//发送字符串
void sendString(uchar *s)
{
        while(*s!='\0')
        {
                sendChar(*s);
                s++;
        }

}

在串口中断中处理接收到的数据:
1:打开蜂鸣器  2:关闭蜂鸣器
3:打开红灯    4:关闭红灯
5:打开绿灯    6:关闭绿灯
esp8266在收到数据并转发给单片机时的数据格式:+IPD,<client号>,<收到的字符长度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客户端编号,esp8266最多支持5个客户端同时连接,也就是说客户端编号是0到4,在本设计中由于只有一个客户端与esp8266相连,所以客户端编号是0;5代表收到的字符长度;hello是收到的字符。在本例中esp8266发送给单片机的数据是+IPD,0,1:1,我们把接收到的字符串缓存到字符数组中,所以在处理收到的数据逻辑中,首先判断是否是以'+'开始的,否则视作无效数据,然后判断数组中的第十个数据,因为第十个数据才是手机APP发送过来的数据。
void uart() interrupt 4
{
    if(RI == 1)   
    {
        RI = 0;     //清除串口接收标志位
        receiveTable=SBUF;
        if(receiveTable[0]=='+')
        {
                i++;
        }
        else
        {
                i=0;
        }
        if(i==10)
        {
                i=0;
                switch(receiveTable[9])
                {
                        case '1':
                                BEEP=0;
                                break;
                        case '2':
                                BEEP=1;
                                break;
                        case '3':
                                RedLED=0;
                                break;
                        case '4':
                                RedLED=1;
                                break;
                        case '5':
                                GreenLED=0;
                                break;
                        case '6':
                                GreenLED=1;
                                break;
                }
        }

  }
}

四、Android APP软件设计
Android APP是借助Android Studio来开发的,界面比较简单,通过编辑框输入esp8266的IP地址和端口号,esp8266默认的IP地址是192.168.4.1,端口号是8080,这些都可以通过AT指令进行修改。布局页面的xml代码我们就不贴了,熟悉Android开发的读者很快就能根据截图编写出来,放上一个APP界面的截图:


我们主要看一下逻辑代码部分:
首先是控件的初始化和按钮点击事件回调的绑定
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnConnect = (Button) findViewById(R.id.btn_connect);
        mEtIP = (EditText) findViewById(R.id.et_ip);
        mEtPort = (EditText) findViewById(R.id.et_port);
        mBtnRedOn = (Button) findViewById(R.id.btn_red_on);
        mBtnRedOff = (Button) findViewById(R.id.btn_red_off);
        mBtnYellowOn = (Button) findViewById(R.id.btn_yellow_on);
        mBtnYellowOff = (Button) findViewById(R.id.btn_yellow_off);
        mBtnBlueOn = (Button) findViewById(R.id.btn_blue_on);
        mBtnBlueOff = (Button) findViewById(R.id.btn_blue_off);
        mBtnConnect.setOnClickListener(this);
        mBtnRedOn.setOnClickListener(this);
        mBtnRedOff.setOnClickListener(this);
        mBtnYellowOn.setOnClickListener(this);
        mBtnYellowOff.setOnClickListener(this);
        mBtnBlueOn.setOnClickListener(this);
        mBtnBlueOff.setOnClickListener(this);
    }
按钮的点击回调方法:
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_connect:
                //连接
                if (mSocket == null || !mSocket.isConnected()) {
                    String ip = mEtIP.getText().toString();
                    int port = Integer.valueOf(mEtPort.getText().toString());
                    mConnectThread = new ConnectThread(ip, port);
                    mConnectThread.start();
                }
                if (mSocket != null && mSocket.isConnected()) {
                    try {
                        mSocket.close();
                        mBtnConnect.setText("连接");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                break;
            case R.id.btn_red_on:        
                if (out != null) {
                    out.print("1");
                    out.flush();
                }
                break;
            case R.id.btn_red_off:      
                if (out != null) {
                    out.print("2");
                    out.flush();
                }
                break;
            case R.id.btn_yellow_on:
                if (out != null) {
                    out.print("3");
                    out.flush();
                }
                break;
            case R.id.btn_yellow_off:
                if (out != null) {
                    out.print("4");
                    out.flush();
                }
                break;
            case R.id.btn_blue_on:
                if (out != null) {
                    out.print("5");
                    out.flush();
                }
                break;
            case R.id.btn_blue_off:
                if (out != null) {
                    out.print("6");
                    out.flush();
                }
                break;
        }
    }


负责连接esp8266的线程:

private class ConnectThread extends Thread {
        private String ip;
        private int port;
        public ConnectThread(String ip, int port) {
            this.ip = ip;
            this.port = port;
        }

        @Override
        public void run() {
            try {
                mSocket = new Socket(ip, port);
                out = new PrintStream(mSocket.getOutputStream());
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mBtnConnect.setText("断开");
                    }
                });
                new HeartBeatThread().start();
            } catch (IOException e) {
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    }




作者: devcang    时间: 2023-7-7 10:03

建议使用esp-12那样有更多引脚的,连51都省了。
作者: bbxyliyang    时间: 2023-7-7 15:00
devcang 发表于 2023-7-7 10:03
建议使用esp-12那样有更多引脚的,连51都省了。

好的,有时间的我试试,谢谢
作者: slf252    时间: 2023-7-7 15:38
楼上说的对。
完全可以使用乐鑫的SDK开发,网上资料也齐全,而且esp8266本身就是32位的,性能比51强。
作者: bbxyliyang    时间: 2023-7-7 20:34
slf252 发表于 2023-7-7 15:38
楼上说的对。
完全可以使用乐鑫的SDK开发,网上资料也齐全,而且esp8266本身就是32位的,性能比51强。

受教了,感谢




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1