找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2557|回復(fù): 4
收起左側(cè)

基于51單片機(jī)Android WiFi控制LED開(kāi)關(guān)設(shè)計(jì)與實(shí)現(xiàn)

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

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

原理圖如下:
3.png 4.png 5.png
三、單片機(jī)軟件設(shè)計(jì)
硬件的連接不復(fù)雜,接下來(lái)主要是單片機(jī)和手機(jī)APP代碼的編寫(xiě)。
單片機(jī)代碼主要是串口初始化、串口中斷和ESP8266的初始化。首先是串口初始化:
    TMOD=0x20;                //定時(shí)器1工作在方式2
        TH1 = 0xfd;                //波特率9600
        TL1 = 0xfd;
        SM0=0;                  //串口工作在方式1
        SM1=1;
        EA = 1;                        //開(kāi)總中斷
        REN = 1;                //使能串口
        TR1 = 1;                //定時(shí)器1開(kāi)始計(jì)時(shí)
然后是ESP8266初始化:

     delayms(1000);                        //延時(shí)
        sendString("AT+CWMODE=2\r\n");        //設(shè)置ESP8266工作在AP模式下
        delayms(1000);        
        sendString("AT+CIPMUX=1\r\n");        //允許多連接
        delayms(1000);        
        sendString("AT+CIPSERVER=1,8080\r\n");     //建立服務(wù)器
        delayms(1000);        
        ES = 1;                                      //esp8266初始化之后開(kāi)串口中斷
貼上51單片機(jī)負(fù)責(zé)串口發(fā)送的兩個(gè)函數(shù):

//發(fā)送一個(gè)字節(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:打開(kāi)蜂鳴器  2:關(guān)閉蜂鳴器
3:打開(kāi)紅燈    4:關(guān)閉紅燈
5:打開(kāi)綠燈    6:關(guān)閉綠燈
esp8266在收到數(shù)據(jù)并轉(zhuǎn)發(fā)給單片機(jī)時(shí)的數(shù)據(jù)格式:+IPD,<client號(hào)>,<收到的字符長(zhǎng)度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客戶端編號(hào),esp8266最多支持5個(gè)客戶端同時(shí)連接,也就是說(shuō)客戶端編號(hào)是0到4,在本設(shè)計(jì)中由于只有一個(gè)客戶端與esp8266相連,所以客戶端編號(hào)是0;5代表收到的字符長(zhǎng)度;hello是收到的字符。在本例中esp8266發(fā)送給單片機(jī)的數(shù)據(jù)是+IPD,0,1:1,我們把接收到的字符串緩存到字符數(shù)組中,所以在處理收到的數(shù)據(jù)邏輯中,首先判斷是否是以'+'開(kāi)始的,否則視作無(wú)效數(shù)據(jù),然后判斷數(shù)組中的第十個(gè)數(shù)據(jù),因?yàn)榈谑畟(gè)數(shù)據(jù)才是手機(jī)APP發(fā)送過(guò)來(lái)的數(shù)據(jù)。
void uart() interrupt 4
{
    if(RI == 1)   
    {
        RI = 0;     //清除串口接收標(biāo)志位
        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軟件設(shè)計(jì)
Android APP是借助Android Studio來(lái)開(kāi)發(fā)的,界面比較簡(jiǎn)單,通過(guò)編輯框輸入esp8266的IP地址和端口號(hào),esp8266默認(rèn)的IP地址是192.168.4.1,端口號(hào)是8080,這些都可以通過(guò)AT指令進(jìn)行修改。布局頁(yè)面的xml代碼我們就不貼了,熟悉Android開(kāi)發(fā)的讀者很快就能根據(jù)截圖編寫(xiě)出來(lái),放上一個(gè)APP界面的截圖:
6.png


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


負(fù)責(zé)連接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("斷開(kāi)");
                    }
                });
                new HeartBeatThread().start();
            } catch (IOException e) {
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "連接失敗", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    }



回復(fù)

使用道具 舉報(bào)

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

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

使用道具 舉報(bào)

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

好的,有時(shí)間的我試試,謝謝
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

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

受教了,感謝
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

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

快速回復(fù) 返回頂部 返回列表