1. 程式人生 > 其它 >考研複試專案回顧——智慧積木開發(硬體開發方面)

考研複試專案回顧——智慧積木開發(硬體開發方面)

 首先是微控制器程式方面,由於使用了淘寶上買的開發板,上面已經集成了一些基礎模組,也附贈了它們的驅動程式。因此我的工作主要是:

  1)設計好整個硬體電路的功能,規劃好主邏輯(裸機)

  2)根據專案需求,選擇外接模組,併為各個模組寫驅動程式(藍芽,ESP8266,自制感測器陣列)

ESP8266+MQTT

  簡單來說,在我的專案中,ESP8266可以理解為,為一個mcu裝置添加了一個網絡卡,使用WiFi進行通訊,支援完整的tcp/ip協議棧。

       為了能夠正常的使用這個模組與阿里雲平臺使用mqtt協議進行通訊,我需要實現兩組功能:

    1)實現ESP8266通過串列埠與mcu通訊,實現ESP8266連線到環境內的WiFi上

    2)將mcu中儲存的遊戲資料封裝成mqtt資料報,實現與阿里雲平臺的通訊。

  我用了兩個c檔案完成上面的功能,為了方便,暫且稱為wifi.c和mqtt.c

     WiFi.c

  這其中我設計了以下內容(巨集定義很少,已省略)

    1)模組初始化函式:選擇了一個空閒IO口,將其設定成匹配的輸出模式。

    2)模組復位函式:根據晶片手冊的時序圖,控制IO口進行模組復位

    3)傳送AT指令函式:選擇串列埠2進行通訊。計數器清零,緩衝區清空,傳送指令,成功或者超時,返回結果。

    4)接入wifi函式:特殊AT指令函式。因為接入無線網需要特定的網路名稱和密碼,所以這個指令的實現也要單獨拿出來。

    5)連線伺服器函式:特殊的AT指令函式,由於mqtt是基於tcp的應用層協議,因此該函式試圖讓mcu訪問目的伺服器的域名地址,埠以建立tcp連線,各種連線錯誤對應不同的錯誤返回值,若連線成功,則傳送一般指令,進入透傳模式(只發送資料,不會有任何的修改)

    6)封裝函式:根據AT指令手冊,將mcu連線阿里雲物聯網平臺的過程封裝到一個函式內以便減少主函式程式碼量。

 

  MQTT.c

  mqtt協議的中文官方網址為:http://mqtt.p2hp.com/mqtt311

  先回顧一下我對MQTT的理解,只有理解了MQTT協議,才能寫出合格的程式碼。

    1)什麼是MQTT協議? ——MQTT協議是一個輕量級的釋出/訂閱資訊傳輸協議。使用者A釋出了一個topic及其Qos,其他使用者訂閱了這個topic後,只要使用者A釋出訊息,訂閱者們就會收到該訊息。

    2)為什麼要用MQTT協議?要在什麼場景下使用它?——這應該是比較難解釋的一個點了。

      先說一下成品中資料的流通方向:感測器陣列  -> mcu  -> 阿里雲物聯網平臺  -> 微信小程式  -> 阿里雲伺服器(模型部署所在)  -> 微信小程式

      在pc端跑模型的時候,我用的是mcu+bluetooth,這是因為我是在一個實驗室裡做的,距離很近。但成品中,使用硬體的老年人/小孩與使用手機的家長未必在一個很近的距離,因此無論是這個因素,還是資料量的大小而言,mqtt都是一個合適的選擇。客戶端包括:mcu,微信小程式。它們各自只與平臺通訊。

    3)怎麼使用MQTT協議?——我是mcu端的開發者,因此我所關心的事情包括:連線雲平臺,訂閱目標主題,處理接收報頭,心跳請求,如果收到startFlag就釋出Qos為0的資料報(壓力,時間資料)。這些通過14個基本控制報文中的一些就可以實現。

 

  這其中我設計了以下內容:

    1)首先我要設計合適的資料結構,管理髮送/接收緩衝區。緩衝區由[8][512]的二維陣列構成,定義三個陣列指標用於管理,分別指向資料的存放位置,讀取位置和緩衝區的結束位置。每次執行後續操作。存放/讀取指標會相應的變化。如果到底了,將buffer入棧,指標回到起點。

    2)初始化函式:初始化緩衝區,初始化產品ID,裝置名,金鑰,訂閱/釋出的主題等(金鑰用了阿里開源庫的雜湊加密演算法)

    後面的程式碼都涉及了上述功能的實現,因此要對MQTT3.1.1協議報文有一個基本的瞭解

    首先,MQTT資料報是基於TCP的應用層資料報,它包括三個部分:固定報頭,可變報頭和負載。

        固定報頭:是所有MQTT報文都必須有的部分,它由2個byte組成。

 

                            byte1的高4bit代表MQTT資料報的報文型別,低4bit根據每個不同型別的報文各有差別,byte2代表報文的剩餘長度。

        報文型別如下,這是我們填充byte1高4bit的重要依據。

        

        byte1低4bit為報文標識位,只有符合表中所示,才表示報文可用,否則連線關閉。

    byte2的資料代表接下來的資料還有多長(不帶他自己這個位元組),他一共可以用4個位元組,最高位是標誌位(後面一整個位元組必都是0,本位元組最高位也必是0),用迴圈取餘/取整/位運算就可以實現。

      可變報頭:每種報文的可變報頭都不太一樣,根據手冊擼程式碼就行。

 

            3)connect函式:填充固定報頭,計算剩餘長度,填充可變報頭(參考手冊),填充負載(ID,產品號,金鑰),加入傳送緩衝區

            4)subcribet函式:填充固定報頭,計算剩餘長度,填充可變報頭(參考手冊),填充負載(topic,QoS),加入傳送緩衝區

            5)ringreq函式:類似

    6)publish函式:只發布QoS0的推送,類似,多一個將資料指標以及資料長度當作引數輸入

    7)pubHandle函式:處理收到的推送函式,這個是最麻煩的,與微信小程式開發人員協定好:收到負載為0xFF表示開始遊戲。

      邏輯:接收所有推送,依次判斷其型別進入相應操作,當收到QoS0的public,進一步判斷其負載量,若為0xFF,返回對應值,交給主函式處理。

 

    主函式邏輯就不說了。