十、W5100S W5500+RP2040之MicroPython开发<MQTT示例>(2)

3. WIZnet以太网芯片

WIZnet 主流硬件协议栈以太网芯片参数对比

ModelEmbedded CoreHost I/FTX/RX BufferHW SocketNetwork Performance
W5100STCP/IPv4, MAC & PHY8bit BUS, SPI16KB4Max 25Mbps
W6100TCP/IPv4/IPv6, MAC & PHY8bit BUS, Fast SPI32KB8Max 25Mbps
W5500TCP/IPv4, MAC & PHYFast SPI32KB8Max 15Mbps
  • W5100S/W6100 支持 8bit数据总线接口,网络传输速度会优于W5500。
  • W6100 支持IPV6,与W5100S 硬件兼容,若已使用W5100S的用户需要支持IPv6,可以Pin to Pin兼容。
  • W5500 拥有比 W5100S更多的 Socket数量以及发送与接收缓存

相较于软件协议栈,WIZnet的硬件协议栈以太网芯片有以下优点

  1. 硬件TCP/IP协议栈:WIZnet的硬件协议栈芯片提供了一种硬件实现的TCP/IP协议栈,这种硬件实现的协议栈比软件实现的协议栈具有更好的性能和稳定性。
  2. 不需要额外的嵌入式系统软件栈和内存资源:由于所有的以太网传输和接收操作都由独立的以太网控制器处理,因此不需要额外的嵌入式系统软件栈和内存资源。
  3. 抵抗网络环境变化和DDoS攻击:与易受网络环境变化和DDoS攻击影响的软件TCP/IP协议栈相比,硬件协议栈芯片能够提供更稳定的以太网性能。
  4. 适用于低规格的嵌入式系统:即使在低规格的嵌入式系统中,使用WIZnet的硬件协议栈芯片也可以比使用软件TCP/IP协议栈的高规格系统显示出更高效的互联网应用操作性能。

在这里插入图片描述

4. MQTT 通信示例讲解以及使用

4.1 程序流程图

在这里插入图片描述

4.2 测试准备

软件:

  • Thonny
  • MQTTX

硬件:

  • W5100S IO模块 + RP2040 树莓派Pico开发板 或者 WIZnet W5100S-EVB-Pico开发板
  • Micro USB 接口的数据线
  • 网线

4.3 连接方式

  • 通过数据线连接PC的USB口
  • 当使用W5100S/W5500 IO模块连接RP2040时
    • RP2040 GPIO 16 <----> W5100S/W5500 MISO
    • RP2040 GPIO 17 <----> W5100S/W5500 CS
    • RP2040 GPIO 18 <----> W5100S/W5500 SCK
    • RP2040 GPIO 19 <----> W5100S/W5500 MOSI
    • RP2040 GPIO 20 <----> W5100S/W5500 RST
  • 通过网线直接连接PC网口(或:PC和设备都通过网线连接交换机或路由器LAN口)

4.4 相关代码

我们直接打开mqtt.py文件。

第一步:可以看到在w5x00_init()函数中,进行了SPI的初始化。以及将spi相关引脚和复位引脚注册到库中,后续则是激活网络,并使用DHCP配置网络地址信息,当DHCP失败时,则配置静态网络地址信息。当未配置成功时,会打印出网络地址相关寄存器的信息,可以帮助我们更好的排查问题。

第二步:尝试连接MQTT服务器,如果连接失败则进入复位程序。

第三步:订阅主题,绑定消息回调函数,并开启定时器定时进行保活。

第四步:等待接收消息,如果接收到了消息则进行回环处理。

此外,还需将umqttsimple.py库保存到开发板中,否则会导致运行出错。

#mqtt.py file
from umqttsimple import MQTTClient
from usocket import socket
from machine import Pin,SPI,Timer
import network
import time
import json

#mqtt config
mqtt_params = {}
mqtt_params['url'] = 'test.mosquitto.org'
mqtt_params['port'] = 1883
mqtt_params['clientid'] = 'W5100S'
mqtt_params['pubtopic'] = '/W5100S/pub'
mqtt_params['subtopic'] = '/W5100S/sub'
mqtt_params['pubqos'] = 0
mqtt_params['subqos'] = 0

timer_1s_count =  0
tim = Timer()
client = None

"""
W5x00 chip initialization.
 
param: None
returns: None

"""
def w5x00\_init():
    spi=SPI(0,2\_000\_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18))
    nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin
    nic.active(True)
    
    try:
        #DHCP
        print("\r\nConfiguring DHCP")
        nic.ifconfig('dhcp')
    except:
        #None DHCP
        print("\r\nDHCP fails, use static configuration")
        nic.ifconfig(('192.168.1.20','255.255.255.0','192.168.1.1','8.8.8.8'))#Set static network address information
    
    #Print network address information
    print("IP :",nic.ifconfig()[0])
    print("Subnet Mask:",nic.ifconfig()[1])
    print("Gateway :",nic.ifconfig()[2])
    print("DNS :",nic.ifconfig()[3],"\r\n")
    
    #If there is no network connection, the register address information is printed
    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())

"""
Subscribe to the topic message callback function. This function is entered when a message is received from a subscribed topic.
 
param1: The topic on which the callback is triggered
param2: Message content
returns: None

"""
def sub\_cb(topic, msg):
    topic = topic.decode('utf-8')
    msg = msg.decode('utf-8')
    if topic == mqtt_params['subtopic']:
        global client
        print("\r\ntopic:",topic,"\r\nrecv:", msg)
        client.publish(mqtt_params['pubtopic'],msg,qos = mqtt_params['pubqos'])
        print('\r\ntopic:',mqtt_params['pubtopic'],'\r\nsend:',msg)
    
"""
Connect to the MQTT server.
 
param: None
returns: None

"""
def mqtt\_connect():
    client = MQTTClient(mqtt_params['clientid'], mqtt_params['url'], mqtt_params['port'],keepalive=60)
    
    client.connect()
    print('Connected to %s MQTT Broker'%(mqtt_params['url']))
    return client

"""
Connection error handler.
 
param: None
returns: None

"""
def reconnect():
    print('Failed to connected to Broker. Reconnecting...')
    time.sleep(5)
    machine.reset()

"""
1-second timer callback function.
 
param1: class timer
returns: None

"""
def tick(timer):
    global timer_1s_count
    global client
    timer_1s_count += 1
    if timer_1s_count >= 30:
           timer_1s_count = 0 
           client.ping()

"""
Subscribe to Topics.
 
param: client object
returns: None

"""
def subscribe(client):
    client.set_callback(sub_cb)
    client.subscribe(mqtt_params['subtopic'],mqtt_params['subqos'])
    print('subscribed to %s'%mqtt_params['subtopic'])
 
    
def main():
    global client
    print("WIZnet chip MQTT example")
    w5x00_init()
    
    try: 
        client = mqtt_connect()
    except OSError as e:
        reconnect()
        
    subscribe(client)
    
    tim.init(freq=1, callback=tick)
    
    while True:
        client.wait_msg()
        
        
    client.disconnect()

if __name__ == "\_\_main\_\_":
    main()

#umqttsimple.py file
import usocket as socket
import ustruct as struct
from ubinascii import hexlify


class MQTTException(Exception):
    pass


class MQTTClient:
    def \_\_init\_\_(
        self,
        client_id,
        server,
        port=0,
        user=None,
        password=None,
        keepalive=0,
        ssl=False,
        ssl_params={},
    ):
        if port == 0:
            port = 8883 if ssl else 1883
        self.client_id = client_id
        self.sock = None
        self.server = server
        self.port = port
        self.ssl = ssl
        self.ssl_params = ssl_params
        self.pid = 0
        self.cb = None
        self.user = user
        self.pswd = password
        self.keepalive = keepalive
        self.lw_topic = None
        self.lw_msg = None
        self.lw_qos = 0
        self.lw_retain = False

    def \_send\_str(self, s):
        self.sock.write(struct.pack("!H", len(s)))
        self.sock.write(s)

    def \_recv\_len(self):
        n = 0
        sh = 0
        while 1:
            b = self.sock.read(1)[0]
            n |= (b & 0x7F) << sh
            if not b & 0x80:
                return n
            sh += 7

    def set\_callback(self, f):
        self.cb = f

    def set\_last\_will(self, topic, msg, retain=False, qos=0):
        assert 0 <= qos <= 2
        assert topic
        self.lw_topic = topic
        self.lw_msg = msg
        self.lw_qos = qos
        self.lw_retain = retain

    def connect(self, clean_session=True):
        self.sock = socket.socket()
        addr = socket.getaddrinfo(self.server, self.port)[0][-1]
        self.sock.connect(addr)
        if self.ssl:
            import ussl

            self.sock = ussl.wrap_socket(self.sock, \*\*self.ssl_params)
        premsg = bytearray(b"\x10\0\0\0\0\0")
        msg = bytearray(b"\x04MQTT\x04\x02\0\0")

        sz = 10 + 2 + len(self.client_id)
        msg[6] = clean_session << 1
        if self.user is not None:
            sz += 2 + len(self.user) + 2 + len(self.pswd)
            msg[6] |= 0xC0
        if self.keepalive:
            assert self.keepalive < 65536
            msg[7] |= self.keepalive >> 8
            msg[8] |= self.keepalive & 0x00FF
        if self.lw_topic:
            sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
            msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
            msg[6] |= self.lw_retain << 5

        i = 1
        while sz > 0x7F:
            premsg[i] = (sz & 0x7F) | 0x80
            sz >>= 7
            i += 1
        premsg[i] = sz

        self.sock.write(premsg, i + 2)
        self.sock.write(msg)
        # print(hex(len(msg)), hexlify(msg, ":"))
        self._send_str(self.client_id)
        if self.lw_topic:
            self._send_str(self.lw_topic)
            self._send_str(self.lw_msg)
        if self.user is not None:
            self._send_str(self.user)
            self._send_str(self.pswd)
        resp = self.sock.read(4)
        assert resp[0] == 0x20 and resp[1] == 0x02
        if resp[3] != 0:
            raise MQTTException(resp[3])
        return resp[2] & 1

    def disconnect(self):
        self.sock.write(b"\xe0\0")
        self.sock.close()

    def ping(self):
        self.sock.write(b"\xc0\0")

    def publish(self, topic, msg, retain=False, qos=0):
        pkt = bytearray(b"\x30\0\0\0")
        pkt[0] |= qos << 1 | retain
        sz = 2 + len(topic) + len(msg)
        if qos > 0:
            sz += 2
        assert sz < 2097152
        i = 1
        while sz > 0x7F:
            pkt[i] = (sz & 0x7F) | 0x80
            sz >>= 7
            i += 1
        pkt[i] = sz
        # print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt, i + 1)
        self._send_str(topic)
        if qos > 0:
            self.pid += 1
            pid = self.pid
            struct.pack_into("!H", pkt, 0, pid)
            self.sock.write(pkt, 2)
        self.sock.write(msg)
        if qos == 1:
            while 1:
                op = self.wait_msg()
                if op == 0x40:
                    sz = self.sock.read(1)
                    assert sz == b"\x02"
                    rcv_pid = self.sock.read(2)
                    rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
                    if pid == rcv_pid:
                        return
        elif qos == 2:
            assert 0

    def subscribe(self, topic, qos=0):
        assert self.cb is not None, "Subscribe callback is not set"
        pkt = bytearray(b"\x82\0\0\0")
        self.pid += 1
        struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
        # print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt)
        self._send_str(topic)
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/1192ff607a9471cdbe24a15a80a694be.png)

![img](https://img-blog.csdnimg.cn/img_convert/fcc43bb129fd3d646216b7ffd741109b.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/ef27997fdf99a372d56fa323c9fcd6d5.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/608e91b0d96a3fde9d70bc5f28441d75.png)

![img](https://img-blog.csdnimg.cn/img_convert/6a1ab01c20d97782fa6b130b262d6746.png)

![img](https://img-blog.csdnimg.cn/img_convert/661a8b9d341a23f2693649be7720e39f.png)

![](https://img-blog.csdnimg.cn/img_convert/0160a6447b77874fe59321b1f562f96d.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


asZIQ-1715680703943)]

 [外链图片转存中...(img-KiUEebMK-1715680703944)]

[外链图片转存中...(img-XW54NNAb-1715680703945)]

[外链图片转存中...(img-aIaxyLHa-1715680703946)]

[外链图片转存中...(img-N29wqJQ5-1715680703947)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
W5500是一款由韩国WIZnet公司推出的基于TCP/IP和物理层的以太网控制器芯片。它具有低功耗、高速传输、低成本等特点,广泛应用于各种物联网设备中。 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,它专门设计用于物联网设备之间的通信。MQTT协议具有简单、灵活、高效的特点,适用于低带宽、不稳定网络情况下的通信。 将W5500MQTT协议结合使用,可以实现物联网设备之间的通信和数据传输。W5500作为以太网控制器芯片,负责处理与网络连接相关的任务,如建立和维护网络连接、数据传输等。MQTT协议则负责定义数据传输的格式、规则和消息订阅、发布机制。 使用W5500MQTT协议可以实现物联网设备与服务器之间的双向通信。设备可以通过订阅特定主题来获取服务器发布的消息,并通过发布消息来向服务器发送数据。通过这种方式,物联网设备可以实时更新状态、接收控制命令,并与其他设备进行通信。 在使用W5500MQTT协议进行通信时,需要在设备内部实现MQTT协议的相关功能,如消息解析、主题订阅、数据发布等。这可以通过使用开源的MQTT库来实现,如Paho MQTT等。通过将W5500MQTT协议结合使用,可以简化物联网设备之间的通信方式,提高设备的灵活性和互操作性。 总之,W5500MQTT协议的结合可以实现物联网设备之间的快速、可靠的通信,为物联网应用提供了一种高效、灵活的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值