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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
一、系统方案7 w- t9 M1 K! b* N6 K
2 x/ N5 B  s! N1 X5 k+ n
' F$ ]- R' ?' }. g' `
手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯的开关控制指令,ESP8266将收到的数据发送给单片机,从而实现对LED灯进行开关控制。5 ^( L/ n' t- {* e6 l; j
# R6 i. f, M7 m/ s$ W

/ c, Y% B: \5 h2 ?# K( f

4 f- f* K6 B2 w+ I

. o. M# B8 z+ a. }0 R1 X5 O设计好的实物是这个样子:
' @6 `+ b1 \# y. P$ K; u% Q
9 ~8 M& j. C4 l1 Z

6 ~3 |* [$ W( B
1 N$ j/ C, D3 L- g! D% n
+ V; v* x9 v- B
二、硬件设计2 ?6 h* p$ p5 O

  b4 N$ _5 J& g3 r! [5 v
. }: z7 x1 c1 t+ K
ESP8266模块作为一个透传模块使用,RXD、TXD分别连接51单片机的TXD和RXD,VCC和CH_PD管脚接3.3V电压,GND接地,只需要连接这些管脚,ESP8266模块就可以正常工作了。在单片机P2口上连接了三个5mm的LED灯,分别是红黄蓝三种颜色,我们的目的是通过手机APP上的开关控制着三个LED灯的亮灭。
& k+ I, E0 p4 X  |2 W: K
" N; G; ], A8 I- F( b" y. c

( M( b$ a- y  w$ M! Q( ^4 j

4 X" @5 g8 v( T3 Z
/ ^; ~4 x3 _# N- i. A
ESP8266实物管脚图; I( S6 \9 y5 o: A

, E/ F% x+ ~( E6 h/ \

; `. ~& N* T7 d" p3 y
: }5 H6 R- f9 y9 u9 A  S

) E! U" D7 L2 o8 s8 c. a  o/ ?  w三、单片机软件设计
9 I9 u) u9 ]6 K3 q! F" S) L
/ N# W6 S  I8 k/ F
* v' e5 v- l, y0 L0 f
硬件的连接不复杂,接下来主要是单片机和手机APP代码的编写。1 L1 F; x. ~- p( @, v2 E9 S6 a
, ~* b+ ~; \5 W  ~+ v4 q% l. O

0 {8 b. N8 ]* Q3 U8 S3 S单片机代码主要是串口初始化、串口中断和ESP8266的初始化。首先是串口初始化:
! ^2 ~( V9 O& h% I& w0 a& H
9 z$ \) r3 F$ S; \/ `4 B

, w) X- u- c& O1 j) P3 w# S5 L+ V        TMOD=0x20;                //定时器1工作在方式2
6 c1 E+ `0 ?# i& u# D* O        TH1 = 0xfd;                //波特率9600& M4 C" u* F) }% m
        TL1 = 0xfd;) @" a; c/ i# p
        SM0=0;                  //串口工作在方式10 g& T$ @- p9 x% b* t6 q! i
        SM1=1;
5 f  @/ D6 |, v- m' d        EA = 1;                        //开总中断5 |. G7 R6 Y* J' l0 {, C; h( |
        REN = 1;                //使能串口! {# s1 H( Z& r
        TR1 = 1;                //定时器1开始计时# v$ g  W; G2 Q. b: \+ f1 @) [
然后是ESP8266初始化:
" o$ k8 V. Y/ n" j" S4 d5 r' D  ~5 Z; h, F

0 A8 ~: q' {8 F) f        delayms(1000);                        //延时. S9 B; o& F0 o
        sendString("AT+CWMODE=2\r\n");        //设置ESP8266工作在AP模式下/ S8 M$ G2 l/ C. a$ }
        delayms(1000);       
8 d1 l2 J1 j8 K0 D: Q) H5 {        sendString("AT+CIPMUX=1\r\n");        //允许多连接, e! ?8 V. k5 s- R
        delayms(1000);        5 P# T7 k0 U' T( ~9 o
        sendString("AT+CIPSERVER=1\r\n");     //建立服务器, B! b% X- N/ ~2 Q/ m+ {1 ]
        delayms(1000);       
7 N5 k8 j9 m( m9 |/ \$ W        ES = 1;                                      //esp8266初始化之后开串口中断# E  F: _( ~5 b/ }* u! v9 B
贴上51单片机负责串口发送的两个函数:" a+ V, U- {9 p- J6 D
+ ]: M, H) K7 x
! X( U' X, B5 v( Y) b0 b6 n: U
//发送一个字节
  d* V" D. w0 h* ?6 X: Ovoid sendChar(uchar a)% m( z) ]' E& ?0 U
{1 m2 Q7 g& P' K8 _( t& J) O
        SBUF = a;$ a; T/ a) W' g7 W1 ^( ?
        while(TI==0);
6 n+ ^0 i8 \" p, v# I8 @; w& h        TI=0;
8 a1 m" x5 X' \1 w       
8 p/ f, I7 R2 r. j0 E& H}
0 ?! s9 Y  k' E/ Y9 S3 b
- x& L  D$ m$ _0 C/ H2 ]//发送字符串
( E% q/ k0 r7 [# k! V; T  X. Lvoid sendString(uchar *s). |- b/ ?- `1 z/ r' _7 J
{2 d4 A2 Q+ V! N. K. S$ d
        while(*s!='\0')
, c& E: C, G* J        {
: _. z" w; H& d) p+ Z  i/ ]                sendChar(*s);
8 t5 G7 `' x# ]# j) y$ w5 M                s++;3 K( K& V# t* I" n/ _
        }, ^' r/ k2 T) M/ W$ o
               
" U9 J# d& i) J: E+ s}$ ~( U0 L1 m1 H
在串口中断中处理接收到的数据:
" F" v+ x2 @8 y) D- A/ B
7 \/ @0 M$ d, a( Q  G
( q- w1 I& h7 l
1:打开红色灯    2:关闭红色灯
* L9 J: i7 z6 x7 a8 `9 N  C' x- o: A5 D; g' b$ ?/ l! ^/ s

3 \# E& U2 z* O( k$ Z/ z3:打开黄色灯    4:关闭黄色灯2 L; E" w( G  a2 G" H2 b& \" P

1 ^: d# |. Q: ^8 I9 F

( f$ Z6 `; P( Q) D5:打开蓝色灯    6:关闭蓝色灯
4 I* n: L$ A9 q+ U6 o- F
  I$ R6 d" Y8 v2 x. x

9 l3 i' d% s% z( jesp8266在收到数据并转发给单片机时的数据格式:+IPD,<client号>,<收到的字符长度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客户端编号,esp8266最多支持5个客户端同时连接,也就是说客户端编号是0到4,在本设计中由于只有一个客户端与esp8266相连,所以客户端编号是0;5代表收到的字符长度;hello是收到的字符。在本例中esp8266发送给单片机的数据是+IPD,0,1:1,我们把接收到的字符串缓存到字符数组中,所以在处理收到的数据逻辑中,首先判断是否是以'+'开始的,否则视作无效数据,然后判断数组中的第十个数据,因为第十个数据才是上位机发送过来的数据。
$ E+ c& S( i( j8 X' v7 o3 T& H2 `/ c. T! w1 y8 m# x, |
( I& A, k- h) r# \1 T( }5 d. `
void uart() interrupt 4
$ j1 q. d9 p  R' Z. E{
7 A2 K# }# {5 D) d1 K    if(RI == 1)   
  H1 C1 ?0 Q& o3 m+ @    {' V  a7 }8 F, m" l
        RI = 0;     //清除串口接收标志位, y; ~9 Z: Q/ s6 p4 f3 j1 T% v
        receiveTable=SBUF;% P) K" b5 G2 a" v7 P; T* H
        if(receiveTable[0]=='+')! W8 t* c: X5 f2 y/ _3 I1 g
        {
. ~5 V3 E4 ]9 l* {                i++;
3 k5 M+ ]  b, ~4 V9 V" K        }, Q! v5 C2 k! n* [7 [( t
        else# o8 C/ X9 W- W' z2 W% ~+ u; M3 f
        {
: S' w0 g, s7 X3 A5 ^                i=0;3 Z/ @+ z) y( U4 C( k1 d
        }' f/ x6 G3 V3 z8 U" L. B
        if(i==10)
/ C8 o1 T( B+ o+ b* j        {7 Y* \7 Q" S/ s+ i6 J, ~* y# L
                i=0;) p" Q( G4 B" O
                switch(receiveTable[9])& y3 w4 Y) {* m7 _# j
                {* m- y8 c% ^* f" E
                        case '1':- s/ @+ k7 J( G
                                RedLED=0;1 m: Q& Z+ w- n9 Q0 K! j
                                break;
7 R; Y' A- k: A8 }8 v- t% u' E0 a# u                        case '2':  ?% w1 p/ H" |  r$ D! K; ~8 m& F5 t
                                RedLED=1;5 x5 E' l3 k# Z- Y/ _6 y
                                break;: N$ h4 w2 I. c; E4 r
                        case '3':+ c4 @# ^* x0 C# a: A
                                YellowLED=0;' @7 z) N9 o, g. Y/ T. c
                                break;
  W6 ~1 M  n/ q6 c! \: z+ @                        case '4':
) W( e4 i+ I0 h& m; p  T. {                                YellowLED=1;0 O7 Z4 M* v: [* X' X9 C8 T
                                break;
3 t: D0 l. V+ R                        case '5':' ]7 d2 S; `! v- {. P8 g
                                BlueLED=0;4 u8 e  ]% S8 b% A# ]3 K
                                break;
! p, v" Z/ C3 V9 A4 U! i- \                        case '6':2 q; ^3 X) W  _6 P+ z
                                BlueLED=1;' F6 L2 P0 j3 F& s' P
                                break;
1 p5 Z7 ?, J( D1 o  X                }/ e2 S& j2 Y5 [8 g$ k! [1 }
        }; r' Y8 o% w1 q: Y5 D) U- w
    0 q1 `- ]8 ~4 @
  }$ j' l0 T+ d8 W
}
! b' l& Z( `( t四、Android APP软件设计
9 u+ F% ~! {7 L, R* q) a& S1 U6 H  G
; B; Z0 ~; T$ w+ y6 X' Z7 G6 `
Android APP是借助Android Studio来开发的,界面比较简单,通过编辑框输入esp8266的IP地址和端口号,esp8266默认的IP地址是192.168.4.1,端口号是333,这些都可以通过AT指令进行修改。布局页面的xml代码我们就不贴了,熟悉Android开发的读者很快就能根据截图编写出来,放上一个APP界面的截图:- g9 _1 ^5 d& N" D* _
3 K) O" @: f* T; p" P

+ z% @2 {& S" l
1 A$ B4 w8 z: N0 X" N

( V" o8 y) U8 ~: g2 e% ]$ H$ D+ d* {' q" ]  d

1 @2 i$ b  b7 y我们主要看一下逻辑代码部分:2 q( j1 l" Z( v; Z& A: H

, G/ X9 j, G. D7 U; z

0 X) ^$ r. q- x1 h0 C% J首先是控件的初始化和按钮点击事件回调的绑定9 s: `2 [- n, U& I0 g4 a

& o& s. i1 d3 x4 h5 H- `
) s: i( U7 i  W! {
    @Override
6 a1 {/ c' ~( k3 R2 N6 h: K    protected void onCreate(Bundle savedInstanceState) {! c' C+ e( x: _  J0 I
        super.onCreate(savedInstanceState);
2 v7 o) U- C8 j- F' Z2 f) k% ~        setContentView(R.layout.activity_main);! M) i* a" k+ ~  g* ]& O; X0 a. k
        mBtnConnect = (Button) findViewById(R.id.btn_connect);  ~1 [) b2 J' [1 g; S/ o& V4 Q
        mEtIP = (EditText) findViewById(R.id.et_ip);) o% y# }2 e# u8 h# ~
        mEtPort = (EditText) findViewById(R.id.et_port);1 b$ T4 v/ h8 q7 }- I4 ^
        mBtnRedOn = (Button) findViewById(R.id.btn_red_on);
( q5 \5 w! F% H$ E        mBtnRedOff = (Button) findViewById(R.id.btn_red_off);8 p' e1 V9 C+ @# c9 {. A
        mBtnYellowOn = (Button) findViewById(R.id.btn_yellow_on);
# V0 I6 y. E5 h, j$ }        mBtnYellowOff = (Button) findViewById(R.id.btn_yellow_off);6 V5 E4 {0 i9 a2 z7 a
        mBtnBlueOn = (Button) findViewById(R.id.btn_blue_on);
: `& X" [- n- J: H0 i; G        mBtnBlueOff = (Button) findViewById(R.id.btn_blue_off);
, E9 h$ D' u" x! t+ B: j4 \        mBtnConnect.setOnClickListener(this);3 q- @. ]/ a: u* w' o( d
        mBtnRedOn.setOnClickListener(this);
% q+ U% T" o/ h% u3 O0 |3 s3 y1 b        mBtnRedOff.setOnClickListener(this);
+ t7 l1 X# S/ H. N        mBtnYellowOn.setOnClickListener(this);
& J0 l' ~# m* L' s4 b5 ^; i6 |        mBtnYellowOff.setOnClickListener(this);  r# `4 f  e# F. q4 \) \
        mBtnBlueOn.setOnClickListener(this);
% o1 M( c% H& ?0 o' p; Q  S        mBtnBlueOff.setOnClickListener(this);# H# r5 Q( a+ Q4 ?. M
' _! K* {, r5 t) W9 G5 T
    }! r* h, b: ~7 [0 D" D2 s
按钮的点击回调方法:" N6 J8 B9 V: O  U7 Q

. K, v2 A! v; t) o( w0 R" d3 b
+ K0 k2 Y5 W% B" g" t/ i
    public void onClick(View v) {
- {" w# P- x, x; U  D9 P        switch (v.getId()) {" D0 U" Q3 Z$ @* `5 M+ K7 N" \
            case R.id.btn_connect:
% ?3 {  A; |8 z5 E2 l                //连接
; O# U* K7 \* Y7 N' E/ t, p' f% S                if (mSocket == null || !mSocket.isConnected()) {
" {; b: M5 y0 \                    String ip = mEtIP.getText().toString();
  n1 V9 H! L+ i4 C6 H5 i& W0 d8 a                    int port = Integer.valueOf(mEtPort.getText().toString());5 d: P6 \& `- b) B- ?( Z9 |
                    mConnectThread = new ConnectThread(ip, port);
6 p+ r) X0 C* s6 e6 o' ^* u                    mConnectThread.start();3 B5 x; [  |3 L3 i/ x+ ?
                }
& b- t% e5 v) n% o7 j                if (mSocket != null && mSocket.isConnected()) {
0 \& F! Q& g; ?2 x                    try {
7 C5 o0 ?+ k7 o9 Q                        mSocket.close();9 k5 S- Z( c0 Y0 Y& a1 Z) w
                        mBtnConnect.setText("连接");
- d; P# \; E) n                    } catch (IOException e) {
2 t% q8 n+ y8 a% p( L/ @                        e.printStackTrace();; W# |" t! p3 l' T7 e
                    }, ~, e; b( w, B# N
                }7 E- T2 O+ F( _5 f9 M" I' j
/ ~- J/ G2 }/ e* W6 ?2 J) i& l# ?; s
                break;/ `+ f* [7 W. M+ L6 V6 j6 Z( J1 }
            case R.id.btn_red_on:         //开红灯, p. S5 y* ]( }
                if (out != null) {
- m$ [7 s0 c2 q  G, E5 g                    out.print("1");$ l& }- P* s% w3 @3 {
                    out.flush();
. m  A" e* ^. {* U                }) S1 m9 R- a$ W
                break;! @, r# S1 a  j7 ?
            case R.id.btn_red_off:        //关红灯
% X; z4 f5 Y$ ?/ s6 O' q                if (out != null) {5 G, \* J8 C4 m6 H: A6 i. `1 a
                    out.print("2");8 y7 Z. t/ h* o& O+ a; I& v
                    out.flush();
1 T- V" C$ f& g                }( {# v, m( O( Y! D8 P$ X- |8 H- t! P7 o  R
                break;
. F2 D9 u: P3 ~  y- K' M            case R.id.btn_yellow_on:
" {9 G# [. G8 O: \                if (out != null) {9 P: ?2 R$ S+ V3 t" p
                    out.print("3");1 O5 n" I3 V3 ~) @* q, S! X
                    out.flush();' l7 D; Y) p+ X7 g# H/ O+ }
                }" X8 A% ^5 p$ E9 k# C
                break;
6 m% \9 [4 n7 ^/ y8 p( v7 e            case R.id.btn_yellow_off:
$ S4 A: `" p: z1 Y9 O0 K. E                if (out != null) {6 f# [% T" w$ p+ P) e) \
                    out.print("4");
1 a: }3 Z5 ^$ N3 \                    out.flush();6 a3 X' q7 n( y+ r+ X
                }3 O, H: G( ]! O% C1 j( a5 i
                break;
  v0 M. ]1 y  E- ?            case R.id.btn_blue_on:! P% g# ~( S$ X4 Q% q! z7 H
                if (out != null) {; v3 P) d; r8 s& u7 z0 y0 R; q( i0 a6 P4 S
                    out.print("5");
; r! K/ R; ]6 `$ p* v  M! \7 V                    out.flush();
, D- {% N! @  ]4 r. ?8 n                }
: J. T0 Y) G6 O1 ?; @                break;2 i, V0 o+ `, Z( d
            case R.id.btn_blue_off:# g! K% u6 L3 N  y9 E. T' N5 Q1 |0 t
                if (out != null) {
: r2 l  E/ k  d" \  O/ D                    out.print("6");1 m9 z. z4 y1 r5 e
                    out.flush();+ |+ E; O& C* x
                }# R0 \' F9 I, Q
                break;
( [  D' M$ J6 Y% o2 G  c# T        }
0 Y' ?9 o+ Y/ n, g$ d0 u' @5 Y3 X7 K    }8 y- J" M% }) Q% r* I
6 Q5 R/ F$ C3 Q9 ~* W
负责连接esp8266的线程:- L, G2 @8 [8 Q" ]' m9 O' {
+ N5 i/ L/ [. M$ m! G9 a( k& v; h
3 I% B$ g  B) T
private class ConnectThread extends Thread {- X% F+ F  _9 `1 a! `
        private String ip;& C+ H5 t( p' ^9 T; F1 k
        private int port;
' K5 \% u, W6 T- _ # U) G0 h+ t  H
        public ConnectThread(String ip, int port) {$ G: G; G0 N4 {) t# l  c
            this.ip = ip;/ F6 v8 j9 J; a  \8 O' Y
            this.port = port;0 x4 H$ x% ~# }. n+ ~& Z0 I- c
        }
! s4 k1 d& i; v % |. \8 U. A6 @2 p
        @Override% G  s+ b0 u( b7 D2 J
        public void run() {8 n; Y8 K- l$ i  i( z8 E+ E+ \
            try {
- T& ]# D1 [7 s1 Y. }( `; G; S                mSocket = new Socket(ip, port);
, }1 Y& P  K- t1 L8 C, k                out = new PrintStream(mSocket.getOutputStream());
& y) w( e! x: e) y% }$ d                runOnUiThread(new Runnable() {
; ?: m  b, ]! K, x; M$ Y# B                    @Override' M* V. o1 ?. K- Z  O) t
                    public void run() {
) ?5 C' h8 q  s, c( P( E                        mBtnConnect.setText("断开");
; S/ M0 x$ a8 C. t                    }5 C2 \" K# Z5 ^9 R1 R, e
                });
! |! D; H* x8 i7 q1 x                new HeartBeatThread().start();/ K( ?0 [$ Y. _6 P9 y3 @
            } catch (IOException e) {6 f  K( x( {" s1 o3 k. y
                e.printStackTrace();
% o9 @: f* E$ r" F! A/ L) _                runOnUiThread(new Runnable() {
+ Z9 r8 j7 {, u                    @Override# g: ]& A/ ]- {
                    public void run() {" u8 q* F6 d% l. |, L( O% X. y  n
                        Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();) c2 V) R0 W0 E+ s
                    }
7 z0 J, u: l! w- m1 F% [                });
$ d* i5 c) k+ Y- U" ^, d            }5 X/ E: s: E, O: r! R7 W9 Y- t3 @
        }% r7 i% `  i7 p5 t5 A% W5 J8 v2 C
    }
* M6 {4 \4 {) [) Q6 |( p) F. E
- H% p% ~1 s5 w) A
) p" f& o+ y6 j$ c5 {; k

% y! u' b# K1 c) Y
/ h! {4 |2 Q; D5 Q* [* |/ @" \

该用户从未签到

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

该用户从未签到

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

该用户从未签到

4#
发表于 2021-9-17 13:59 | 只看该作者
学习了  感谢分享/ A: B6 |+ f' y

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-10-9 20:36 , Processed in 0.171875 second(s), 26 queries , Gzip On.

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

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

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