<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ESA2GJK1DH1K_A/" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
說明
此節適用於所有支持TCP通信的模組!
准備一份程序(先看透傳版)
透傳版就是配置好模組以后直接發送數據給模組,模組就把信息直接轉發到網絡
模組從網絡接收到數據就直接輸出.
1.准備一份已經實現TCP通信的程序
2.TCP連接
注:因為是WiFi模塊,所以需要連接路由器(連接的路由器名稱和密碼根據自己的修改)
連接的IP地址是MQTT服務器的地址
連接TCP以后模塊進入透傳模式
2.我把網絡接收的數據緩存到了環形隊列
開始移植
1.把這節里面的mem和MQTT文件夾拷貝到工程目錄
注:我提供的STM32F10xTemplate工程里面已經有了mem,可不用拷貝
2.把mem和MQTT添加到工程
3.寫上下面的程序
注:MQTT信息根據自己的修改
#include "mqtt.h" char mqtt_connect_flag=0;//1:Á¬½ÓÉÏMQTT·þÎñÆ÷; 0:δÁ¬½ÓÉÏMQTT·þÎñÆ÷ char mqtt_id[50] = "11223344";//ClientID char mqtt_username[20] = "yang";//Óû§Ãû char mqtt_password[50] = "11223344";//ÃÜÂë char mqtt_keepalive = 30;//ÐÄÌø°üʱ¼ä unsigned char mqtt_publish_topic[30]="";//´æ´¢MQTT·¢²¼µÄÖ÷Ìâ unsigned char mqtt_subscribe_topic[30]="";//´æ´¢MQTT¶©ÔĵÄÖ÷Ìâ /**¶©ÔÄÖ÷Ìâ³É¹¦**/ void subscribedCb(int pdata){ printf("\r\n³É¹¦¶©ÔÄÖ÷Ìâ\r\n"); } /**¶©ÔÄÖ÷Ìâʧ°Ü**/ void failsubscribedCb(int pdata){ printf("\r\n¶©ÔÄÖ÷Ìâʧ°Ü\r\n"); } /**·¢²¼³É¹¦**/ void PublishedCb(){ printf("\r\n·¢²¼³É¹¦\r\n"); } /*Á¬½ÓÉÏMQTT»Øµ÷º¯Êý*/ void MqttConnect(){ printf("\r\nÁ¬½Ó³É¹¦**********************************************************\r\n"); mqtt_connect_flag = 1; } /**MQTT¶Ï¿ªÁ¬½Ó»Øµ÷**/ void MqttDisConnect(){ printf("\r\nÁ¬½Ó¶Ï¿ª**********************************************************\r\n"); mqtt_init(&mymqtt); mqtt_connect_flag=0; } /** * @brief MQTT½ÓÊÕÊý¾Ý»Øµ÷ * @param topic:Ö÷Ìâ * @param topic_len:Ö÷Ìⳤ¶È * @param data:½ÓÊÕµÄÊý¾Ý * @param lengh:½ÓÊÕµÄÊý¾Ý³¤¶È * @retval None * @warning None * @example **/ void MqttReceive(const char* topic, uint32_t topic_len,const char *data, uint32_t lengh) { } void MqttConnect(void);//Á¬½ÓÉÏMQTT»Øµ÷ void MqttDisConnect(void);//MQTT¶Ï¿ªÁ¬½Ó»Øµ÷ void subscribedCb(int pdata);//¶©Ôijɹ¦»Øµ÷ void failsubscribedCb(int pdata);//¶©ÔÄʧ°Ü»Øµ÷ void PublishedCb(void);//³É¹¦·¢²¼ÏûÏ¢»Øµ÷ void MqttReceive(const char* topic, uint32_t topic_len,const char *data, uint32_t lengh);//½ÓÊÕµ½Êý¾Ý»Øµ÷ mqtt_init(&mymqtt); mqtt_connect_reg(&mymqtt,MqttConnect);//×¢²áÁ¬½Ó»Øµ÷º¯Êý mqtt_disconnect_reg(&mymqtt,MqttDisConnect);//×¢²á¶Ï¿ªÁ¬½Ó»Øµ÷º¯Êý mqtt_received_reg(&mymqtt,MqttReceive);//×¢²á½ÓÊÕÊý¾Ý»Øµ÷º¯Êý
//Á¬½ÓÉÏMQTT·þÎñÆ÷ if(mqtt_connect_flag) { mqtt_send_function(&mymqtt);//ÌáÈ¡·¢ËÍ»º´æµÄMQTTÐÒé mqtt_keep_alive(&mymqtt);//´¦Àí·¢ËÍÐÄÌø°ü }
4.把mqtt_time_data(&mymqtt); 放到1ms定時器里面
5.在mqtt.c里面替換自己的tcp發送數據函數
注:我的單片機是通過串口2和模組通信
關於下面的 mymqtt.timer_out_send = 0; 這個是預防有的模塊發送數據之后需要等待,按照提示修改就可以
wifi模塊透傳模式下每條數據的時間間隔需要保持在20ms以上,所以我直接設置的20

6.編寫組合發送連接MQTT協議函數
7.連接上TCP服務器以后每隔一段時間發送MQTT連接協議給服務器
8.把模組接收的網絡數據交給mqtt處理函數處理
注:在未連接上mqtt服務器交給 mqtt_function_connect_ack函數(該函數判斷連接成功會調用注冊的mqtt連接成功回調)
注:在連接上mqtt服務器交給 mqtt_read_function 函數
9.把代碼下載測試
10.斷線重連
典型處理方式:在TCP斷開的時候需要重新連接TCP,然后再連接MQTT
在MQTT斷開的時候讓模組也重新連接TCP.
現在wifi模組是透傳模式,模組不會返回tcp斷開的信息了,所以就只在mqtt斷開連接回調里面重新讓tcp連接
11.訂閱主題和發布消息
12.提示
只要是連接上MQTT服務器了,可以在任意地方調用訂閱和發布函數.
打包的信息都緩存到了內部的緩存管理里面,緩存管理使用的是我在環形隊列基礎上封裝的 BufferManage
13.如果自己的MQTT數據包超過500不超過16383字節,則只需要修改數據緩存大小
mqtt_send_buff_len是每個數據包的長度(假設自己的數據包最大是800,則可以設置為802)
send_buff_loop_len 是保存每個數據包數組的長度(一般設置為mqtt_send_buff_len的整數倍)
14.如果自己的MQTT數據包超過16383字節,則還需要修改底層
當前是使用兩字節保存數據個數
15.接收數據,如果內存充足,推薦的處理方式
現在看非透傳版
透傳版和非透傳版只是發送和接收數據的方式不一樣,所以就在透傳版的基礎上修改
1.首先模塊資料
2.TCP連接改為非透傳多鏈接模式(使用的socket 0 進行的連接)
3.改一下接收數據的地方,咱使用另外一個緩存只存儲網絡數據
3.改一下發送連接協議的方式
4.串口接收處理數據改一下
上面只處理連接上MQTT服務器前和連接中出現的問題
下面是把網絡數據交給MQTT處理函數處理
5.現在應該可以連接上MQTT服務器了
6.接着修改這里面
這里也需要改為先發送 AT+CIPSEND 然后再發送真實數據
發送真實數據咱在透傳的時候以后寫了.
我這個底層其實也是支持非透傳的.
7.設置為非透傳模式
8.編寫發送數據命令函數
8.根據下面的提示修改 >
9.現在已經可以了
結語
代碼不是重要的,重要的是處理思想和方案.