几步实现stm32上面移植mqtt

 最近项目需要,stm32上面使用到mqtt了,百度了下,发现网上资料还是挺少的,虽然有几份相关的资料,下载下来之后,看到了mqtt的底层代码竟然还有错误,这个问题导致了我后面一直调试不通,后来,我直接从官方下载了mqtt的源码用比较器比较后找到了原因,最后果断将官方的mqtt底层代码移植上来,mqtt的发布还是比较顺利,订阅虽然可以收到消息,但是由于没有移植os,发布消息时,订阅接受有时无法收到消息,这个还在优化,我使用的是stm32f103c8t6平台+w5500.其实只要带以太网接口就行。  首先我们从mqtt官方下载源码
http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.embedded-c.git/refs/
下载后将 MQTTPacket下面的src文件都加入到自己的MDK工程中。


如果采用W5500的话,最好先用官方的TCP例子将TCP调试通,而且能保证访问外网,可以借鉴下网上那个STM32F405+W5500的例子,我觉得那个还是挺好的,我也是主要借鉴了那个例子,不过我还是不太喜欢他把TCP的建立封装到mqtt里面,一开始我也是采用他那种方法,不过一直出错,后来我采用了状态机实现,先让TCP和mqtt服务器建立TCP连接在调用mqtt的连接,发布等API,这样比较好调试。调试的话,我采用的是下面那个页面调试的 http://m2m.demos.ibm.com/mqttclient/#log

其实真正要你实现的mqtt接口,主要是transport.c里面的几个API
int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
  return send(SOCK_MQTT,buf,buflen);
}
/**
  * @brief  ×èèû·½ê½½óêÕTCP·tÎñÆ÷·¢ËíμÄêy¾Y
  * @param  buf êy¾Y′æ′¢ê×μØÖ·
  * @param  count êy¾Y»o3åÇø3¤¶è
  * @retval D¡óú0±íê¾½óêÕêy¾Y꧰ü
  */
int transport_getdata(unsigned char* buf, int count)
{
  return recv(SOCK_MQTT,buf,count);
}


/**
  * @brief  ′ò¿aò»¸ösocket2¢ᬽóμ½·tÎñÆ÷
  * @param  ÎT
  * @retval D¡óú0±íê¾′ò¿a꧰ü
  */
int transport_open(void)
{
  int32_t ret;
  //D½¨ò»¸öSocket2¢°ó¶¨±¾μض˿ú5000
  ret = socket(SOCK_MQTT,Sn_MR_TCP,4500,Sn_MR_ND);
  if(ret != SOCK_OK){
    printf("%d:Socket Error\r\n",SOCK_MQTT);
  }else{
    printf("%d:Opened\r\n",SOCK_MQTT);
  }

  //ᬽóTCP·tÎñÆ÷
  ret = connect(SOCK_MQTT,domain_ip,1883);//¶Ë¿ú±ØDëÎa1883
  if(ret != SOCK_OK){
    printf("%d:Socket Connect Error\r\n",SOCK_MQTT);
  }else{
    printf("%d:Connected\r\n",SOCK_MQTT);
  }               
        return ret;
}
/**
  * @brief  1رÕsocket
  * @param  ÎT
  * @retval D¡óú0±íê¾1رÕ꧰ü
  */
int transport_close(void)
{
  close(SOCK_MQTT);
  return 0;
}

以上的其实transport_open(void)我没调用,让状态机来实现了这步。
int mqtt_publish(char *pTopic,char *pMessage)
{
  int32_t len,rc;
  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  unsigned char buf[200];
  MQTTString topicString = MQTTString_initializer;
  int msglen = strlen(pMessage);
  int buflen = sizeof(buf);
  data.clientID.cstring = "Client74925";
  data.keepAliveInterval = 15;
  data.cleansession = 1;
  len = MQTTSerialize_connect(buf, buflen, &data); /* 1 */
  topicString.cstring = pTopic;
  len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen); /* 2 */
  len += MQTTSerialize_disconnect(buf + len, buflen - len); /* 3 */
  rc = transport_sendPacketBuffer(buf,len);
        if (rc == len)
                printf("Successfully published\n\r");
        else
                printf("Publish failed\n\r");
  return 0;
}

=========================================

void do_tcp_client(void)
{       
  uint8 connect_State = 0;
        uint16 len1;
        switch(getSn_SR(SOCK_MQTT))                                                                                                           /*»ñè¡socketμÄ×′ì¬*/
        {
                case SOCK_CLOSED:                                                                                                                         /*socket′|óú1رÕ×′ì¬*/
                        socket(SOCK_MQTT,Sn_MR_TCP,local_port++,Sn_MR_ND);
                  break;               
                case SOCK_INIT:                                                                                                                                 /*socket′|óú3õê¼»ˉ×′ì¬*/
                        connect(SOCK_MQTT,domain_ip,1883);                       /*socketᬽó·tÎñÆ÷*/
                  break;               
                case SOCK_ESTABLISHED:                                                                                                              /*socket′|óúᬽó½¨á¢×′ì¬*/       
                        memset(buff,0,500);
                #if 0
                        connect_State=mqtt_subscrib("planets/earth",buff);
                  if(connect_State)
                        {               
        printf("%s",buff);
                               
      }
                #endif
                 if(heartbeatflag>=TIME_5S)
                 {
                         heartbeatflag=0;
                   mqtt_publish("planets/earth","firstName: Brett, lastName:McLaughlin,email:aaaa");         
                 }         
                  break;                       
                case SOCK_CLOSE_WAIT:                                                                                                              /*socket′|óúμè′y1رÕ×′ì¬*/
                        close(SOCK_MQTT);
                  break;

        }
}
上面的发布我每5s发送一条消息,公司的电脑加密了,无法截图,只能copy下网页测试的数据
============================================================================
(06:23:57.487) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.492) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.810) >> [planets/earth][retained] Hello world!(06:24:02.810) Subscribed to [planets/earth][qos 0](06:24:07.501) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:12.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:17.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:22.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:27.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:32.481) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:37.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:42.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:47.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa
订阅消息的函数目前暂且不公布,主要是还在优化,其次我觉得有点鸡肋,以其误导大伙,还不如不公开~~~~~~~~~~~~,如果大伙觉得有意思,可以把mqtt的ping也加上去,如果实用的话,这个还需要加入很多容错机制~~~~~~~~~~~~
  • 7
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
首先,我们需要了解MQTT是什么。MQTT是一种轻量级的即时通讯协议,它被设计用于在低带宽和不稳定的网络环境中传输消息。而STM32是一种32位的微控制器,具有较高的计算和通信能力。 要在STM32移植MQTT,需要完成以下几个步骤: 1. 硬件支持:确保STM32芯片具有与MQTT协议相关的硬件功能,例如串口通信、网络接口等。如果芯片不支持这些硬件功能,可能需要通过外部组件进行扩展,以满足MQTT的通信要求。 2. 选择MQTT库:选择适合STM32平台的MQTT库,并将其添加到项目中。常见的MQTT库包括Paho MQTT、emMQTT等。选择合适的库取决于需求和特定的硬件平台。 3. 连接底层驱动:MQTT库通常需要与底层驱动程序进行连接,以实现STM32芯片的通信。这可能涉及到串口、网络接口等底层驱动的配置和集成。 4. 配置MQTT:根据需要配置MQTT协议的参数,例如服务器地址、端口号、订阅/发布的主题等。这些参数可以在代码中进行配置,或者基于外部存储器(如EEPROM)进行配置,以便随时更改。 5. 处理MQTT消息:在STM32实现MQTT协议的主要目的是能够发送和接收消息。因此,需要在代码中实现相应的消息处理函数,以便从服务器接收消息、订阅主题或发布消息。 6. 错误处理:在移植和使用过程中,可能会出现一些错误或异常情况。为了确保系统的稳定性和可靠性,需要实现适当的错误处理机制和异常处理代码。 在完成了上述步骤后,STM32就成功移植MQTT协议,并可以通过MQTT实现与其他设备之间的通信。这为在低带宽和不稳定网络环境下进行实时通信提供了一种轻量级和简便的解决方案。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值