你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于NONOS 2.0的ESP8266串口透传

[复制链接]
gaosmile 发布时间:2021-1-19 12:16
项目有些久远,前年的机器人上需要的功能,当时是需要将STM32上的数据上传到服务器,比如机器人的速度,行驶距离,是否在拍照等等。便于管理者在PC或者手机上了解机器人的工作状态,同时可以远程下发指令给机器人,控制其完成相应动作。$ p- K* ]. }' D
因为所有的逻辑判断和控制都在服务器或者STM32上面,作为中间的无线模块仅仅需要上传STM32的数据并接收服务器下发的指令即可,所以这里对WiFi模块的要求不高,仅仅需要它作为透传功能即可。当时在选型的时候试过好几款WiFi模块,最终敲定了安信可的ESP8266,价格便宜,开发简单,但是搭建环境是真的不容易,深受其害。7 I2 a/ F3 Y' Z( N
选择好模块就该考虑使用AT指令还是使用SDK开发,AT指令固然简单,但是局限性非常大。如果使用AT指令,我那开发控制端的同事估计就要跳脚了,代码里需要写一大堆的AT指令,如果功能改变,指令代码就需要重写,烦不胜烦。
/ V8 e) b2 \% r# f8 X. A; a" W
如果使用SDK开发,控制端只需发送简单的数据就行,完全不用考虑其他任何东西,ESP8266完全当做一个中转站,相对应的我的工作就会繁重,但是,我屈服了,选择使用SDK。0 A0 K) p  V' B4 q) A! A9 w, l
于是就有了下面基于NONOS 2.0的ESP8266串口透传。主要有以下几个功能:* |& @5 c: w: g3 q
/ B% o5 I. s( M5 g  L
  • 纯串口透传,接收MCU串口数据,直接通过MQTT上传到服务器,接收服务器数据下发给MCU。
  • smartconfig+airkiss配网,随意使用,场景丰富。
  • 最多储存5个WIFI账号和密码,自动寻找网络连接。
  • 按键配网,长按重新配网,前一次WiFi自动储存,添加配网指示灯。
  • OTA空中升级(待验证)! z$ {! b' V/ I& `$ _

    3 L3 c; D( K+ y
( R7 I4 J: x" `& t
从程序的入口开始:
  1. ( K7 w4 L3 }% |5 H9 R! p6 H& M$ w$ f
  2. //程序入口
    % ~, U1 l: }1 P( b
  3. void ICACHE_FLASH_ATTR user_init(void). l5 X& J& p& O6 d% P2 @) u
  4. {  e9 X! e/ Z; D
  5.         uart_init(115200, 115200);4 a& r6 @1 E2 d7 b  {0 ?& j
  6.         os_delay_us(60000);
    ' q6 S! m( h$ s
  7.         keyInit();
    - K+ J9 F; U- e3 E
  8.         set_uart_cb(uart_cb);* I( `* R4 M% X0 d
  9. 5 c" l* w' u2 x
  10.         PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); //GPIO12初始化
    - n) U4 Y/ _2 b4 u; i0 _2 i7 l5 ^
  11.         GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);//低电平
    ; v# t4 q8 @2 D) d. h

  12. - q' m+ {0 {  g
  13.     get_mac();//获取MAC地址
    " Z/ d+ N, ^) J
  14. 7 z' d+ J: T: A2 Z
  15.         wifi_set_opmode(STATION_MODE);
    / c% V/ s2 b& Z2 R, L
  16.         //设置wifi信息存储数量,最大为5个
    " [+ Q7 b* |) F6 P7 d4 ?
  17.         wifi_station_ap_number_set(2);* }( M8 o0 f5 R0 D
  18. . ^* M3 C' ^! j8 f0 v/ C1 Q) T, R
  19.     mqtt_init();! B1 {, K) e" G- e6 q8 Z9 {7 i
  20. * ~) E) ~8 o& _2 f& q" x1 Q* l
  21.         set_wifistate_cb(wifi_connect_cb, wifi_disconnect_cb);2 u% c1 o% ?! i2 @- I, }9 b
  22. }
复制代码
$ \& E" e, p7 j) E* P% e: |1 L$ I
程序的入口先进行串口初始化和按键的初始化,以及LED的初始化。串口要初始化波特率,按键初始化配网按键,用于短按配网,长按重新配网,LED只要用于判断模块是否进入配网模式以及是否配网完成。3 o9 A  ]8 K4 }
初始化完成后会首先读取MAC地址,该地址是唯一的,每个模块都不一样,用于填充进主题中,便于服务器区分不同设备,用于多台量产设备的使用,在连接MQTT服务器时会自动填充。
6 p& Z) |2 s8 ~6 I3 W3 w
微信图片_20210119121309.png
4 _) T; Z! z7 D5 e8 ]% x# H' Z每连接一次WiFi都会将WiFi信息保存在模块内部,每次上电都会自动扫描暴露的WiFi,直接连接,就像手机的WIFI连接,目前最大支持五个WiFi信息的保存,超过5个会剔除最早的WiFi信息,通过短按D5(GPIO14)可进入配网模式。
% W! w1 @. a1 i) L, E( `) ]

  1. 5 m# L* o. Z. I7 o' y, v, ?
  2. /**
      G- p1 i1 e0 {+ k, N+ F
  3. *         按键短按回调% r" }. d$ @6 C
  4. */
    + R  w' M5 b# K& J  a7 r
  5. LOCAL void ICACHE_FLASH_ATTR key1ShortPress(void) {4 N, F' F" C# ~5 I

  6. * G/ y4 J! `+ H% c" I' ?
  7.         start_smartconfig(smartconfig_cd);
    5 F$ l$ r0 r" H0 G( n
  8.         INFO("start_smartconfig\n");1 C  k6 R0 s" n8 F
  9. }* U3 h7 a9 Q! b; [) s
  10. /**
    9 b& h* s$ a! R
  11. *         按键长按回调7 j) n+ f7 ?3 S
  12. */' D' B$ F7 W9 F3 _  ~4 s' {
  13. LOCAL void ICACHE_FLASH_ATTR key1LongPress(void) {5 z9 ], a. G! y7 m& U
  14. 0 m5 t1 e" F- s- N1 h5 K
  15.         start_smartconfig(smartconfig_cd);+ u6 P6 `. D; o2 q, B
  16.         INFO("start_smartconfig\n");
    # m2 S& G! \3 Q0 y5 K$ w
  17. }: q1 R/ u2 ?( ?; C' k# M/ U2 }
  18. /**  [. R: f8 `8 z6 b( T
  19. *         按键初始化2 X7 v; [4 q( y5 U" m3 A
  20. */( L5 |+ o. s/ H8 j
  21. LOCAL void ICACHE_FLASH_ATTR keyInit(void) {
    : e% E2 v8 K- r1 L

  22. 6 l. {, y6 v3 c7 n
  23.         //设置按键数量( u& w2 J0 e  ]4 a) I+ i0 j
  24.         set_key_num(1);3 s* b& r6 I. V
  25.         //长按、短按的按键回调
    , R1 e/ d3 a4 [  ]
  26.         key_add(D5, NULL, key1ShortPress);
    / F: m* f9 q" A9 x5 Y4 f
  27.         key_add(D5, NULL, key1LongPress);
    . _1 ~8 e8 t/ v9 B7 I  i
  28. 0 n# [0 Y( Y3 n$ w& E. O; S; P
  29. }
复制代码
! K  R" D; @: v/ n. P$ H/ [! F
) e0 G  U% }! _7 [* U/ g0 e( A
由于找不到最新的代码。这里的长按我没做处理,应该是断开WiFi重新进入配网模式, 或者软复位模块,再进入start_smartconfig()函数:) [6 e; q/ Z8 ]$ B# ?2 x

  1. 5 z* m6 ^% N' M0 Q; j
  2. /**
    ; t5 H0 M2 q3 A
  3. * 开始Smartconfig配置  + K+ |1 l: }* Z
  4. * @param  cd: Smartconfig状态回调: U9 j5 J; l. d
  5. * @retval None
    1 h1 [; o' c+ x; A& s
  6. */
    ' O- v! ?$ ~& O2 Y5 ]
  7. void ICACHE_FLASH_ATTR start_smartconfig(smartconfig_cd_t cd) {# d7 E' w" e# S  z: J) ?
  8.         smartconfig_flag = 1;- g: \% A, E7 v/ q3 V2 Y# u* B
  9.         smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS); //SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISS" z8 s5 y9 P: o5 n1 h. h
  10.         wifi_station_disconnect();! X, t: y# ?2 T+ _
  11.         wifi_set_opmode(STATION_MODE);$ ?( L" O2 }1 `+ Z
  12.         finish_cd = cd;
    ! z+ {! h& I& |: h, S' ]" l
  13.         smartconfig_start(smartconfig_done);. U3 Z* l0 C: U4 n; F
  14.         os_timer_disarm(&OS_Timer_Wifichange);        // 关闭定时器! T1 @. o9 x* a( y# L0 L, w) c9 d( N

  15. ( S% F7 R2 [6 r6 j
  16.         if(connect_flag == 1){5 l* T. p1 ]5 }: c
  17.                 w_disconnect();
    ) v. y+ s9 O7 R4 J' t5 G  |3 ?! e
  18.                 connect_flag = 0;
    + \9 U! p7 d$ a
  19.         }7 W. h; I1 h7 x% k

  20. # C- t$ m1 B+ w  r4 C
  21.         os_timer_disarm(&OS_Timer_SM);        // 关闭定时器
    ; t6 `/ D! x: v* G1 N6 E2 p& f. H
  22.         os_timer_setfn(&OS_Timer_SM, (os_timer_func_t *) sm_wait_time, NULL);// 设置定时器( o3 V% }. r; `! p# }& ?
  23.         os_timer_arm(&OS_Timer_SM, 1000, 1);  // 使能定时器" v5 C3 a+ R$ o. r+ B  A
  24. }
复制代码
$ b1 H, i' l: V2 ?' J

3 ^, B3 ~- o) l, W( r* x, R% _4 U
微信图片_20210119121312.png
( o0 v! h3 H2 k3 `6 X4 A
smartconfig_set_type();函数可选3个参数:分别是:SC_TYPE_ESPTOUCH、SC_TYPE_AIRKISS和SC_TYPE_ESPTOUCH_AIRKISS4 l& H0 T* D2 k- t( u: G
第一个是smartconfig配网(手机APP),第二个是airkiss配网(微信公众号),最后一个两者都可以。进入该函数会调用smartconfig_start();,该函数会调用smartconfig_done()函数进行配网,配网成功后会点亮LED灯。
  1. ( k  E+ y, e' z4 A1 N' q
  2. /**
    : ]0 D# ^% g( r5 B% a
  3. * Smartconfig 状态处理, ]4 Z: a1 ~# [# \7 m" o
  4. * @param  status: 状态
    $ T3 o* o8 m9 F" M
  5. * @param  *pdata: AP数据
    - Z1 q3 v5 X! Y
  6. * @retval None! U% ^& ]4 F7 D5 G2 B
  7. */' A; O7 I$ t& P' a! e( M
  8. void ICACHE_FLASH_ATTR
    ( c2 F% J4 L& u
  9. smartconfig_done(sc_status status, void *pdata) {
    3 Q3 Q% K1 R$ w' L
  10.         switch (status) {
    " ]2 n' ~) D& H; ~
  11.         case SC_STATUS_WAIT:
    7 P% A, M( O+ x1 v7 y! H) C/ _
  12.                 INFO("SC_STATUS_WAIT\n");* D# Y; r) Y- v0 l2 b$ [
  13.                 break;- |' l6 }6 v# i9 y& \+ o5 k
  14.         case SC_STATUS_FIND_CHANNEL:; L. w( X' d' y
  15.                 INFO("SC_STATUS_FIND_CHANNEL\n");
    ! g8 ^& {% y5 Z3 K% s
  16.                 break;
      R9 ~: M3 q, F$ g
  17.         case SC_STATUS_GETTING_SSID_PSWD:
    ! q* _' `+ ?- l0 m4 s/ t
  18.                 INFO("SC_STATUS_GETTING_SSID_PSWD\n");
    % R! P1 m& G! P% x8 a% G, J
  19.                 sc_type *type = pdata;, b8 C$ b; H0 C# c0 G2 C
  20.                 if (*type == SC_TYPE_ESPTOUCH) {2 W+ @6 a  c- }' M# f8 ^; N
  21.                         INFO("SC_TYPE:SC_TYPE_ESPTOUCH\n");
    6 K; ]1 l7 J5 R$ g* Q
  22.                 } else {
    5 @% k$ n1 L6 k/ K- b* |# v5 ^; l
  23.                         INFO("SC_TYPE:SC_TYPE_AIRKISS\n");! n7 u4 G- M6 G# f) x+ }1 e
  24.                 }
    ; s+ H: C( Q$ \7 h
  25.                 break;
    6 g- i* U# v+ {$ K: m9 ]
  26.         case SC_STATUS_LINK:
    $ {) C$ m9 J0 q: v- B+ \* x
  27.                 INFO("SC_STATUS_LINK\n");+ Z. N& V) u. g+ G% m' b. |
  28.                 sm_comfig_status = SM_STATUS_GETINFO;
    0 P2 A8 X! E3 R  j
  29.                 struct station_config *sta_conf = pdata;
    9 ~& _; x: `' {
  30.                 wifi_station_set_config(sta_conf);
    ! o' K% ^. I9 r
  31.                 wifi_station_disconnect();
    ; B- f9 }% H: v$ V* ?( r+ d6 Z
  32.                 wifi_station_connect();7 @5 Z' _3 q% a# L! x  d
  33.                 break;
    ! b0 i' J( }& {- F" A/ U3 L
  34.         case SC_STATUS_LINK_OVER:
    * L  v. T7 G9 k# X) Z% q1 m% S
  35.                 sm_comfig_status = SM_STATUS_FINISH;
    7 t# {( W$ n. ?8 V6 d& u
  36.                 INFO("SC_STATUS_LINK_OVER\n");. c7 d. V2 ]: r& \: R' M
  37.                 if (pdata != NULL) {
    ' I. U8 m# ^3 ?+ B+ O1 D7 x- D
  38.                         //SC_TYPE_ESPTOUCH  M: s' }! L( ?$ S. K9 W1 m
  39.                         uint8 phone_ip[4] = { 0 };) Q& u# S& `% `% u% ^" z4 V8 z
  40.                         os_memcpy(phone_ip, (uint8*) pdata, 4);
    % A+ s1 Y" Q! t  V8 F1 l% I
  41.                         INFO("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1],
    6 [1 f/ g" J& b; ~* C- `
  42.                                         phone_ip[2], phone_ip[3]);
    0 b2 s. n& X$ s0 V/ \) F
  43.                 } else {
    , j4 ]1 j: @/ {
  44.                         //SC_TYPE_AIRKISS - support airkiss v2.0
    ; e1 k& K3 D# H9 q9 l1 K. m0 C' y
  45.                         airkiss_start_discover();
    6 b" G" e/ g+ L1 B6 B, o
  46.                 }, l, @; }- ]& n8 n
  47.                 smartconfig_stop();
    . G9 Y6 }# @4 Y
  48.                 smartconfig_flag = 0;9 ]5 M" g" |* F; c4 ~" N0 g- ^; j
  49.                 connect_flag = 0;
    , Q2 ]8 u' e, N5 l& j, K& `4 b7 W
  50.                 os_timer_disarm(&OS_Timer_SM);        // 关闭定时器
    8 t" ~7 I9 M4 @$ ^
  51.                 finish_cd(sm_comfig_status);, a0 S5 [! T0 S' |
  52.                 os_timer_arm(&OS_Timer_Wifichange, 3000, 1);  // 使能定时器
    " E$ y/ X) W/ l$ q& d. c) h# f
  53.                 break;
    5 V1 S! `) v' i
  54.         }
    6 n  l9 T( i0 M5 k

  55. 1 @9 x7 y( b% x( m* R
  56. }# D9 H$ z% `  L) e- `
  57. : q$ r$ t! L. c/ f0 f: e/ v
  58. /**
    4 a: h/ d2 v! T
  59. *         WIFI连接回调
    8 X* K& ^5 o, f4 e* K- [4 ~' R
  60. */  @3 B$ e8 _& Y5 ^  o
  61. void wifi_connect_cb(void){: U1 b' [" i5 x3 L
  62. 6 a1 u' Z+ |1 V! d* h" O+ p8 ?' T
  63.         INFO("wifi connect!\r\n");
    : W+ M( L# ?" u& i, ~1 p
  64.         os_printf("----- WiFi连接成功,打开绿灯---\r\n");
    : a3 q9 _8 x- A$ V# P& T
  65.         GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);
    0 @6 s; o# s' N, u
  66.         MQTT_Connect(&mqttClient);
    - W# A9 y( m9 s: b( M( [: d
  67. }
    : F  C* B+ g2 p( p( c% j

  68. ! ?7 J! x( \  M- e- X- f6 a
  69. /**
    # S* J; x/ y6 v8 b% k- k4 o$ h; ?  L
  70. *         WIFI断开回调" r% w4 y9 `3 y1 z9 h
  71. */
    ; K% v* Y* j- V, z; J7 B$ \
  72. void wifi_disconnect_cb(void){
    ! d' K7 i  B3 G! ?3 }0 M& e
  73.         INFO("wifi disconnect!\r\n");* F& Y/ J3 R, l( @1 V0 y
  74.         os_printf("----- WiFi断开,关闭绿灯---\r\n");
    ; k6 @# f6 i/ }) ~$ I# I
  75.         GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);
      l. D1 p3 O9 T6 \- @
  76.         MQTT_Disconnect(&mqttClient);0 s/ Z+ _8 h! p+ t; ~) n! ?
  77. }
复制代码

0 G) {' [( y# V# o- o: x* K1 o
( Y* H1 l1 D2 R/ F9 _2 \& i
连接MQTT服务器:! w6 a  I4 A! _1 ]: X5 h. C
$ d" u& l, `* Q/ x( p2 H8 r3 u6 l
网络连接成功以后可以开始MQTT的初始化,初始化包涵一系列的连接初始化回调,连接成功或不成功回调,主题订阅发布回调等等。

  1. % }6 @, |: {$ v9 d
  2. /**
    9 x( |, M! Z# R' ~+ M. N6 H6 H
  3. *         MQTT初始化
    5 c8 `9 ^  s& J' L
  4. */
    9 \) A& ~+ p+ s2 h. M$ m" ?) {
  5. void ICACHE_FLASH_ATTR mqtt_init(void) {
    ( q' H/ ^) }" K& F- Y6 _/ u

  6. / P  Z% h) Q& e" K' J
  7.         MQTT_InitConnection(&mqttClient, MQTT_HOST, MQTT_PORT, DEFAULT_SECURITY);9 C$ {, ?9 t8 c! d
  8.         MQTT_InitClient(&mqttClient, mac_str, MQTT_USER,MQTT_PASS, MQTT_KEEPALIVE, 1);
    8 \3 Y7 N# Z5 }8 W6 F% h. u* m
  9.         MQTT_InitLWT(&mqttClient, lwt_topic, LWT_MESSAGE, 0, 0);
    ' k7 k* ~2 V. q! b8 Q3 V- Z
  10.         MQTT_OnConnected(&mqttClient, mqttConnectedCb);7 ^$ q, [- k# E
  11.         MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
    7 N; v% ^  m' H' d/ z! c! u8 B( D
  12.         MQTT_OnPublished(&mqttClient, mqttPublishedCb);
    2 T+ x3 s8 W0 _3 i; H. y2 b% G! g, Y
  13.         MQTT_OnData(&mqttClient, mqttDataCb);( {- h0 |+ }% B3 @
  14. }
    . e6 Y5 h3 a! c; x3 ~0 `

  15. 6 W5 E. e2 J, `0 S9 y/ |0 o$ ?; h$ p
  16. void ICACHE_FLASH_ATTR3 z9 y0 y. N/ }+ u) ~* X! I
  17. MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security)
    1 b, a9 W  |8 N7 _" Q5 M
  18. {
    6 U( F8 D! {, ^( m5 S
  19.         uint32_t temp;+ z  K1 Q/ H8 T, o% m7 ]$ j! m
  20.         INFO("MQTT_InitConnection\r\n");  F" ^7 S1 d4 S% J
  21.         os_memset(mqttClient, 0, sizeof(MQTT_Client));* R  w9 y0 n1 H6 V. n8 P& s5 _
  22.         temp = os_strlen(host);
    - _: S  ]* \0 n( j, w  T
  23.         mqttClient->host = (uint8_t*)os_zalloc(temp + 1);: Z+ F/ x* |& i8 n; f/ M8 E* U, `
  24.         os_strcpy(mqttClient->host, host);
    : `, ]2 m3 P$ W' n
  25.         mqttClient->host[temp] = 0;
    8 [) I# o5 x$ q) L: @. h( K: i- ^( z  ]
  26.         mqttClient->port = port;
    " y6 U6 ]( \! O8 [0 V
  27.         mqttClient->security = security;8 n# S- g5 A0 f
  28. - L( i! m' T4 U3 v
  29. }
    ( D6 V( e7 L5 \! K( m
  30. ; W, m3 s% r# J' g% m
  31. void ICACHE_FLASH_ATTR5 T$ {6 F( i% r8 p( v3 m2 Z4 E6 N2 H
  32. MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession)& f- |- @9 N) H4 h; Q  X
  33. {
    0 i! [% `4 W' d- D
  34.         uint32_t temp;1 E) J7 i# g8 ?1 S
  35.         INFO("MQTT_InitClient\r\n");7 h$ [  Z. B4 j
  36.         os_printf("CD MQTT_InitClient++++++++++++++++++++++\n");7 M0 _4 Z6 a1 p1 b! @; s0 \9 k# N
  37.         os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t));
    # c/ ?- \, A5 G% k, d
  38. & b4 B$ f  F3 V( H+ }4 W7 }( Z9 f
  39.         temp = os_strlen(client_id);
    5 R9 W. ?$ F: s, G/ p
  40.         mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1);
    6 F! n! |( T) x) I7 ^
  41.         os_strcpy(mqttClient->connect_info.client_id, client_id);
    2 Y" A7 o( v  D! C6 p2 L  i* b& f3 F
  42.         mqttClient->connect_info.client_id[temp] = 0;
    / M: Q2 E& C  }4 e, j0 ?/ O+ \

  43. ( O2 l! v% D" x' ~- Z9 K9 `' C
  44.         if (client_user)
      O7 U1 }- @* v/ }& E
  45.         {
    , R# `1 [4 A! J7 F+ w
  46.                 temp = os_strlen(client_user);
    ; }6 x' A' C! [6 U/ h$ j4 S
  47.                 mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1);, w" P3 Z; P- U8 }5 L
  48.                 os_strcpy(mqttClient->connect_info.username, client_user);
    9 U+ [- Z+ q# z
  49.                 mqttClient->connect_info.username[temp] = 0;
    . N4 w4 M: R- x& P- K! r: n
  50.         }% H8 e4 p. y! `4 F( P% b& y# o
  51. ) q2 M- }5 O: _$ j# O* N7 w
  52.         if (client_pass)  Y. E; h, `0 `8 y  j
  53.         {
    ' m" @2 t+ z# H+ [4 C6 L  S* b
  54.                 temp = os_strlen(client_pass);  N  o% D- e8 t5 j
  55.                 mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1);% R1 u- N* c4 U/ F" [
  56.                 os_strcpy(mqttClient->connect_info.password, client_pass);9 [# U1 C6 o& ]9 K  Q. r' H1 B
  57.                 mqttClient->connect_info.password[temp] = 0;4 i, M9 P/ {7 D% Z* m
  58.         }% e  O+ v7 t( T# {2 c$ H3 L
  59. ; d* S" ]; r2 }0 i

  60. / p. Z3 g/ X( t' D5 h
  61.         mqttClient->connect_info.keepalive = keepAliveTime;
    0 b; I4 q# b0 i
  62.         mqttClient->connect_info.clean_session = cleanSession;
    * S5 P5 z8 ^' g- `4 [
  63. 8 ]& W  ?# z( a0 u! P
  64.         mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE);
    , K* I; m3 Q8 e! O
  65.         mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE;
    : g/ P% q" ]/ a) q( Y  X
  66.         mqttClient->mqtt_state.out_buffer =  (uint8_t *)os_zalloc(MQTT_BUF_SIZE);8 U' z- n3 v( o: v4 @; \
  67.         mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE;
    . g& u! p3 j4 ~- q. V' T. p+ z% N
  68.         mqttClient->mqtt_state.connect_info = &mqttClient->connect_info;
    - _+ v: T% ?0 R4 ^9 m4 F3 l' Q
  69. * z  |3 V1 h& c3 K: I+ m* R
  70.         mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length);$ R# h) m, n/ c* A; g
  71. 0 O/ v1 C" g4 j# H8 M# g4 Y
  72.         QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE);8 Q6 t* x) z( U4 k. r- q" d4 \
  73. ! u0 w0 y4 `8 A
  74.         system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE);
    ; U3 W7 y& b# b# c0 Y8 C" B* c
  75.         system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient);
    3 {0 J2 c% F* u* ]4 j
  76. }
复制代码

& i6 p" \% X- v$ X

" W8 n9 d/ g9 K, I- B  [
WiFi连接成功和失败会触发不同的回调函数:
  1. 5 Z1 t6 G+ B1 o# B! E& W- S* n/ \" R
  2. /**. Q5 n& z4 ^+ [: O2 N
  3. *         MQTT连接回调
    ) _; ]# S1 u4 ?6 D- o
  4. */
    6 ~6 ?* t  o6 y' \9 X, I3 F
  5. void mqttConnectedCb(uint32_t *args) {
    ' J5 D, x  n. A/ }  k' }
  6.         MQTT_Client* client = (MQTT_Client*) args;8 Q& C. s- J8 b: F: R# V7 h
  7. 3 }2 z5 w/ D& S
  8.         INFO("MQTT: Connected\r\n");3 @1 S9 y. a1 G: u
  9.         MQTT_Publish(client, birth_topic, BIRTH_MESSAGE, os_strlen(BIRTH_MESSAGE), 0,0);
    * ~2 M# j. _0 r6 b8 M# a0 v
  10.         MQTT_Subscribe(client,ota_topic, 0);# C$ o; K( h& z1 ~- ]
  11.         if(updata_status_check()){
    / k' I/ X0 o) Q$ G0 A
  12.                 MQTT_Publish(client, ota_topic, "updata_finish", os_strlen("updata_finish"), 0,0);
    % K, r& w* g' `7 ?. c6 Z) R
  13.         }8 ?/ W5 r$ A, ]5 x/ [/ w" Q
  14. }
    : e( G+ l& a6 u. ~2 o
  15. /**
    9 _3 R7 F' D" [$ X! P; y
  16. 6 p! s8 I7 Z% l, E' d3 Z
  17. *         MQTT断开连接回调
    / M/ k& |! ]8 T; e6 M1 a
  18. */
      Q4 P( V5 }, M7 d
  19. void mqttDisconnectedCb(uint32_t *args) {
    ' Q! J5 ~: i0 f
  20.         MQTT_Client* client = (MQTT_Client*) args;
    : @) V" U% n! U3 o( M; `
  21.         INFO("MQTT: Disconnected\r\n");
    , s" o+ V/ k- y
  22. }
    ; A' j3 {; Q* r$ t$ z9 X8 g" a

  23. 2 Y0 q0 [# n3 |
  24. /**
    9 E' A4 A, i2 R& K* L1 e) E9 G; d
  25. *         MQTT发布消息回调* \0 y) J6 R9 [$ {3 t8 U4 J
  26. */% s4 R) J& J+ b( V9 |
  27. void mqttPublishedCb(uint32_t *args) {
    $ |! `! r$ Q& D4 c& T: U  c1 D5 Q
  28.         MQTT_Client* client = (MQTT_Client*) args;
    $ }, G, Z* t6 w3 N) u- O) g  \$ _
  29.         INFO("MQTT: Published\r\n");- @$ i. l0 a8 Y  O' f/ C. R0 o
  30. }
复制代码
9 n' R# L) x( j9 L- l2 O# z4 p
串口透传:5 h- S9 N+ i; k0 _
当模块的WiFi和MQTT服务器都连接上之后,模块就开始监听串口和服务器的数据,如果串口有数据过来便转发到服务器或者进行OTA升级,如果服务器有指令下发就转发给串口。

  1. 3 V+ {- M6 {9 R; M8 l
  2. /**
    0 Q1 ]* p  ?4 `: k7 h
  3. *         MQTT接收数据回调(用于OTA升级和串口透传)/ A, e1 T# A  s* _2 O- F2 x
  4. */- z0 H6 P# k! {  |+ `5 g
  5. void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len,
    * g" b* E! N& P3 P
  6.                 const char *data, uint32_t data_len) {) g3 L6 R% ~8 }7 V2 u' O' c/ v. Z, ^5 d
  7.         char *topicBuf = (char*) os_zalloc(topic_len + 1), *dataBuf =% |0 ?- c$ s2 j8 p& A
  8.                         (char*) os_zalloc(data_len + 1);
    % e9 a  P  Q! Z
  9. ! A) Z8 h# S1 Z, b. x! U
  10.         uint8 *pdata = (uint8*)data;2 ?! o9 H3 I/ i; t- ]& f. U, o" V
  11.         uint16 len = data_len;# N. z% ?5 S0 N" ?$ N
  12.         uart0_tx_buffer(pdata, len);//串口输出
    8 `- x$ O1 C) z' _; f
  13. - |  @2 a( y" O) \
  14.         MQTT_Client* client = (MQTT_Client*) args;% X! c8 K! x& b% S3 ^( p6 f
  15. % G) F" X& m9 J5 i; i( Z+ c
  16.         os_memcpy(topicBuf, topic, topic_len);
    + c# w/ h8 j- P" ]7 a
  17.         topicBuf[topic_len] = 0;1 ]5 s) S/ Y9 t* C

  18. ; g% g7 l6 ^8 I' v/ h0 I. Q
  19.         os_memcpy(dataBuf, data, data_len);
    8 e0 j% b0 r6 _9 p, h3 a' K- m
  20.         dataBuf[data_len] = 0;! p' \* B4 ^. H" R
  21. 0 t7 Z; U  }8 ]: M" }' L
  22. //        INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf);
    1 U) D& o1 K% l1 G; ]
  23. # u: S8 C. c  X: p# [% `/ @9 X
  24.         //data = {"url"="http://yourdomain.com:9001/ota/"}
    $ Y; V* H+ Y- ^( z7 G" s
  25.         if (os_strcmp(topicBuf, ota_topic) == 0) {# A9 c: P. z( |0 f! V
  26.                 char url_data[200];0 s3 o5 J5 S- K( R! I
  27.                 if(get_josn_str(dataBuf,"url",url_data)){
    + m6 E9 K4 R/ z4 U! o/ C; n
  28. //            INFO("ota_start\n");* N" i# O( d8 ]+ v6 |
  29.             ota_upgrade(url_data,ota_finished_callback);
    " W% ]- ]% u; K
  30.                 }
    * ?" K2 ~( T1 U% a1 I! @
  31.         }
    ! a0 O8 r: A4 _2 S5 |9 G; v7 y

  32. ; [; T2 {% f2 B1 N) X1 V! T2 v
  33.         os_free(topicBuf);
    , K1 z2 R0 `9 a/ v7 z8 y3 `
  34.         os_free(dataBuf);/ o0 R7 }. t* ^' l& ]

  35. - h- }7 Q* h! S  \
  36. / O, v. ~% N% Z. C
  37. 3 Q# A6 X$ [# w( c% m; b
  38. }
    + ]1 R& N7 P4 g) G6 v  P* a: E
  39. ' U* I$ v! u6 ^8 |
  40. /**
    $ G5 O5 Q# D4 `) [' q
  41. *         ota升级回调/ O0 m  o, D( y) n1 _* o
  42. */
    $ d4 R& V9 ?0 H( L( X; k) K
  43. void ICACHE_FLASH_ATTR ota_finished_callback(void * arg) {6 [0 d7 E' [& R& K5 Y
  44.         struct upgrade_server_info *update = arg;
    9 ~3 a2 S- z! N0 e- C, i8 x" Y; R
  45.         if (update->upgrade_flag == true) {: e; }5 [  U& L+ v( V
  46.                 INFO("OTA  Success ! rebooting!\n");( I! r# t4 a! Q, z6 z
  47.                 system_upgrade_reboot();
    ' I! H) ?5 r% U/ O
  48.         } else {
    & ]) Q8 a9 {$ \" G# H
  49.                 INFO("OTA Failed!\n");6 q0 P4 \$ C2 Q  A$ F$ Y
  50.         }
    / E$ V9 _$ e6 p% B, m9 q) v9 n( X) C
  51. }
复制代码

! N! b1 i/ b: H% H8 ~9 T3 R
其他问题:3 }5 K" Q2 D# M! V) G
连接的服务器地址,端口号等信息需要写在代码里烧录进模块,这些信息在在mqtt_config.h文件中定义。 微信图片_20210119121315.png ! v) U3 Y8 _& n7 B& F& V. E8 O9 o7 s  D
: }: O, z# U: b, M# r$ p, v
上电后可以在串口助手看到打印的MAC地址:( a" H/ J1 O1 L. I# O7 c
微信图片_20210119121318.png + Y% _2 U8 @0 [: U3 C/ ]
+ [4 G( Q( m1 j1 f! H% ]2 k' W
按下配网按键(GPIO14接地),进入配网模式,使用APP或者微信公众号将信息发给模块便可联网,联网后自动连接MQTT服务器。 微信图片_20210119121322.png
8 F7 f* O% G. F* I7 A 微信图片_20210119121326.png
/ Q1 J% _/ V6 v! _
至此连接完成,后续只需要串口发数据给模块,便可在服务器收到信息,服务器下发指令,单片机串口也可以接收到数据。但是要记得订阅主题哦。该透传代码烧录完成可搭配任意MCU的串口使用。非常便捷。由于项目期较远,可能介绍的不是很详细,需要的大大们可以点击阅读原文回帖获取源码。自行查看。
8 h( s3 N$ Y5 n3 x& P) K1 P
8 [* m% ]' c  Z. }6 X0 c
赞 收藏 评论0 发布时间:2021-1-19 12:16

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版