物联网学习之旅:微信小程序控制STM32(二)--ESP8266连接mqtt服务端
ESP8266連接mqtt服務端
微信小程序控制STM32的第二步,就是要編寫ESP8266固件,來連接已經搭建好的物聯網服務器。也有別的方式,只要你足夠了解mqtt協議,可以通過使用ESP8266原生的AT指令來連接,因為ESP8266連接mqtt服務端中mqtt協議也是通過建立TCP連接,發送相應的協議報文來連接服務端。但是樂鑫官方提供的SDK中含有連接mqtt服務端的實例代碼,要做的就是根據自己的功能要求去修改代碼。
我修改的固件是ESP8266與STM32之間進行串口通信,以透傳的方式互相傳遞數據,然后ESP8266作為中轉把數據發到相應的目的地。
我用的是ESP8266-01這款模塊
ESP8266有UART 下載模式和Flash 運行模式 ,接線不一樣的地方就是在下載模式時GPIO0要接低電平,運行模式時懸空即可,每次運行模式和下載模式切換都需要重啟一下模塊,才能第二次燒寫或者運行。
我是采用這樣的連接方式來燒寫固件,運行程序時把GPIO0拔掉,然后拔掉esp8266的vcc線,然后又插上,重啟一下就可以了。燒寫的時候把GPIO0接共地端,然后拔掉esp8266的vcc線,然后又插上,重啟一下,就可以燒寫程序了。至于我為什么要用這么復雜的接線方式來燒寫程序,那是因為買這個esp8266調試器的時候,不懂,圖便宜(根本也是因為我太窮了,哈哈哈),然而這個用來運行調試是最合適的,直接插上去即可。不過這樣也能燒寫固件。也可以用TTL轉串口來燒寫,都是可以的,原理都一樣。
進入安信可ESP8266 系列模組專題,按照開發環境搭建的步驟搭建開發環境。
點擊藍色文字下載ESP8266_NONOS_SDK-v3.0.0,也可以選擇在樂鑫官網上下載最新版本的SDK,根據需要下載開發文檔,我用到了這兩個文檔。
值得注意的是,本項目用到的是esp_mqtt_proj這個例程,所以在構建工程文件時,需要將examples/esp_mqtt_proj目錄工程目錄的頂層文件中,其它的按照安信可提供的步驟搭建即可,編譯沒有錯誤之后,其實example文件夾就可以刪除掉了,這個項目只用到mqtt部分,其它例程刪掉后編譯仍然是成功的。
打開編譯通過的工程,需要修改的有這幾個地方
1)user_main.c中修改
2)uart.c中修改
通過user_main.c文件中的uart_init()定位到uart.c文件,然后對這里面進行修改。首先需要引入user_main.c定義的“MQTT_Client* mqttclient;”,這樣下面在串口處理函數中,當從串口接收完數據之后,通過引入的mqtt客戶端指針,將數據發到特定的主題,然后別忘了引入“mqtt.h”,因為這里要用到這里面的函數,將數據發送出去。
最后修改串口中斷處理函數。
LOCAL void uart0_rx_intr_handler(void *para) {/* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents* uart1 and uart0 respectively*/uint8_t RcvChar[256];uint8_t uart_no = UART0;//UartDev.buff_uart_no;uint8_t fifo_len = 0;uint8_t buf_idx = 0;uint8_t temp, cnt;if (UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) {DBG1("FRM_ERR\r\n");WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);} else if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) {DBG("f");uart_rx_intr_disable(UART0);WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);system_os_post(uart_recvTaskPrio, 0, 0);} else if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) { //檢測到是超時中斷fifo_len=(READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; //獲取數據長度buf_idx=0;for(buf_idx=0;buf_idx<fifo_len;buf_idx++){RcvChar[buf_idx]=READ_PERI_REG(UART_FIFO(UART0))&0xFF; //將數據儲存起來}if(RcvChar[0]=='A'){ //接收到詢問是否初始化完成的消息if(mqttState==1){ //初始化完成了os_printf("1111\r\n"); //串口發送初始化完成,如果發送字母就會亂碼}else{os_printf("2222\r\n");}}if(RcvChar[0]=='{'){MQTT_Publish(mqttclient, "Topic1", RcvChar, fifo_len, 0, 0); //把接收到的數據發送到mqtt服務端}if(RcvChar[0]=='T'){os_printf("\r\ntime:%s\r\n", time);}os_memset(RcvChar,0,256); //清除數據WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR); //清除超時中斷狀態} else if (UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)) {DBG("e");CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); #if UART_BUFF_ENtx_start_uart_buffer(UART0); #endif//system_os_post(uart_recvTaskPrio, 1, 0);WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);} else if (UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST)) {WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR);DBG1("RX OVF!!\r\n");}}問為什么要這樣改,官方文檔中做出了說明,參考esp8266技術參考手冊,串口中斷狀態分為:接收 full 中斷、接收溢出中斷、接收超時中斷 tout、發送 fifo 空中斷、流量量控制狀態中斷。我只對接收超時中斷進行了配置,因為這個足夠滿足需求,若考慮全面,可以適當增加。手冊中也有一個中斷處理函數的例程,參照這個修改。
上面代碼的注釋也寫的很清楚了。
3)修改mqtt_config.h
記得要修改CFG_HOLDER,隨便更改某一個十六進制數就行,否則出現修改的參數不生效的后果,我也是一步一步采坑過來的。
不過還有一個坑,我現在才說,目的就是為了經歷遇到問題,解決問題的過程。遇到問題之后自己解決,這樣可以學到更多的東西。修改完中斷處理函數之后,調試時,似乎根本就不會進入修改好的中斷處理函數,找了各種原因:是不是沒有配置好串口的相關寄存器啊,是不是mqttclient不能傳遞到另一個文件中使用啊,等等等。最后找到答案,ESP8266 NONOS_SDK-3.0 開發中官方例程 UART0串口進入不了中斷問題。因為工程構建得有問題,esp_mqtt_proj目錄中雖然有uart.h頭文件,但是根本不含有uart.c文件,我們所修改的不過是沒有引入到項目中的uart.c文件。所以我的解決方式是:
1)將driver_lib下的driver復制到esp_mqtt_proj項目文件夾內
2)在Makefile文件中加入相應的庫文件目錄。
把對應的二進制文件燒錄進esp8266
4. 調試效果
1)連接好ESP8266和串口調試器,插到電腦USB口上。
2)打開串口調試助手(安信可官網開發工具清單中下載)。
這樣表示mqtt服務端連接成功。
3)模擬一下微信小程序與ESP8266之間進行通信,首先在MQTTBox上添加mqtt客戶端用以模擬微信小程序端,配置如下:
在MQTTBox上發布消息
可以看到esp8266串口中打印出來了消息,如果esp8266接在STM32上,STM32只需要讀取串口數據就可以獲取到微信小程序發來的數據了、
esp8266轉發串口數據(AT+RST)
可以看到微信小程序訂閱的Topic1主題,接收到了消息。
這樣這個環節就OK了。
更新內容
問題:在最開始做這個項目的時候,有一個問題沒注意,后來調試之后,突然發現一個問題,當Esp8266和STM32同時上電之后,不會發送上線消息,然后微信小程序就不會檢測到STM32是否上線,進而無法控制STM32。這是因為在上電后,stm32和esp8266各自執行自己的代碼,沒有聯系,所以STM32初始化過程中發送在線信息時,ESP8266還沒有連接上服務器,然后向串口發送在線信息時,ESP8266不會轉發到主題上去。
解決方法:更改STM32程序,在STM32初始化時,向ESP8266串口發送詢問數據,詢問ESP8266是否連接上服務器。更新ESP8266固件,當串口接收到詢問數據后,在串口返回初始化完畢的狀態。
更改后的代碼貼在下面。
user_main.c
在mqtt.c里面mqtt_tcpclient_recv函數,當訂閱成功之后表示連接服務器成功,表示可以接收詢問數據了
case MQTT_MSG_TYPE_SUBACK:if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id){mqttState=1;os_delay_us(60000);uart_rx_intr_enable(UART0);}break;個人能力有限,有錯誤的地方歡迎指正,有問題也可以提,可以一起探討一下
總結
以上是生活随笔為你收集整理的物联网学习之旅:微信小程序控制STM32(二)--ESP8266连接mqtt服务端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 滚动到页面底部自动加载内容
- 下一篇: [转]你每天90%的注意力被浪费了