(一)模式设置! w. u1 y* b* G, T& W
ESP8266有两种模式,AP和Station。可设置为AP、Station、AP&Station三种工作模式。* w: M* O# G _( U& a" `0 b: a, ^
AP模式:无线接入点,例如路由器。
" d' }7 v& h5 o) `5 IStation:AP的Client模式,例如手机连接路由器,手机就是Station模式。
/ V8 x" e+ \+ r! o9 N5 ]9 m8 L4 c
& y+ {: x1 H/ n0 C# m1、AP模式设置. O; X$ ^9 W: w6 d8 Y
设置为AP模式:
7 G( Q0 W, R9 x( A& M. E/ C* hAT+AT+CWMODE_DEF=2
# u. G9 I6 H- N8 j* l( i6 P6 @5 R5 [: M
设置WIFI名、密码、通道、加密方式、最大连接数:
0 [9 m7 O: l6 v" BAT+CWSAP_DEF="esp8266-ap","1234567890",5,3,19 f' L0 h% r( D5 T/ A# _/ t
% T8 a/ t: L' E! X6 R. c+ U
设置WIFI的IP地址、网关、掩码:# n. X6 Z6 Q+ U
AT+CIPAP_DEF="192.168.166.4.1","192.168.4.1","255.255.255.0"- B5 Q2 @: C! c7 p, Y" j) y
5 M, D# L. d, E4 s重启使配置生效(选做,如果命令不带DEF字样,此步骤不需要):
! M- B. |& v: M8 I7 }AT+RST
" R6 |) L9 t' D8 t }1 S$ Q1 G8 t3 G2 m
开启WIFI多连接:1 L; `* f1 w( b5 @+ j, f+ T
AT+CIPMUX=1
$ Y; \ V- e: ^. h: ]
, z" d- l, f- q3 n O开启WIFI服务器:
/ r( n# i- H6 p6 D* sAT+CIPSERVER=1
3 l: o% t) h* j: y
# s5 Y- L- c: SAP模式ESP8266数据接收并解析: \- s( F$ h: N6 G
" X! n1 P+ s; W- Q4 v$ L/ p$ a
- void WIFI_APModeRecvHanler(void)0 p5 ?3 y \/ i8 |" f* T
- {) j' m0 H- c0 U$ W
- if (WIFI_RX_STA & 0x8000)
2 W+ g7 ?( D) ]+ r2 Z- { - {4 v$ O3 u# W' Z7 ?' C& ~' D. Q
- char* start = NULL;$ ^ U* g. A6 N \! |% |7 H6 p2 w9 F
- const char* header = "+IPD,0,";5 Z+ M. O# H7 }1 j4 O- [
8 h6 z8 r- g5 V a- if ((start = strstr((const char *) WIFI_RX_BUF, header)) != NULL)5 o( m! u- s# Z+ Q( O
- {1 u. g) V p: ~8 L) P
- if ((start = strstr((const char *) start, ":")) != NULL)7 }0 F3 t& |" n% i4 l& e5 x
- {. [. O. c/ [2 H J$ M
- uint32_t datalen = WIFI_RX_STA & 0x3FFF; G7 d: ]% L0 C; [) I3 M
- const uint8_t* dataptr = (uint8_t *) (start + 1);
5 v5 s, I: ?# M$ T* z - WIFI_RX_BUF[datalen] = '\0'; _& ~% w( h. l+ d! C1 v
- printf("tcp:%s\r\n", dataptr);
; D, Y5 t( A3 g; U - }
8 \) N( q$ Q" Q - }' g# D+ Y: S$ i6 w8 I# V
- WIFI_RX_STA = 0;
5 F' l2 w* v' ]/ o - }% g+ l, m4 B4 m% J' e9 F% Q+ Q8 q
- }
复制代码
. S8 {4 h: j" w! H6 r2、Station模式与透传! h% G8 ~- e( g) J% D6 Y: _
设置为Station模式:, G* d& [5 N" m) \: H( q: _4 o
AT+CWMODE_DEF=1
' u5 w/ m$ q' D- s$ U( \5 N r
2 m2 t( q. X) n/ R* ]加入路由器:
- i: V8 d$ x& G+ j4 ~( i* RAT+CWJAP_DEF="路由器WIFI名","密码"
4 {6 s8 S# P" x% j7 i4 Z% ~3 Z2 ?( ?
重启配置生效(不带DEF字样,此步骤不需要):* R1 U6 h5 u& {" y4 P1 J0 s
AT+RST% x# e: g3 ]3 H( R
7 t8 ?& P- c9 J' p% A关闭多连接(多连接模式关闭才能开启透传):
% U1 O1 Z0 }/ Y2 H5 O+ FAT+CIPMUX=0
: f' B& W& u: d; Z6 K( `
% t6 k/ w) @6 O# G8 }设置为透传模式:
( \6 T5 R+ M) |! ZAT+CIPMODE=1
7 N) w5 R# [% H4 F3 W8 l" \. ^, v+ [: w& b
连接到服务器:
% ^" N$ i! `6 ?AT+CIPSTART="TCP","服务器IP地址",服务器端口号+ Y' k$ y* Z" m! m; C1 N. a5 c$ z
+ o7 T1 k1 C+ v! C1 u进入透传模式:
9 q' l/ l$ @, T! U4 l( RAT+CIPSEND& s0 Q9 B) T& u
: |& e* m2 \1 E O# _/ h退出透传模式(不加回车):
: s; m# n) a3 T) P1 ?4 J+++. b, T. a7 k* ~( Q% \7 N! T( m
3 Z# r3 a w9 R0 I/ z2 g(二)固件更新
% `1 v t g' D6 p/ B( U5 D; h' r& z% Z; ?, L& L
ESP8266-01S引脚说明:6 i! H8 c, m9 x0 k( J& w
3 Y( b# q) m. J
" q, q+ ^! u" x% J- P7 u( C$ w所以ESP8266-01S刷机需要将GPIO0拉低,接线图如下:$ L( e) w! s P" g. u
0 d' u, w' k( Y4 s; p" [) k
) e* ?7 G1 [5 }注意:如果点击start后,一直处于等待上电同步,需要我们拉低一下复位引脚,或者直接断电再上电。
3 Q( t: S% V9 @5 m: v$ m" b/ e: t; \, A$ h* s5 A! U) }
刷AT固件配置:/ @8 r8 X/ w" l2 k p- O6 O& z
/ E$ F# q( t4 A) _' K1 W4 d
; r/ w& E; w0 E3 @5 p5 c+ n
% Q* _$ I: u9 ~. r- `" E/ G3 w( c刷MQTT固件配置:# K2 J0 X7 w. |4 z3 b
8 U o4 @- F: e3 B$ n2 @8 U
) ~! }0 J8 E( L
. H, H# b$ Z2 x" s! k(三)STM32移植MQTT
( r, ]) o4 A3 s1 Q; z5 j平台:战舰mini板(stm32f03rb)
9 t# L) [( v: E6 G# q% [软件版本:STM32CUBEMX V5.3、TrueSTUDIO V9.3
: `2 x1 C) c) ]3 U+ wMQTT服务器:emqx. n3 A9 L: B5 K
效果:stm32订阅主题led_control,数据为on和off,以此来控制mini板上的led灯。
6 g; T, y- `" Z
0 V; `& M; T. }, `7 M9 X/ [7 B& r注意:ESP8266需要首先初始化为Station模式并进入透传。! r' U" f) `8 [1 K0 r9 e! d7 d
/ {) y! [9 p5 o- I( \0 F& X
嵌入式移植工作比较简单,只需要修改transport文件的硬件驱动读写函数即可,打开和关闭) E1 X m) S* a" ^0 l0 }
函数暂时不需要。MQTTClient.c和MQTTClient.h文件是我自己编写,可根据需要自行修改。完整目录如下图所示:
2 a& f0 w# L3 Q: |
* G5 O5 i+ F5 A7 S& a' V/ x
) K) k5 g+ v# H5 T @8 K' X
$ y- M. D6 }. p6 Itransport.c
" A4 e) E3 T& P5 w1 |8 [- #include "../inc/transport.h"; ], R. Y7 P9 s% n+ m5 E
- #include "../Inc/usart.h"
4 d7 W" S& q/ S% s) D - #include "../Inc/main.h"4 N5 W7 A8 A0 e: o( w* F1 i
- #include "../Inc/app.h"
: K7 G, \# a" E- s# O7 \% B
) m u5 }5 x7 O# P6 u* P; C- int transport_sendPacketBuffer(unsigned char* buf, int buflen)
0 b0 r7 z. w# [' L - {
0 r, l: M7 f" b/ M6 J" a& V3 } - if (HAL_UART_Transmit(&huart3, (uint8_t *) buf, buflen, 0xFFFF) == HAL_OK)
: q4 j) [/ e$ }6 Q3 i - return buflen;! L, I% x( r; T
- return 0;( Y4 v% j9 q: j, k) ?
- }; e; ` U+ b2 ]) y
- 8 y1 B) X6 h7 z+ D2 a' A
- int transport_getdata(unsigned char* buf, int count); h. H3 v6 R& G, [1 w& j& |9 K: Y
- {
: I% r- `& L% R% Q! _8 w0 f( U - static uint32_t index = 0;
2 {( Z6 e6 i; ~, i3 o; W8 E% K, ?& T - uint32_t datalen = WIFI_RX_STA & 0x3FFF;3 p7 I: n% t6 \3 F: _9 O
7 r, x4 ~6 C. w3 \6 h- if (WIFI_RX_STA & 0x8000)
. \, P0 k/ A* E" i' ]3 Q - {5 ^" M% {( T2 l7 l4 A
- if(datalen >= count)9 k ^, h) @6 ~2 Y+ ?% H6 p9 z
- {1 D# a% Q w# M. h, N/ Z$ u
- memcpy(buf, WIFI_RX_BUF + index, count);
. n" { g' X; u' F+ r0 O' k - index += count;9 M' k$ v) G3 \4 e' a
- if(index == datalen)
5 t5 r( c' g! X - {7 }. j) ~' |; x& [
- WIFI_RX_STA = 0;; c: W% r- i( G3 h3 g5 K
- index = 0;
% y& S7 S- J, \& m4 S - }4 A! [ ^; I. ]2 z
- return count;* U# }" @' B% B/ u; ~ i% l
- }
. C$ `, m4 U. `0 v: w6 @ - }
( E; R2 B, |& |4 }3 n - return 0;- n: u, p: I& l* `
- }
复制代码
6 k- _6 O5 N1 z# J$ n9 JMQTTClient.c
6 K% o; G' ^: L6 Z9 y0 [: G6 d& d- /*
4 Z- ?) p2 u6 o9 K" P - * MQTTClient.c
# s- M6 {7 o3 r; y: a5 r- w - *' h3 N: M0 Z% M$ x, w$ t4 e* C. Z
- * Created on:
) g6 ~- W0 e( u) @1 [1 H - * Author:
, V& P! a# z. k2 m0 t) v( g/ X- V - */9 o) j+ O. a+ r1 d
- 1 @) q( Q+ B0 Y6 Z+ B% h, [4 K7 b' K3 C
- #include "../inc/MQTTClient.h"
8 P) A; c& V+ R1 k) K - #include "../Inc/app.h"' u u3 ]- R1 u5 \+ P; n: l4 {, W
' q6 T9 D* j+ B1 E- q3 x, s- uint8_t MQTT_ClientConnect(const void* clientId, const void* username, const void* password, uint16_t keepalive, bool cleansession)
5 m/ Z1 n F; y5 s - {' C) `' I' e3 @- S" T/ Z5 a
- int len = 0;
: @0 o7 C. p- A5 _" I - int buflen = 256;
7 O( u8 \# ^' ?9 G9 h - uint8_t buf[256];
' c t+ U" B$ I* h' } - uint8_t sessionPresent, connack_rc;
+ ]# C9 U4 V: ~ - MQTTPacket_connectData data = MQTTPacket_connectData_initializer;+ P. J* L. ?6 |' H" c3 b7 O
1 N- I0 c4 F9 i- X3 x1 q) a- data.clientID.cstring = (char *) clientId;
. P, e% ]; U p9 a - data.keepAliveInterval = keepalive;
* g- q6 b9 y7 s% h7 q" u - data.cleansession = cleansession;- n' q$ L# R: ^( |/ q: J
- data.username.cstring = (char *) username;$ Q/ r* }- |' A& {) D$ z$ K
- data.password.cstring = (char *) password;
5 w" c4 ]% @/ r, ?1 N o - data.MQTTVersion = 4;6 Y. ]3 J- w: j% M' k
- 5 N1 o6 J# i, U& d, K* |: F# W
- if ((len = MQTTSerialize_connect((unsigned char *) buf, buflen, &data)) <= 0)/ f4 M+ `9 \- k) t, T& a, f8 N
- return 1;; K5 h6 Q" I0 v& ]/ }
- # U7 W9 Q0 I% t1 q% N" c/ @0 X9 L
- WIFI_RX_STA = 0;
5 S' i" z2 F w8 N" w! p# R - if (transport_sendPacketBuffer(buf, len) != len)
4 v( ~! G, Y1 D3 R [" _$ A - return 2;0 F. @$ }4 D3 N: H% v. `
- ' H( T. H5 N$ Y4 [7 ]8 y' w
- delay_ms(1000);
1 f7 y7 h* {+ c6 d/ k# D - 0 w+ Q$ _- Q# D
- if (MQTTPacket_read(buf, buflen, transport_getdata) != CONNACK)- N0 H- e6 K1 H: Q$ }
- return 3;
+ f2 j) E! _( g. P( C - * ]7 s$ R, @9 c' V( h
- if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0)
2 c( H" t9 V) H - return 4;6 {" C) W& i! J5 u" k9 ]
! ~. z. l2 d; @9 k3 ]6 y) A- return 0;
4 w/ S3 N( l* U1 j% I3 j L( n7 | - }
4 Z: ]+ a6 @5 D* A" J1 G0 u4 u! r0 ^/ y+ ]
/ D+ R1 b& b0 k- uint8_t MQTT_ClientPublish(const void* topic, const void* data)
# a* N1 @$ N- t/ H; x - {4 x/ K( s. d9 F M% |9 P7 V
- uint8_t buf[256];: Q1 |* o. d5 G1 [3 d0 e7 w9 Q n
- MQTTString topicString = MQTTString_initializer;
) z0 `, }& |) e- v - int len = 0;. M3 @( @' N7 h4 w \) T, H% [
- # `# {1 _& Z/ t
- topicString.cstring = (char *) topic;
- L; B! F/ B N$ d - if ((len = MQTTSerialize_publish((uint8_t *) buf, sizeof(buf), 0, 0, 0, 0,
9 w! W, B! H" j, S- B - topicString, (uint8_t*) data, strlen((const char*) data))) <= 0)
: L* k$ A5 e/ x3 [7 S" B* p0 I: x - return 1;9 v7 j) x+ ~; x3 h- r
- if (transport_sendPacketBuffer(buf, len) != len)
) j3 ]& |* x! p* r, w V - return 2;
- R3 O1 W2 P. A R4 S - return 0;; }2 K, R4 n" k6 X" i
- }7 r3 N+ P/ T; m0 }) Z- v f8 }
8 k: o2 p9 c7 |* @* {" P; p6 T- uint8_t MQTT_ClientSubscribe(const void* topic, int qos)) {, p9 B8 w4 a& w7 j
- {1 d* v" S/ G( p/ ~
- uint8_t buf[200] =4 h* y* {0 g, F2 o7 `
- { 0 };
$ U2 f( L9 r* y - uint32_t buflen = sizeof(buf);* y% }' m4 Q5 ^( f" J6 E
- uint32_t len = 0;
7 w; G4 s% ^7 h8 G4 T+ j - uint16_t packetid;1 p; B4 b6 |1 ~/ X
- int maxcount = 1;
; n7 W# A$ t; H2 Y* s - int count;& L V" n4 |, I* j# o
- int grantedQoSs;
. K; p; z5 ^5 ? b6 E - MQTTString topicString = MQTTString_initializer;; B5 k' H7 Y. p, v# v
- topicString.cstring = (char *) topic;
4 h1 E/ c# f) f5 M; N S% K - " S; W8 L1 H( w$ b
- if ((len = MQTTSerialize_subscribe(buf, buflen, 0, 1, 1, &topicString, &qos)) <= 0)
, r. C5 x% \6 j- U - return 1; N$ H- h' i+ c" V( } `1 A
- . V1 n& _7 U& H; G: k# ~1 k
- WIFI_RX_STA = 0;
( Q6 N" Z: A( X: n - if (transport_sendPacketBuffer(buf, len) != len)& ]- G% T$ n' t$ \: ]# q% K' a5 x0 |
- return 2;
+ [8 y( u' u8 l/ ]! ]! s
, l; h: U% j6 s) ?! ^- delay_ms(1000);1 I* ~8 S$ D* Y9 c+ G9 k
- # f. {' S3 j: A- E* I6 M2 V3 E
- if (MQTTPacket_read(buf, buflen, transport_getdata) != SUBACK)1 j( _5 Q! i) ~- s! @; w7 H
- return 3;
& _; o: i2 K0 |( S; U8 \ - 5 K! k0 X) \# }5 f( @
- if (MQTTDeserialize_suback(&packetid, maxcount, &count, &grantedQoSs, buf, buflen) == 0)
6 T# W+ Y- L4 c' r+ R n" S" M - return 4;* T, B' ~; \& w6 Q) Z! o5 B8 d
- # D, e e( L! y& X p3 o
- return 0;+ h' e3 E/ N( h# V% x8 X8 M3 n% a
- }! m$ P( g8 D- o% h, e
- 6 n8 f- Z0 V' ~# @/ H7 D, E( _
- extern bool G_isConnected;
, k1 t; T& i6 z1 L! J2 l& n
% F0 B/ O" a. X* X N8 l1 U- void MQTT_RecvParser(void)7 z$ Y' f! K- g4 R
- {
' R9 z, k' G9 y$ e6 w# V5 ` - size_t topiclen = 0;
* M: D B7 p; V2 e* O. c/ | - size_t datalen = 0;/ \# v2 c- e4 s6 S4 n2 b5 v
- static uint8_t topic[0xFF];& V9 x' q0 r/ Y, U
- static uint8_t message[0xFF];' p, k: B* V/ G& ]
- static const uint8_t* buf = WIFI_RX_BUF;) F4 D! Q# t) ?1 O6 z
+ n, r2 y6 r& L% z- if(G_isConnected == true)
) @' h; R% f% I) d6 P4 e - {5 p# Y- [) P1 \- ]( w) t! B
- if (WIFI_RX_STA & 0x8000)( h* L/ Y( J) v3 A K: w" b
- {
8 G9 n+ |, z2 a7 q" _ - WIFI_RX_BUF[WIFI_RX_STA & 0x3FFF] = '\0';
* R6 ?. C$ `5 A4 e8 T& p' F3 G8 g - if(strstr((char *)WIFI_RX_BUF, "CLOSED") != 0)
- X7 l" Z$ A$ } S - {% B/ {8 {4 f" k
- G_isConnected = false;
! C2 e: D' s9 ~( Q - WIFI_RX_STA = 0;
+ m& `* K0 z3 z - return;
" J& u/ O5 S1 a! C - } z$ O8 ^# ?, U+ R, j
- 6 H" I4 d% r p, ~% k
- topiclen = buf[3];
6 B2 A" I( Z! q" Z H0 M# ~: e2 B - datalen = buf[1] - buf[3] - 2;
4 Y. ?7 f6 s! g - memcpy((char *) topic, (const char *) (buf + 4), topiclen);
4 l5 F7 R: _! i. z) | - memcpy((char *) message, (const char *) (buf + 4 + topiclen), datalen);$ x9 I5 T; }: ~+ b* M
2 i8 n4 {1 C% F& `- topic[topiclen] = '\0';6 U8 Z9 H a. I9 G. ]
- message[datalen] = '\0';
2 n' O; h; M( S( M
* @2 [. J: t, q, n7 n) f- if(strncmp(TOPIC_LED, (const char *)topic, strlen(TOPIC_LED)) == 0)
3 F. k) ?2 S) ]: ?- w4 ?, i- C - {
, \; c: X K( _7 ^& [ - if(strncmp(MSG_LED_ON, (const char *)message, strlen(MSG_LED_ON)) == 0)
2 ?4 d/ M. }% O4 v, b! J, ~+ A; C - {+ W3 R6 C& B- C0 f! q7 |0 u
- HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);$ d# e. N; d3 d% W! ~9 L: P
- }else if(strncmp(MSG_LED_OFF, (const char *)message, strlen(MSG_LED_OFF)) == 0){
% S" k( O& `; x/ s( F9 k+ n, y - HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);+ b6 v; j+ n6 S+ J
- }
6 d. Y, B9 p1 X" L" n3 u - }
) K: v: X0 k7 @1 C3 ^& ? - 1 c* v" e' O* S! A+ o7 f
- printf("\r\n");
# M( }- _8 x4 d/ `( N; L$ J# c - printf("topic:%s\r\ndara:%s\r\n", (char *) topic, (char *) message);4 I, N- K, {0 N! ^
- WIFI_RX_STA = 0;/ S, p0 L$ [0 @1 B
- }9 l! P( a* A* U. y
- }: q, W# a8 ]6 \4 H7 F
- }3 w4 H5 L: d2 o% S4 R! r# o# B
复制代码 ' d' r5 b8 ]* l( u6 V9 ^, w L' x
main.c
f4 u0 c3 r+ A2 u5 U6 }" {+ t
& F' e/ E" w t: Z4 r5 _
$ h$ `) D( `% n( a7 V2 _9 y
8 @+ C# o7 ~) K0 }ends…5 a; Q! S) t+ ^7 K& ]3 R
+ `7 J1 [9 e& x" V; O2 q$ u) K' ]5 S
( D; s' {: R' F# z. v |