找回密码
 注册
关于网站域名变更的通知
查看: 509|回复: 4
打印 上一主题 下一主题

51单片机通过WIFI模块ESP8266控制LED灯

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-9-17 11:16 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
一、系统方案
1 ]/ s; c5 G( X) n' i
" N: h1 [1 y0 M. }& Y- Z# q

) y* U8 e6 I8 [( l% h6 ]手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯的开关控制指令,ESP8266将收到的数据发送给单片机,从而实现对LED灯进行开关控制。
5 e+ T% \, [- L; k5 ^6 P) M6 J
  u) }- ]) v+ W
7 l9 S& K  j7 N7 Y$ S, P

5 ]  n' \+ p' Q. J
3 b2 {& ^8 F' Y1 R. l# R9 I' i2 U4 C
设计好的实物是这个样子:6 ?8 T! E' Y% U6 O  K, N' f3 z! x

- n; f3 }* O- C
8 Q& o8 a" k4 V6 C+ ^5 P! k3 k

! e0 O* b  Q$ G1 r, v; J+ @
9 J+ p/ J* s  A5 a) g9 G( U
二、硬件设计
6 F3 @0 Q0 K8 n4 ^( X& X1 N+ e. R3 _- w  J0 r: b1 Q

& z# W2 e. {) BESP8266模块作为一个透传模块使用,RXD、TXD分别连接51单片机的TXD和RXD,VCC和CH_PD管脚接3.3V电压,GND接地,只需要连接这些管脚,ESP8266模块就可以正常工作了。在单片机P2口上连接了三个5mm的LED灯,分别是红黄蓝三种颜色,我们的目的是通过手机APP上的开关控制着三个LED灯的亮灭。
7 s; W' i1 B# t1 S
" ?  r: s- _* ^5 M2 [
6 @; t& S& U5 ?1 k
. n' A4 P  @& Z4 ?/ b1 `$ x2 m
  w! Y* N! x. t
ESP8266实物管脚图
7 {- t* R& G. j; Z! P  n! K8 G; F! o# I% N. |: d" n% \
( T7 K' n1 W* V4 H( x' ?; I
, l0 F8 s1 t, b1 @+ L
  E7 @3 g% F% M' _% H6 S
三、单片机软件设计
: N+ {0 ]8 Y! V  I/ K, m7 Q" h9 u, h2 ~7 Y' Q, v. j

2 c4 \' r. I3 y  }, |4 w硬件的连接不复杂,接下来主要是单片机和手机APP代码的编写。! ^: F( F% S4 n$ W7 m

  t. Q7 w6 F: B

6 G6 p* C$ |$ y3 |! {6 V单片机代码主要是串口初始化、串口中断和ESP8266的初始化。首先是串口初始化:* y5 D7 h$ \9 N3 E9 E; u% m" k" @
8 ^* c0 G! q! F! N' P3 c1 e

  Z3 m7 M' L( D" v* ~. q$ Z4 J% [        TMOD=0x20;                //定时器1工作在方式2
& j5 m. _: F' J        TH1 = 0xfd;                //波特率96000 q# X$ g7 K7 S% t& p: x' `
        TL1 = 0xfd;
0 D1 U9 v# J# W        SM0=0;                  //串口工作在方式1
" [8 O  N  j# {  x        SM1=1;
7 X; P: K% ?) I# u+ ~4 M5 p        EA = 1;                        //开总中断
* \4 b7 n5 v# \- z        REN = 1;                //使能串口6 v- o+ T# n( O
        TR1 = 1;                //定时器1开始计时
. r& g3 E! \+ M. F+ R然后是ESP8266初始化:& p/ i8 x1 G5 _0 V/ Q$ ?2 y

& J& ]6 b9 ?/ P! n. {, A

/ f( ?% ]: {1 z$ r        delayms(1000);                        //延时
( D. ~: e3 g3 R0 x# |        sendString("AT+CWMODE=2\r\n");        //设置ESP8266工作在AP模式下" `* S! X6 i6 P$ r5 K7 r6 F
        delayms(1000);        7 e1 H5 G& H0 L% N: V' ]
        sendString("AT+CIPMUX=1\r\n");        //允许多连接
. K+ v3 |& |9 s7 M' s& V( I3 C' Q5 `        delayms(1000);       
. u" I4 p1 Q( y% {0 D6 e        sendString("AT+CIPSERVER=1\r\n");     //建立服务器: W3 y* T' |' t3 f
        delayms(1000);       
$ J3 `: S4 @3 W4 ^) {        ES = 1;                                      //esp8266初始化之后开串口中断
- |; N6 J$ V2 l* u3 ^$ n贴上51单片机负责串口发送的两个函数:/ ]$ c9 _- B. [, |, H" {& g+ z

6 }; Y7 n* f8 k' `4 {0 ?

% a3 q# }, q, K1 _//发送一个字节
- ?5 ]. x- G6 H5 {: Q/ Uvoid sendChar(uchar a)% S: c0 V- V% G- i/ @# N9 p
{  t/ f# U% h' K# z+ C, @, @
        SBUF = a;/ ]: ]  R+ E0 ~9 s  l9 j
        while(TI==0);& D: A- @: a% J
        TI=0;7 D# t/ B2 o5 H/ ~( u. w' N4 P8 E
       
3 l9 i% ]0 v& m# H* y9 ^}+ m! {  l5 w3 I$ `" Z1 c& [
( ?3 x& o# v3 G
//发送字符串
4 w/ E+ J( r' jvoid sendString(uchar *s)
+ `: e- g( {& r/ L0 t2 Q{
$ O* F1 i' e  f! H; _- f1 O# Q        while(*s!='\0')
4 O5 e" [( k# m9 V; d        {
5 \5 d) L: S2 d( ~/ h6 u# f' e, q% t                sendChar(*s);6 }: n) z) a/ i5 t
                s++;
! f: f# U" y8 G; [        }; m* c6 ~, C; \+ K& |% q9 {7 J; M
                3 A" ?" v% t" K
}
* P$ V& s8 n0 V8 W/ f1 j7 j在串口中断中处理接收到的数据:- @0 I- Y7 h; P9 g
. p4 r3 Q$ }& O0 I% a1 N
- y! V6 L: q0 q8 ?
1:打开红色灯    2:关闭红色灯- P7 b5 L" {; U! E; r7 ~8 X
3 A+ t6 W4 e. E9 a7 B
( Y  `7 N4 [- M2 W% |8 I
3:打开黄色灯    4:关闭黄色灯
# k  Q2 s: p$ Z7 x1 ?
- m5 Z& @% d! Z# d# L/ ^0 y
+ V5 g. x7 v3 c: H9 J# p+ q& [
5:打开蓝色灯    6:关闭蓝色灯
$ r' U4 Y, r; J7 m2 X* b8 Q  a
' Z" a  \! T5 C$ l, i: e
7 b/ w( P& ?% q1 L1 O
esp8266在收到数据并转发给单片机时的数据格式:+IPD,<client号>,<收到的字符长度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客户端编号,esp8266最多支持5个客户端同时连接,也就是说客户端编号是0到4,在本设计中由于只有一个客户端与esp8266相连,所以客户端编号是0;5代表收到的字符长度;hello是收到的字符。在本例中esp8266发送给单片机的数据是+IPD,0,1:1,我们把接收到的字符串缓存到字符数组中,所以在处理收到的数据逻辑中,首先判断是否是以'+'开始的,否则视作无效数据,然后判断数组中的第十个数据,因为第十个数据才是上位机发送过来的数据。, E+ m8 l- P' P' ^. ~$ G
! p; v, l* e3 U. r* T$ V

  N& ^8 l/ Q) Rvoid uart() interrupt 4
1 t$ s4 \: K# X{
) T  e1 N: E! t  p    if(RI == 1)   ! g5 b% Q, ?# N. c9 E# K. @' H! ~
    {
5 D4 T' K2 j- `( [* _) W        RI = 0;     //清除串口接收标志位7 i& h. v3 D5 h+ ]  N$ Z; n
        receiveTable=SBUF;
: {$ }  Z% f. u5 U( _        if(receiveTable[0]=='+')( e* f3 k8 @2 T, U- c: |
        {% b9 T) \5 {4 ]0 V
                i++;! J' C7 H7 p; C( {
        }
( c9 i. f* m, q& e        else
  ~" i# t4 H; z( [! L        {
+ p& o. u$ S% O$ }* t$ ]* `                i=0;9 X. q( |7 U3 y6 C4 Z4 U
        }& J+ ]) d9 v8 M, g2 J  _
        if(i==10)$ C' g2 O7 ~: `
        {5 c/ [5 p3 o5 L$ U0 D) v7 T* i
                i=0;. f' x8 v0 C/ ?7 [6 k7 E/ j) `
                switch(receiveTable[9])
: e8 A7 Y; v" v2 f+ p! h                {/ N, o+ ^' r8 ^' H
                        case '1':
5 i. ]  h3 K6 ~                                RedLED=0;: ?9 i. _, d- t" _
                                break;
, J6 o) r$ R) X9 a5 |9 L                        case '2':0 t# A6 H3 Q" o
                                RedLED=1;4 l/ \0 L- P+ n0 @7 B8 V$ d. E# I
                                break;
4 D3 c$ O. q% o! y. q0 @" ^, H                        case '3':
! k, L. S# W7 e0 j                                YellowLED=0;. _/ }: ~4 y- G: y* Q
                                break;
+ C3 n! g: r) T6 [9 h6 J                        case '4':" _  }$ U5 \3 d, @5 k4 ?  O1 J
                                YellowLED=1;0 H: S, Y* ^2 [
                                break;4 B: |- ?: c6 j3 k
                        case '5':
2 P- L$ m- v+ l- K2 P                                BlueLED=0;
0 d4 y/ N  R) X" {& j; R                                break;1 {2 @6 Y) p, x) x" H- v$ W0 g
                        case '6':$ j+ }2 p$ ^0 t0 u: k
                                BlueLED=1;
0 Z* O# o" R$ @, a! x* M& B" p- I* U                                break;* ?& v  X  T" c# D
                }, h1 t5 X- c& Y* e
        }
  c1 E( W, b6 F2 K6 s) P) F) n    & U( b9 ~- e9 l$ Z, T3 [* P
  }! B' B* {9 w% G& ~& a
}! e3 E4 b: i4 V, P9 W; L
四、Android APP软件设计2 o5 E0 u" t" I# s. |: S$ f4 M+ n

5 C- j2 W) T, I. C( k2 `+ I
! X0 P) }# F6 r8 j
Android APP是借助Android Studio来开发的,界面比较简单,通过编辑框输入esp8266的IP地址和端口号,esp8266默认的IP地址是192.168.4.1,端口号是333,这些都可以通过AT指令进行修改。布局页面的xml代码我们就不贴了,熟悉Android开发的读者很快就能根据截图编写出来,放上一个APP界面的截图:
$ \/ B9 X2 B) }4 o/ t% t
% c( n0 t$ g( ^) C0 `
) ]0 c' m" ~+ H' z; @$ I1 E

2 l: |) t- g. `

0 ?  R7 w8 y. h. J9 B* A/ H9 W, K7 L! W

, J# F3 G1 f8 [1 y6 _我们主要看一下逻辑代码部分:8 o" J) c/ h$ |  o3 D- W6 x' G1 b
' ~. q9 @  k9 b; q" x* e( \
+ s2 z$ X1 e: q5 c/ i6 C$ k& \
首先是控件的初始化和按钮点击事件回调的绑定
% [: J" h9 v# F  z7 u2 I$ D- X! ]; E3 w  {

' |4 C& D; h$ c9 A! O5 V2 W    @Override! W' Q6 e. j4 [! {- V% I- A7 q( F
    protected void onCreate(Bundle savedInstanceState) {7 J, @, t* t+ I' s% v8 n
        super.onCreate(savedInstanceState);
6 t, A# N4 M  h, a        setContentView(R.layout.activity_main);
$ T2 L% e9 u% M" I/ Z* a        mBtnConnect = (Button) findViewById(R.id.btn_connect);. b- Q$ T! R* S/ r2 I' {' K% }' z: |( |. v
        mEtIP = (EditText) findViewById(R.id.et_ip);
3 u( |0 W5 T! L5 i        mEtPort = (EditText) findViewById(R.id.et_port);
# N: X4 w4 }! T1 q  [        mBtnRedOn = (Button) findViewById(R.id.btn_red_on);
( H! z9 `& Q( p- X5 A8 q4 k        mBtnRedOff = (Button) findViewById(R.id.btn_red_off);/ p/ `2 d8 K  i0 R5 }" h  N
        mBtnYellowOn = (Button) findViewById(R.id.btn_yellow_on);4 D5 z; G5 F/ x+ x
        mBtnYellowOff = (Button) findViewById(R.id.btn_yellow_off);3 p% k3 N$ N! [& B: |
        mBtnBlueOn = (Button) findViewById(R.id.btn_blue_on);
0 t3 M/ d/ V5 H8 w- Q+ L! h1 ]        mBtnBlueOff = (Button) findViewById(R.id.btn_blue_off);; V; ?+ z9 o- ]* f. W
        mBtnConnect.setOnClickListener(this);7 d0 ?* X+ k/ S$ h
        mBtnRedOn.setOnClickListener(this);0 r0 Q  b" g6 j
        mBtnRedOff.setOnClickListener(this);
" t2 [4 U5 s: z        mBtnYellowOn.setOnClickListener(this);7 K) \" j6 H; A* K9 b
        mBtnYellowOff.setOnClickListener(this);( R0 E3 D/ I3 |9 l
        mBtnBlueOn.setOnClickListener(this);% k$ k5 C7 ?! O' k# f" L8 r
        mBtnBlueOff.setOnClickListener(this);
6 \, E9 h& U6 F/ p1 O( N+ K' P5 s
3 u! s9 I+ ]: H* ~8 N, z    }
! N+ p0 `1 C1 ?按钮的点击回调方法:
& }1 |( f+ }1 R2 j3 {7 e4 i4 ~8 q' o0 C  m) I* [
2 s3 `% e" O& N. Y9 k
    public void onClick(View v) {
2 ]! B9 z& O, t        switch (v.getId()) {& r0 c) \2 j, g( W
            case R.id.btn_connect:3 g, p/ B. ]4 n1 d1 q% a5 W
                //连接
/ A4 c: |8 c/ B( B; i9 s9 Y                if (mSocket == null || !mSocket.isConnected()) {! h0 p* r. P/ G" ^* D& n# U0 Y8 X
                    String ip = mEtIP.getText().toString();
+ a% R. f( `8 S+ U% P                    int port = Integer.valueOf(mEtPort.getText().toString());* E, f# u/ n& T1 u3 O: @/ Z! F7 K+ g
                    mConnectThread = new ConnectThread(ip, port);- U6 x. C- ~' T6 r% P6 `3 x) \
                    mConnectThread.start();
* W; Y  ^) t) R: ]8 R0 }                }
* U0 {0 j0 c2 J: O: e% O                if (mSocket != null && mSocket.isConnected()) {
' }0 N9 v! ~) b. G, a                    try {
( H, V9 {" @4 B" r. u                        mSocket.close();* D* Z# Q4 ^1 K" U/ X5 s- Y2 `
                        mBtnConnect.setText("连接");
: G3 O8 [* q7 g" R: ]( W                    } catch (IOException e) {' D- i6 o& U8 v6 i6 f9 `' D3 ]
                        e.printStackTrace();
; X" _) x( z) c7 X                    }9 A' H1 s8 O9 u) A; \
                }2 ?. }( l; P+ W0 c8 f  O& Y

, g6 \6 R, W4 j* J4 a) c4 e6 f" a                break;
& c9 k; I+ l& C# q1 ?! c            case R.id.btn_red_on:         //开红灯* g. }  |5 T" o4 d. f
                if (out != null) {
9 ?" d- a6 ^+ _$ n; ?                    out.print("1");
" _3 Z% |! A: l% P1 P: w                    out.flush();4 _& m& [- V+ j5 U
                }
( V  Q  v) a6 h" Q* F                break;
8 [# D' V7 O# l& h+ U            case R.id.btn_red_off:        //关红灯0 k9 S$ r: K5 p+ }$ d, T
                if (out != null) {1 G/ p" X* ^' A  x; l: a$ W$ P
                    out.print("2");
  ~, V5 k3 V+ v2 O                    out.flush();' B8 i& I/ W* a
                }
. }3 j& O+ w6 }& Q9 a                break;% G" O% L- w8 B: s' c; n3 X; g
            case R.id.btn_yellow_on:1 [0 ?9 g7 ~7 ?( h0 j) q) }) o
                if (out != null) {- Q" F) x3 x; x9 Z6 Q
                    out.print("3");1 V" u" {4 Y$ K1 e5 d+ ?9 f% D
                    out.flush();
% n* V  D# r0 E" d- }                }9 c! |( f! n' D) C
                break;" ]* x6 o0 P' M+ T& e
            case R.id.btn_yellow_off:
1 y  v0 d! J( P$ J0 R0 H4 M                if (out != null) {
. ~$ d. U- P. a9 ]4 v1 F* I                    out.print("4");  g! z/ H# y3 Z/ V& O) R/ f
                    out.flush();
8 A4 [8 m; o5 X. n1 g" ~) t                }
  S5 H2 e# _" {                break;$ ]1 j  h6 A: |8 B. t# W8 F& g; V
            case R.id.btn_blue_on:# n& L/ ^2 ?- a7 V/ A
                if (out != null) {) B1 v2 o( C6 ~% k5 L2 O
                    out.print("5");6 N' i; R( C6 k
                    out.flush();* b, k- a* l# I! ~( \
                }: d+ u' f7 W& t8 Y6 f2 Q
                break;
6 m  c+ z/ f! q' M0 x- P$ b) A            case R.id.btn_blue_off:
) F8 l- P# Y' @  B                if (out != null) {
9 a5 }+ m8 S! G$ q$ i1 {  H/ y" A                    out.print("6");7 v: @% a, f/ y
                    out.flush();( g9 r9 w, ^- ]' k, Y; @& N% d
                }
2 e8 S' F+ V+ h; }                break;/ k% L3 D9 X# z2 v. m; t
        }. H' O! l" m0 O5 @3 W! k7 \9 h
    }0 \& |1 Q) [& C3 z; ]# z1 ]

+ L0 r, l0 A/ o& d负责连接esp8266的线程:
  C  K  ~2 L2 ~/ t6 {; Z$ D6 W1 \' d* P- D' t
1 U; Z7 T+ }+ P
private class ConnectThread extends Thread {
6 ^4 x( \6 @+ v9 o- A- T7 X        private String ip;7 b& P/ p: K  {0 F0 g! [3 {, k
        private int port;
6 k7 ~- Y# O  B# Q; V : t% X) h2 m2 f0 F) C. b  O4 `3 _
        public ConnectThread(String ip, int port) {3 j# v% }8 G8 G( ?/ e; C
            this.ip = ip;9 U3 P+ t+ ]" c: V$ V$ z6 V
            this.port = port;
2 ~- f* t9 [: a3 U1 p4 ~/ z        }
) @+ H$ u& l# m + x/ j- O  i. i, ^! z' y1 Y
        @Override
2 V( G) F+ q6 W- i) c+ V5 M        public void run() {
) |6 F+ Q8 }, ^            try {
, v* ]: f2 C3 M1 @) ^3 O$ ]                mSocket = new Socket(ip, port);
5 M; B. _+ m4 H% w0 R                out = new PrintStream(mSocket.getOutputStream());2 m6 S9 E+ `9 l2 O! ]5 B8 C  D
                runOnUiThread(new Runnable() {
& a# A% W1 [  B                    @Override3 t/ \, F" F; F; ~4 e8 C1 x& I1 P
                    public void run() {! Z$ j: b5 V6 k% x
                        mBtnConnect.setText("断开");
, Q. k6 R6 R2 t: C3 u; T; {9 w                    }
' d7 [: Y% [4 U3 `                });2 W5 b8 d; Q9 h) ~& h- J6 o& N, c
                new HeartBeatThread().start();+ B5 ?$ W  y+ [
            } catch (IOException e) {' _' c/ h# B% {6 m, j! |
                e.printStackTrace();; [) M% z4 o7 h
                runOnUiThread(new Runnable() {3 ^6 `; l2 Y- m5 K3 t( k
                    @Override$ h  T* C4 M: ?+ Q/ @: Z7 [
                    public void run() {. E* _+ V0 j; n2 f( f6 |9 d. \
                        Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
$ _% d2 R- D6 m$ z. b                    }( p8 T0 B2 L4 k1 M6 Z" W
                });
6 @* l! h$ k2 [$ a) ~2 }: P/ ]8 h            }
/ _) n/ |4 V# X) u: u1 j: a        }3 f* l% f+ v5 p  E+ s1 j
    }
3 i. s0 n6 b4 @0 A" ~. w$ }3 r& O- ^: {' R, w, X8 j
) M5 t; U6 D* {9 S" M6 u0 i
3 n/ F- z; m; m

" G: o( }  }2 M% Y6 P2 C

该用户从未签到

2#
发表于 2021-9-17 11:28 | 只看该作者
通过APP控制灯的亮灭成功率高吗

该用户从未签到

3#
发表于 2021-9-17 13:54 | 只看该作者
是怎么进行通信的呢

该用户从未签到

4#
发表于 2021-9-17 13:59 | 只看该作者
学习了  感谢分享
6 X9 e5 u( r: @2 K

该用户从未签到

5#
发表于 2021-9-18 11:01 | 只看该作者
强烈支持,谢谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-20 06:40 , Processed in 0.171875 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表