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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
一、系统方案7 n( T, o0 u9 M! |. I5 C

/ Q. {# w5 ^5 h' H

1 G7 s: E, {6 `8 L" o$ q8 b手机APP通过ESP8266 WIFI模块与51单片机通信控制LED灯的开关。下位机由单片机、ESP8266模块和LED灯组成,上位机由Android手机APP承担。我们在APP上发送LED灯的开关控制指令,ESP8266将收到的数据发送给单片机,从而实现对LED灯进行开关控制。9 e8 e$ Z; l  z4 |) T- z2 p
" c4 ^6 L+ i5 z$ X

% @6 @$ v/ V& M9 m

) [; L- e) @  K/ Y( L$ r
" f8 L( r+ y& }2 s0 C
设计好的实物是这个样子:
7 J, U. {# _, F& u- m+ b2 o2 Q" j3 g1 v

2 n) i/ R. X. ?/ u7 n  L

+ J& J* e: ?& r1 ^  C) q3 h

6 j  Z; V. N6 F0 P二、硬件设计
6 p6 S: {3 Q: X  y3 }# j/ ~1 {/ ~* K, @7 K5 Q8 F1 q5 m% f6 g
0 e6 v/ g& ?$ @/ h. W8 H' x
ESP8266模块作为一个透传模块使用,RXD、TXD分别连接51单片机的TXD和RXD,VCC和CH_PD管脚接3.3V电压,GND接地,只需要连接这些管脚,ESP8266模块就可以正常工作了。在单片机P2口上连接了三个5mm的LED灯,分别是红黄蓝三种颜色,我们的目的是通过手机APP上的开关控制着三个LED灯的亮灭。
! t3 r2 z; Z% M7 b& T
8 b' P' B  F6 b1 B- r: i3 f6 g

$ j+ q6 k% X% O1 f( O- U; ^

0 |' v, w2 J8 z$ ^
6 g4 ^# t0 L: x: Y5 K. e
ESP8266实物管脚图
4 j1 e- N. H& S2 e* `1 a2 x& B# ]' I9 {, R2 i. O; z

' Y/ L  d% c# Z6 c. O) A4 t5 ]' e

9 F2 }8 |' e3 r

2 G& x7 _4 N2 L% I. r2 B三、单片机软件设计
% @: G1 }4 I; t- r
7 G: E# |" Z, D6 I; _9 K
5 j4 ]+ Z- m( k- e: O; c+ B8 Y
硬件的连接不复杂,接下来主要是单片机和手机APP代码的编写。6 P% Z$ h* l! @* ^

. S1 y" w5 g+ [' b, Y
% z" k3 D0 J( Z0 V
单片机代码主要是串口初始化、串口中断和ESP8266的初始化。首先是串口初始化:
+ F6 k& i2 C6 }/ W
' \( W0 K  s+ `% ?4 B3 d. D: f

2 s6 ?% p! F: K% _" Y+ y        TMOD=0x20;                //定时器1工作在方式2
6 T3 b) G! L0 `# P1 K        TH1 = 0xfd;                //波特率96006 G, a$ G5 ?& k0 _5 U& r
        TL1 = 0xfd;
8 x& h( f8 n+ [8 F  o# x* r        SM0=0;                  //串口工作在方式1" V- C; q7 T' e- }& C) E
        SM1=1;
4 g& L$ o3 G8 _, X) q        EA = 1;                        //开总中断
4 F/ W6 m- D* I2 `        REN = 1;                //使能串口
% N( E; j& j4 E        TR1 = 1;                //定时器1开始计时
6 R% W' c* t7 \+ T/ A然后是ESP8266初始化:
( ]/ x) U6 u3 C+ e4 \% z: r& _1 R$ D- D- A& @
/ V# V. M2 P$ Y$ D' _( {6 ^
        delayms(1000);                        //延时+ T* A- [/ D/ u$ Y
        sendString("AT+CWMODE=2\r\n");        //设置ESP8266工作在AP模式下- d$ y6 Y- \6 |
        delayms(1000);        " C& s8 ~- X+ ~3 m5 D. [& j
        sendString("AT+CIPMUX=1\r\n");        //允许多连接
" ]  ^1 |: ?  T# i        delayms(1000);        0 y4 f3 C7 J7 W' m, P
        sendString("AT+CIPSERVER=1\r\n");     //建立服务器. A( u8 {) h' ?- s; P/ F
        delayms(1000);       
- M7 b6 s+ e% H/ Z: f8 ^7 b7 K        ES = 1;                                      //esp8266初始化之后开串口中断
3 `/ i! {( O" p贴上51单片机负责串口发送的两个函数:0 J% k' a( d% ^2 P
0 A4 M) @, b6 E, N4 v
) d/ d) }5 _/ V# Q
//发送一个字节
# j* [) m3 g! J$ J. U' H1 {void sendChar(uchar a)
  K8 f, j7 n: C& t* `: G{
& N1 M6 g" r1 w, d6 r3 k" {2 L        SBUF = a;: F& F  N  e4 p; e4 l+ l
        while(TI==0);0 N! b) E6 e. a3 g
        TI=0;$ k! `, n6 o9 Y1 T( S& w. l/ x; C- a
        - N9 W* a3 a: D/ C0 {& J3 e/ i
}
8 z; t- Z" w$ e( s
' B7 S. n" Q' ]& H//发送字符串1 C  {; b- Z/ R  Z! d, e1 u
void sendString(uchar *s)5 Z% o4 q! Z/ I" F3 ^& I
{
7 g) R- k6 S2 o: ]( S) o6 A        while(*s!='\0')
0 Y+ [7 [; R8 |  W, `# y        {/ L# H/ `( R" Z8 V
                sendChar(*s);, j" K5 @$ L) K9 i) k) T' `2 c
                s++;+ o  _/ u7 p4 k& \
        }; T4 e3 u: w1 G5 b# @
                6 |" k* B+ A/ x! S0 C
}! ~( O3 M9 u) D8 c6 [: `+ p  h' h" J+ H4 i
在串口中断中处理接收到的数据:0 y  ^4 H# z. G3 U6 Z
4 m, F  T/ |0 O
! o/ k+ G: h! d% g" R7 x+ `7 m
1:打开红色灯    2:关闭红色灯
0 o( e4 s1 [9 b6 d
/ N7 O6 K, t& W% S, p6 \
. X# E3 R% K" I! j8 P/ t/ r  B
3:打开黄色灯    4:关闭黄色灯( z" m3 T3 y$ M9 ]! h6 l
: ]1 h3 j# }2 r- `* n1 b9 M
3 [/ e/ o% h, V5 ^" P
5:打开蓝色灯    6:关闭蓝色灯5 u& w. R/ M9 `, L
9 N$ x' h$ {7 [' L  T8 E8 v

7 r: M/ ?- L# U! I" @esp8266在收到数据并转发给单片机时的数据格式:+IPD,<client号>,<收到的字符长度>:收到的字符,比如+IPD,0,5:hello,其中+PID是固定的;0代表的是TCP客户端编号,esp8266最多支持5个客户端同时连接,也就是说客户端编号是0到4,在本设计中由于只有一个客户端与esp8266相连,所以客户端编号是0;5代表收到的字符长度;hello是收到的字符。在本例中esp8266发送给单片机的数据是+IPD,0,1:1,我们把接收到的字符串缓存到字符数组中,所以在处理收到的数据逻辑中,首先判断是否是以'+'开始的,否则视作无效数据,然后判断数组中的第十个数据,因为第十个数据才是上位机发送过来的数据。
7 _6 _/ ?) \4 U0 G+ {+ H; F# y3 G6 e+ ?! G% P' s
' O1 u( i2 P0 W0 C: W
void uart() interrupt 4
7 ^, z, @5 B- ]1 s{) R/ ]6 S" [( W5 c8 ~
    if(RI == 1)   
  G0 L( l$ j1 F9 L    {
6 y7 U2 Q, E8 ~- N7 z9 ~        RI = 0;     //清除串口接收标志位
  A9 M. \' F) f8 `( ~        receiveTable=SBUF;. Z& B. C9 `1 V7 k
        if(receiveTable[0]=='+')) C9 u+ j0 H) z+ i) G
        {& _# U$ l$ T- g3 b/ F& K$ V, V+ H; n
                i++;
! n8 Q' W' ?5 ^1 e! g- A        }7 d$ P* ~7 G3 F5 F0 ]
        else5 A0 C' ^# y4 q, e# X& c+ O
        {9 O# N7 T- W. O3 }( e! P$ R1 o
                i=0;
0 G$ S5 e7 l( u2 }! O: d        }
9 p2 S  K, E+ x! W. E3 f/ f        if(i==10)3 H6 o, i' n( ]7 N' [
        {
5 b. D6 {3 c8 E7 V% Q/ F" u                i=0;
* Y% \" Q' `4 U: a- M' o                switch(receiveTable[9])+ t8 q" x6 ]2 R* e5 W
                {
8 O, I3 t, ^8 [) H1 ?                        case '1':
) H6 }' [0 x% u* j3 W6 p                                RedLED=0;
! L8 ?3 a5 f1 b8 x7 ]2 l. m: [( _                                break;
7 w0 f( N% L# \3 q1 x* J4 u$ o4 x                        case '2':* K) ]+ G, T2 O
                                RedLED=1;
8 w( ~9 W6 m. R" j: p! M& i1 }                                break;0 F5 I; R: V# ]1 ]! q6 Y
                        case '3':
7 P" k0 T& A9 c# k! R% r& t                                YellowLED=0;, X" v5 O: u# E, o# j! U7 e
                                break;/ g9 H" T7 Y  I& `
                        case '4':
& x0 b9 `1 i* n                                YellowLED=1;
9 s7 `% ^9 C4 M* m: N                                break;% s: [# ?! {3 H
                        case '5':0 |8 @8 a4 b, S; o, X: b. A9 m
                                BlueLED=0;8 L" r+ g4 T5 T4 Y0 ^
                                break;4 E8 }! N* D1 {" O+ Q8 T( q- a
                        case '6':
1 m7 @) w# m# q9 ^, u                                BlueLED=1;
% ^. m" v  O  L# L( G% a                                break;; i+ O6 g7 c# t+ J4 p+ k: z2 z9 I
                }
& j' |3 J$ f& v. w' C; }0 }        }  C4 x9 w; C" n/ {) S
   
7 i4 O/ K" o. v9 ]; E  c' X4 Y7 D  }
- n$ [8 v7 |8 Q3 `}9 ~% h) |3 Z5 w5 h/ Y1 X+ J+ v
四、Android APP软件设计0 \# A2 j5 k6 S% w* C! f
- Z- Q* ?5 A7 H6 _' _! ]

3 }1 x2 K0 i( }) P( Q7 g8 q" [2 [) xAndroid APP是借助Android Studio来开发的,界面比较简单,通过编辑框输入esp8266的IP地址和端口号,esp8266默认的IP地址是192.168.4.1,端口号是333,这些都可以通过AT指令进行修改。布局页面的xml代码我们就不贴了,熟悉Android开发的读者很快就能根据截图编写出来,放上一个APP界面的截图:: I( }2 B: e. g4 O' L1 ~
5 `: ?* T; ^( G6 A3 F

0 G/ [3 H# R! M% v; x& F& Y2 q% v3 T$ e1 }

& Z3 u7 `1 {, |8 {! Z$ P( o5 b
; X% \! m" W6 `0 U% D1 a
9 Q9 ~: C3 K6 x% V; f6 S
我们主要看一下逻辑代码部分:% M6 f. l& h1 ]/ n! j2 e1 E

4 q2 S3 `& z& a
4 b" L( O4 J/ I" p% @" b5 U
首先是控件的初始化和按钮点击事件回调的绑定4 ?5 \1 ^" q, P0 r
% ^, W) a$ j9 @' f; d

' q6 q. ]- [" a$ l: J$ n7 ?; r% r8 [/ b    @Override# W4 Z  W5 H% L3 `
    protected void onCreate(Bundle savedInstanceState) {
4 t6 A. J& S9 e% {        super.onCreate(savedInstanceState);" G& ]) a) b1 t$ p! k
        setContentView(R.layout.activity_main);4 i  H0 d' W1 C" f( E7 t1 w
        mBtnConnect = (Button) findViewById(R.id.btn_connect);
# y& ~9 |. T+ K$ {3 _* I* o7 g        mEtIP = (EditText) findViewById(R.id.et_ip);( U6 N  I1 `* e# K( \
        mEtPort = (EditText) findViewById(R.id.et_port);, M2 x( Y- r9 _4 u
        mBtnRedOn = (Button) findViewById(R.id.btn_red_on);
- \4 x8 Z3 C8 D/ r7 F        mBtnRedOff = (Button) findViewById(R.id.btn_red_off);. o# `9 F  v+ g% G
        mBtnYellowOn = (Button) findViewById(R.id.btn_yellow_on);# I( i. I6 P7 j" q' v
        mBtnYellowOff = (Button) findViewById(R.id.btn_yellow_off);$ _% L* X7 T+ |1 A  A: p
        mBtnBlueOn = (Button) findViewById(R.id.btn_blue_on);- e$ \3 B! Z/ r/ A2 h/ D4 u+ v2 M( g% e# O
        mBtnBlueOff = (Button) findViewById(R.id.btn_blue_off);
; |; s0 ]( |8 j5 ?4 U- K        mBtnConnect.setOnClickListener(this);7 [( b# y5 C5 w; V4 ^$ d
        mBtnRedOn.setOnClickListener(this);! d, ~( a  u% L) w# C
        mBtnRedOff.setOnClickListener(this);3 a/ a9 C. N+ r  d
        mBtnYellowOn.setOnClickListener(this);/ Y5 b4 f6 r, ?' L/ w
        mBtnYellowOff.setOnClickListener(this);' j# z9 x! Y9 i4 b
        mBtnBlueOn.setOnClickListener(this);' X% Z* Q9 ]% a5 D
        mBtnBlueOff.setOnClickListener(this);& Y* u( c& I& e/ d

9 D4 I9 u9 c, y5 }; H2 n6 }    }7 u/ x0 \8 m5 {
按钮的点击回调方法:- B; X2 h6 Z3 Q% @
$ z1 P: e9 v/ r5 ]" b7 S
1 Q9 N" R' j8 q6 p! F7 u' e
    public void onClick(View v) {/ R. u% {# n1 a1 i& o8 [" u8 M- m
        switch (v.getId()) {/ e  j! p% P4 O9 ~  ]4 i' n
            case R.id.btn_connect:; P- F" m% g  d% k- M0 G( V
                //连接8 O  F- F2 ?7 N. a+ h" A
                if (mSocket == null || !mSocket.isConnected()) {1 O5 `3 r6 k, u+ |+ }' x0 E) T; T
                    String ip = mEtIP.getText().toString();- n! z5 R2 o) M5 B9 T; O
                    int port = Integer.valueOf(mEtPort.getText().toString());5 \( P! I) ?% Q0 r8 G' d( U
                    mConnectThread = new ConnectThread(ip, port);7 U0 [* {% m% s  N' P5 k% J0 o' G1 M  {$ N
                    mConnectThread.start();
3 u7 n! R& k% i0 S5 d3 y- X4 r                }9 _  Y$ z+ S7 M; D3 ]# a  A
                if (mSocket != null && mSocket.isConnected()) {
, S7 {' T/ O4 \1 @) [1 ?                    try {! T' c) g  A4 W; @; C
                        mSocket.close();; w" ?8 ~' _' R  @" a( F! R2 M+ \
                        mBtnConnect.setText("连接");6 j7 `' j$ t) c" L3 {% d9 p
                    } catch (IOException e) {7 P" f/ F1 R$ j: x
                        e.printStackTrace();
$ o* M7 [- K) V  K                    }5 u1 d$ f7 h! M
                }% ^2 F* ~! ~3 {# a

- w1 Y. o; {. t( V' C                break;  ]- ^) Z7 e; S: e8 o& @% R
            case R.id.btn_red_on:         //开红灯! T+ h( w* A% C6 _
                if (out != null) {
' l6 |6 @7 c6 z! z) H% m                    out.print("1");
9 @) V9 X( b1 L" j3 g6 J                    out.flush();
" E  v& Q" ?" p+ l7 P0 ?, H: s                }2 c2 x- }1 q4 _. s; R, L- ~: q
                break;5 k2 j: L" u" ^* s0 d4 B
            case R.id.btn_red_off:        //关红灯: _# M4 e0 M- x. \" r* u
                if (out != null) {
6 H% }2 b9 u9 w9 e' {                    out.print("2");. [/ ?" X  y5 f9 J
                    out.flush();
0 Z0 ?) `4 |8 H+ T                }$ y! Q: b5 T- f3 c( ^( Z
                break;
3 B5 |% j% M) o            case R.id.btn_yellow_on:
. ^: F  p* H( C5 r, O" ~  \' E                if (out != null) {
* y3 h9 N2 V  c$ v" H% \% a                    out.print("3");
) ?+ B$ h& a4 }$ n' v8 \                    out.flush();) R; n- Y/ D7 O7 H
                }. D& K& `* x; W6 Y! q2 s( g/ o" B
                break;
$ M, n$ u0 a, I$ p/ ^4 R            case R.id.btn_yellow_off:4 k# ]: x0 a& z9 C0 d" M9 A; x( d
                if (out != null) {
" O/ ^* X1 [( O% }- ~                    out.print("4");; f6 E9 P- ]* `/ d9 V
                    out.flush();+ n  x8 p5 J) h4 ^% N
                }
) J+ h- ?" F1 C3 l: X4 ~; h1 ^                break;. M2 M) p; t# D+ ]# U0 J
            case R.id.btn_blue_on:$ G' [( z2 k7 R/ W4 v4 x, }
                if (out != null) {" Y/ U; F- y- S# q% T
                    out.print("5");
" m' Q# N5 r# B$ r# w% g                    out.flush();
$ U8 ^2 l' w* _" B                }$ D& M: Q; ~1 `
                break;
: }; l, `% \* `8 M2 j5 ?2 e            case R.id.btn_blue_off:
6 Y8 O: v& b& Y% m+ Y                if (out != null) {. `" b3 m% ^8 p( P4 s
                    out.print("6");
4 @8 ?  u; A3 o* T& {                    out.flush();
- e" w: _% O* k& n+ i1 N: L: @! _! b                }& s1 S- q: F/ x% x& g# e
                break;1 T$ K+ x3 m5 ^/ i9 i
        }
2 `2 P# j$ {9 J+ X    }
3 }: m) n. a7 e1 |1 o1 a, S
7 g& b/ ~/ {( N9 z% T* E负责连接esp8266的线程:3 E) @( ^) d: j3 T+ d0 T5 E  t1 z

; r# q; {1 B  q/ l
. e3 e/ F/ U* y# k) e
private class ConnectThread extends Thread {3 q) U6 f1 n' _- z$ v
        private String ip;! v2 J! \3 i% s6 S# c
        private int port;
  k% v: |# E, T5 ^6 y 7 s+ [8 N& F, V
        public ConnectThread(String ip, int port) {
& x: K# p8 o! a# k            this.ip = ip;8 J" S1 N. {4 Q2 g, n* w+ m+ _$ Q
            this.port = port;' q! l" ?, ]5 i3 b' F
        }3 I$ M! T3 d9 n& t+ [) F* y
, O6 V3 y2 C( v( [
        @Override
1 ^3 W1 b3 a; u* O( O        public void run() {
! e7 F  x7 u% P            try {$ k: k: s% l* J4 {+ t7 y" L( h
                mSocket = new Socket(ip, port);
# U+ U$ i' }1 B0 S# m                out = new PrintStream(mSocket.getOutputStream());# F0 ~  D1 x1 |6 V" Q
                runOnUiThread(new Runnable() {
) V/ Z1 Z5 n& x6 K3 _3 N/ n& H; N. i                    @Override
  H% [8 Y, q, I6 d                    public void run() {
0 }( r; S9 m: o6 ?                        mBtnConnect.setText("断开");
* {5 y7 V% @1 Z. [                    }
  e& S% G& ^$ F; Y% }! ?. J9 J5 ^                });
! A( q' i1 {5 V( V2 @+ j* b                new HeartBeatThread().start();5 x9 a" T0 g& a( `& A% r0 {
            } catch (IOException e) {/ X9 X4 `. ~: J+ k
                e.printStackTrace();, J2 ^& x: \4 P8 N' m' g- u
                runOnUiThread(new Runnable() {" }. E7 {+ }, e1 ?& S
                    @Override: p! Q( z0 |1 l# W, h$ K' S
                    public void run() {
) q  t! C' k2 D( Y' [) d: Z1 @                        Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
1 q( ?8 i8 V/ q* {& E5 ]                    }6 W. H. [( ~1 h, ?( y
                });
, ]! q9 W" E# x. }: g" ]9 q            }
3 P; {4 H* S9 i  J6 X* R% r        }
8 M  x  @) u1 |+ e8 E! Y    }
4 T2 a' T$ ~& R, G* R) t9 U5 ?# {( F/ ]" g6 f8 d0 O- |* \
0 l% A; J7 n5 I1 P, h* Q! Z
3 H" R, e. z5 ~: X" ^0 [( L

1 I7 M5 ]7 ?, v  E* [1 E0 o

该用户从未签到

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

该用户从未签到

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

该用户从未签到

4#
发表于 2021-9-17 13:59 | 只看该作者
学习了  感谢分享
9 J" }+ d. }. G2 }% C! I

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-6-21 13:32 , Processed in 0.093750 second(s), 26 queries , Gzip On.

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

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

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