找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2420|回復: 4
收起左側

基于51單片機Android WiFi控制LED開關設計與實現(xiàn)

[復制鏈接]
ID:190577 發(fā)表于 2023-7-5 14:13 | 顯示全部樓層 |閱讀模式
一、系統(tǒng)方案
手機APP通過ESP8266 WIFI模塊與51單片機通信控制LED燈、蜂鳴器的開關。下位機由單片機、ESP8266模塊和LED燈組成,上位機由Android手機APP承擔。我們在APP上發(fā)送LED燈、蜂鳴器的開關控制指令,ESP8266將收到的數(shù)據(jù)發(fā)送給單片機,從而實現(xiàn)對LED燈、蜂鳴器進行開關控制。
1.png
設計好的實物是這個樣子:
2.png
二、硬件設計

ESP8266模塊作為一個透傳模塊使用,RXD、TXD分別連接51單片機的TXD和RXD,VCC接3.3V電壓,GND接地,只需要連接這些管腳,ESP8266模塊就可以正常工作了。在單片機P16口上連接蜂鳴器、P26、P27連接兩個3mm的LED燈,我們的目的是通過手機APP上的開關控制著LED燈的亮滅以及蜂鳴器打開與關閉。

原理圖如下:
3.png 4.png 5.png
三、單片機軟件設計
硬件的連接不復雜,接下來主要是單片機和手機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單片機負責串口發(fā)送的兩個函數(shù):

//發(fā)送一個字節(jié)
void sendChar(uchar a)
{
        SBUF = a;
        while(TI==0);
        TI=0;        
}
//發(fā)送字符串
void sendString(uchar *s)
{
        while(*s!='\0')
        {
                sendChar(*s);
                s++;
        }

}

在串口中斷中處理接收到的數(shù)據(jù):
1:打開蜂鳴器  2:關閉蜂鳴器
3:打開紅燈    4:關閉紅燈
5:打開綠燈    6:關閉綠燈
esp8266在收到數(shù)據(jù)并轉發(fā)給單片機時的數(shù)據(jù)格式:+IPD,<client號>,<收到的字符長度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客戶端編號,esp8266最多支持5個客戶端同時連接,也就是說客戶端編號是0到4,在本設計中由于只有一個客戶端與esp8266相連,所以客戶端編號是0;5代表收到的字符長度;hello是收到的字符。在本例中esp8266發(fā)送給單片機的數(shù)據(jù)是+IPD,0,1:1,我們把接收到的字符串緩存到字符數(shù)組中,所以在處理收到的數(shù)據(jù)邏輯中,首先判斷是否是以'+'開始的,否則視作無效數(shù)據(jù),然后判斷數(shù)組中的第十個數(shù)據(jù),因為第十個數(shù)據(jù)才是手機APP發(fā)送過來的數(shù)據(jù)。
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來開發(fā)的,界面比較簡單,通過編輯框輸入esp8266的IP地址和端口號,esp8266默認的IP地址是192.168.4.1,端口號是8080,這些都可以通過AT指令進行修改。布局頁面的xml代碼我們就不貼了,熟悉Android開發(fā)的讀者很快就能根據(jù)截圖編寫出來,放上一個APP界面的截圖:
6.png


我們主要看一下邏輯代碼部分:
首先是控件的初始化和按鈕點擊事件回調(diào)的綁定
    @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);
    }
按鈕的點擊回調(diào)方法:
    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();
                    }
                });
            }
        }
    }



回復

使用道具 舉報

ID:277550 發(fā)表于 2023-7-7 10:03 | 顯示全部樓層

建議使用esp-12那樣有更多引腳的,連51都省了。
回復

使用道具 舉報

ID:190577 發(fā)表于 2023-7-7 15:00 | 顯示全部樓層
devcang 發(fā)表于 2023-7-7 10:03
建議使用esp-12那樣有更多引腳的,連51都省了。

好的,有時間的我試試,謝謝
回復

使用道具 舉報

ID:359272 發(fā)表于 2023-7-7 15:38 | 顯示全部樓層
樓上說的對。
完全可以使用樂鑫的SDK開發(fā),網(wǎng)上資料也齊全,而且esp8266本身就是32位的,性能比51強。
回復

使用道具 舉報

ID:190577 發(fā)表于 2023-7-7 20:34 | 顯示全部樓層
slf252 發(fā)表于 2023-7-7 15:38
樓上說的對。
完全可以使用樂鑫的SDK開發(fā),網(wǎng)上資料也齊全,而且esp8266本身就是32位的,性能比51強。

受教了,感謝
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表