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

【经验分享】MQTT 协议学习:008-在STM32上移植MQTT

[复制链接]
STMCU小助手 发布时间:2022-2-8 21:58
前言
通过前面了解MQTT有关概念、分析了有关的报文,我们对于这个协议也有了更深的认识。但纸上谈来终觉浅,绝知此事要躬行。
* F& Y: l; t; g, \
W5500 - 芯片介绍
全硬件TCPIP协议栈
  • 支持TCP,UDP,ICMP,IPv4,ARP,IGMP,PPPoE协议
  • 硬件协议栈不受网络攻击,安全稳定
    6 H; K4 }# l' o7 w7 D: k
8个独立的硬件Socket,各路通信互不影响
% N' S& M% O9 o6 R9 H8 h32KB片上缓存供TCP/IP包处理
* z% N% z% K" W) S; E集成802.3以太网MAC
" |! `# \8 f: V集成10BaseT / 100Base-T以太网PHY& Z1 z# i0 Z5 ], M, s+ a* U; F
主机接口:SPI高速串行外设接口(最高80Mhz )
低功耗,工作温度40℃左右/ ?) ?% p2 f- T& a6 h% t+ [
支持嵌入式操作系统:Linux & RTOS' d& d8 R( ^' _8 ?! z
支持掉电模式 & UDP网络唤醒: F9 u: |3 X& @2 C6 Q$ O
工作电压3.3V,I/O 5V耐压1 n3 {$ ?$ |" g3 B' }3 u& K
支持自动协商(全/半双工,10M/100M). [# S5 D! `8 Q( [
48Pin LQFP无铅封装(7x7mm, 0.5mm针间距)
, n; V6 l) @2 q5 n( @) j
W5500以太网芯片内核
* [. L! J. B$ m1 m6 P/ T
1281523-20200208115742430-1272220396.png

# q8 C' y+ w$ V* X; Q! H' B
全硬件TCP/IP协议栈以太网接入方案
MCU <---spi---> w5500 <------> 以太网
/ V) I( K4 _0 r9 m( F/ VMCU : 应用层- T  L. d3 ?- @8 ^7 T: ~
w5500 : 传输层,网络层,链路层,物理层

6 z1 H* {' S) l方案介绍
STM32 <---spi---> W5500 <------> 以太网/ G( d& T3 z/ N! d- Q2 X8 W, x
实际上,单片机这块有很多的方案:RTL8711(WIFI SOC) + LWIP + FreeRTOS + MQTT、ESP8266 + MQTT
1)STM32F405为主控芯片,它通过传感器采集环境数据,比如温度,湿度,光照度,大气压强等;; f" S7 V8 N( Y$ `9 N2 S
2)主控芯片通过W5500模块将测量的数据通过MQTT协议方式发布到MQTT服务器(服务器域名和IP见固件程序);
! {1 A% N) Q1 F6 I2 F; g3)主控订阅LED灯控制的消息,当接收到对应的控制指令后点亮或者熄灭对应的LED灯;
( W) ^! L/ u: \- n, P4)安卓手机端订阅传感器数据的消息,当接收到消息后将传感器数据在界面显示;
( P2 i5 I) C/ \$ l4 U5)安卓手机可发送点亮或者熄灭LED灯的指令到服务器,然后服务器会将该指令转发给STM32主控,然后STM32主控解析该指令并执行指令。

+ z1 Y, S0 y( \" i; h准备
1)下载MQTT客户端 源码
2)解压源码,再进入MQTTPacket文件夹,里面有三个文件夹。
: e1 x5 I% j- t7 G. SA)) 拷贝 src 下 所有 *.c *.h、samples下的transport.c、transport.h两个文件复制到工程目录下。
这里我们主要的移植工作就在transport里面。
打开transport.c文件,这个是MQTT连接,发送,接收的接口,源码是Linux跟Windows平台,用的标准的Socket接口函数,我们这里的移植工作量很小,因为LWIP也是支持标准的Socket接口函数,只不过里面有些函数接口是LWIP不支持的,主要就是transport_open这个连接函数有区别。把原来的transport_open函数注释掉,重新写一个。
如果STM32或者其它单片机是用WIFI模块或者GPRS模块,没有用到LWIP的怎么办。其实只要理解的MQTT的源码,就不难用GPRS或者WiFi模块去实现。
& m9 x, r) R9 I' hMQTT的源码里都是对协议包进行打包解包,数据传输都是在tranport.c里面,我们完全不用transport,可以自己写通信接口,然后把打包的数据包通过模块发出去,写接收接口,把模块接收到服务器数据调用MQTT解包接口解析就可以了。
MQTT的移植非常简单,将C/C++ MQTT Embedded clients的代码添加到工程中,然后我们只需要再次封装4个函数即可:
  1. // 通过网络以TCP的方式发送数据  X$ F6 Y- B6 k  `
  2. int transport_sendPacketBuffer(unsigned char* buf, int buflen); ; O! @: p8 Z0 \

  3. 7 M& A) f7 i& Y( o! p
  4. // TCP方式从服务器端读取数据,该函数目前属于阻塞函数;5 g( Y0 F9 T, H- z
  5. int transport_getdata(unsigned char* buf, int count);! F8 e+ o% ?5 {/ V4 i
  6. ) k/ C  n) q7 R7 h1 y/ e1 I3 I
  7. // 打开一个网络接口,其实就是和服务器建立一个TCP连接;
    , V0 q- \# H9 a
  8. int transport_open(void);. O' n6 @% \# r/ w! j  ]$ X1 R1 w7 X

  9. $ o1 Z3 U, W6 e1 q4 F
  10. // 关闭网络接口。
    7 x! C, a6 [, S; e( d
  11. int transport_close(void);
    7 `, X( T8 F9 q5 n! A; Q' @/ n

  12. 3 U/ ?, S, _, C- {7 P: m- s
  13. // 因为LWIP也是支持标准的Socket接口函数,只不过里面有些函数接口是LWIP不支持的,主要就是transport_open这个连接函数有区别。
      b, ?/ n" X9 n/ {( W
  14. // 所以,如果 协议栈是 LWIP,那么只需要 把原来的transport_open函数注释掉,重写 即可1 Z* r6 J# m  d
复制代码

5 o1 v7 l! \/ Q. Q( U1 T% k9 w  F* H1 ?
$ b4 n6 N" [9 G5 t' h
赞 收藏 评论0 发布时间:2022-2-8 21:58

举报

0个回答

所属标签

相似技术帖

官网相关资源

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