1. 程式人生 > >使用esp8266實現STM32聯網(最簡單USART方法)

使用esp8266實現STM32聯網(最簡單USART方法)

上一篇

esp8266怎麼配置
    esp8266和USB轉TTL連線
esp8266簡單介紹
esp8266連線路由器
esp8266通過路由器連線在同一區域網中的電腦,建立TCP連線
esp8266使用串列埠傳送資料到電腦上的網路除錯助手
esp8266使用串列埠通過區域網傳送到電腦上自己寫的Java程式
esp8266的透傳模式
esp8266使用透傳模式連線到電腦的網路除錯助手
esp8266使用透傳模式連線到電腦上的java程式

這一篇

esp8266與STM32連線,電腦通過STM32配置esp8266實現聯網傳送資料
具體流程如下圖

2=
esp8266怎麼和STM32連線(引腳連線)?

STM32CubeMx配置的usart2使用的PA2和PA3要與esp8266的TX和RX對應,但是得反過來接,要麼根本發不出去,看來esp8266又印反了
3V3和EN得接到同一個3V上才可以,要不收到的老是error

STM32使用USART和電腦相互傳輸資料?

將STM32產生的資料傳送到電腦的串列埠除錯助手
    第一種方式:
        使用UASRT傳輸只需要重新定義fputc()函式,直接使用Printf函式就可以將字串列印到電腦(即通過串列埠輸出到電腦)
    第二種方式:
        使用HAL庫中封裝好的UASART函式  HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)也可以實現串列埠輸出
電腦要傳送字串給STM32,那麼STM32怎麼收到資料,而且知道這個資料什麼意思呢?
    第一種方式(只能接收定長字串):
        HAL庫依舊有封裝好的函式HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout),但是使用這個函式有一個問題,這個函式的額第三個引數是收到的字串的大小,可是我都沒有傳送,怎麼提前把這個字串的大小寫入微控制器呢?
            其實問題是STM32如何接收不定長的字串?
        【STM32內部產生的資料或者從感測器中獲取的資料,STM32如果要傳送該資料可以直接使用sizeof獲得資料長度作為第三個引數,但是當人為的傳送給串列埠時,由於提前燒入的程式如果要使用HAL庫的USART接收函式的話,需要確定一個字串長度,那麼這個程式就只能接收指定長度的字串了,那要如何實現不定長也能接收呢?】
    第二種方式:
        DMA+接收結束判斷。這接收結束判斷可以是位元組的timeout,也可以是USART_IT_IDLE線路空閒的標誌等。這種方式對於需要整幀接收,且通訊速度較快或需要佔用cpu較少的情況
        【詳細的處理方式可見串列埠USART 收發資料處理方式總結--DMA+USART+USART_Idle_Interrupt】

那麼如何配置呢?

        既然是DMA和空閒接收中斷就需要設定DMA和UASRT的中斷(即在中斷處理函式中需要有DMA1 channel5 global interrupt和USART1 global interrupt)

        如果要使用printf輸出到串列埠的話,就需要重定義fputc函式(定義在usart.c中)

        如果要用線路空閒來觸發中斷來結束接收的話,需要有判斷線路是否空閒的函式,這個函式最好還需要在結束接收時將收到的資料儲存到自己定義的變數中

那麼如何實現不定長接收呢,不還是得知道接受的字串的長度嗎?

    是需要知道,這裡使用一個結構體來儲存字串和字串的長度以及一個標記(用來表示一次接收完成,如果不放在結構體裡面,使用全域性變數的話會比較麻煩)
    具體的方法是這樣的:在一開始接收的時候,將收到的字串儲存在結構體中的字串陣列中,而函式要求的大小這個引數設定為比較大的數字(可以是一次接收資料長度的最大值,這裡是1024),在判斷線路是否空閒的函式中,當線路空閒時(即一次接收完成時),將收到的字串的長度儲存到這個結構體中的字串長度變數中,這樣,當需要將收到的字串再次發出時,就可以使用已知的長度進行傳送了,由此實現了不定長接收。
    【其原理其實是用一個大空間去接收(看來接收空間夠大就行,不需要定長接收),在接收完成時計算收到的資料長度儲存起來(和收到的資料要一一對應,這也是使用結構體的好處),當需要再次傳送出去時,就知道這個字串的長度了,就可以定長髮送了】

    結構體
        #define RX_LEN 1024  

        typedef struct  
        {  
        uint8_t  RX_flag:1;        //IDLE receive flag
        uint16_t RX_Size;          //receive length
        uint8_t  RX_pData[RX_LEN]; //DMA receive buffer
        }USART_RECEIVETYPE; 

        extern USART_RECEIVETYPE UsartType;

下面是程式的流程

    首先在main函式中使用HAL_UART_Receive_DMA(&huart1, UsartType.RX_pData, RX_LEN); 開始接收,接收的資料放到結構體中,長度為最大值
    然後開啟中斷,__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);這個函式進行中斷使能,

    具體介紹:
    /** @brief  Enable the specified UART interrupt.
    * @param  __HANDLE__: specifies the UART Handle.
    *         UART Handle selects the USARTx or UARTy peripheral 
    *         (USART,UART availability and x,y values depending on device).
    * @param  __INTERRUPT__: specifies the UART interrupt source to enable.
    *          This parameter can be one of the following values:
    *            @arg UART_IT_CTS:  CTS change interrupt
    *            @arg UART_IT_LBD:  LIN Break detection interrupt
    *            @arg UART_IT_TXE:  Transmit Data Register empty interrupt
    *            @arg UART_IT_TC:   Transmission complete interrupt
    *            @arg UART_IT_RXNE: Receive Data register not empty interrupt
    *            @arg UART_IT_IDLE: Idle line detection interrupt
    *            @arg UART_IT_PE:   Parity Error interrupt
    *            @arg UART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)
        * @retval None
        * */
            #define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__)
    之後是否需要延時防止接收不到或者防止其他錯誤的發生不是很清楚。

    在stm32f1xx_it.c的DMA和USART的中斷函式中並沒有需要重寫的回撥函式

    在usart.c中實現處理空閒的函式新增到USART的中斷函式中,那麼當線路產生空閒時,就會觸發一箇中斷,這個空閒處理的函式,就會開始工作,先清空空閒標誌以允許繼續接收,然後使用HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)停止此次接收,接著獲得此次接收到的字串的長度(這裡比較深入,有暫存器的問題,不大理解),然後又呼叫了HAL_UART_Receive_DMA,這個應該和取得的長度是同一個結構體,那麼之前的HAL_UART_Receive_DMA又是再幹什麼呢?(或許是為了解決第一次的傳輸問題,學的不夠深入,還需要學的再深入)
    最後就可以使用獲得的長度和字串將收到的字串傳送出去了,這樣就實現了不定長接收。

【問題】在結構體中定義的是一個uint8_t型別的陣列,那麼可以按字串輸出嗎?

        可以,
        HAL_UART_Transmit(&huart1, UsartType.RX_pData, UsartType.RX_Size, 0xFFFF);
        printf("\n%s\n",UsartType.RX_pData);
        上面兩句一樣的效果
    具體程式碼:
        在usart.c中新增
            /* USER CODE BEGIN 1 */
            /**
              * @brief  Retargets the C library printf function to the USART.
              */
            int fputc(int ch,FILE *f)
            {
                HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
                return ch;
            }

            /**
              * @brief  This function handles USART1 IDLE interrupt.
              */
            void UsartReceive_IDLE(UART_HandleTypeDef *huart)  
            {  
                uint32_t temp;  

                if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))  
                {   
                    __HAL_UART_CLEAR_IDLEFLAG(&huart1);  
                    HAL_UART_DMAStop(&huart1);  
                    temp = huart1.hdmarx->Instance->CNDTR;  
                    UsartType.RX_Size =  RX_LEN - temp;   
                    UsartType.RX_flag=1;  
                    HAL_UART_Receive_DMA(&huart1,UsartType.RX_pData,RX_LEN);  
                }  
            }  
            /* USER CODE END 1 */
    在usart.c中例項化結構體
            /* USER CODE BEGIN 0 */
            USART_RECEIVETYPE UsartType; 
            /* USER CODE END 0 */

    在usart.h中定義結構體
            /* USER CODE BEGIN Private defines */
            #define RX_LEN 1024  

            typedef struct  
            {  
            uint8_t  RX_flag:1;        //IDLE receive flag
            uint16_t RX_Size;          //receive length
            uint8_t  RX_pData[RX_LEN]; //DMA receive buffer
            }USART_RECEIVETYPE;  

            extern USART_RECEIVETYPE UsartType; 
            /* USER CODE END Private defines */
    在stm32f1xx_it.c的中斷函式中新增
            void USART1_IRQHandler(void)
            {
              /* USER CODE BEGIN USART1_IRQn 0 */
                UsartReceive_IDLE(&huart1);  
              /* USER CODE END USART1_IRQn 0 */
              HAL_UART_IRQHandler(&huart1);
              /* USER CODE BEGIN USART1_IRQn 1 */

              /* USER CODE END USART1_IRQn 1 */
            }
    在main.c中main函式中基本的初始化函式後新增
              /* USER CODE BEGIN 2 */
                HAL_UART_Receive_DMA(&huart1, UsartType.RX_pData, RX_LEN);  
                __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 
                HAL_Delay(1000);
              /* USER CODE END 2 */

STM32如何給esp8266傳送AT指令?

途徑就為通過串列埠
那麼怎麼使用串列埠,
    是直接使用HAL庫封裝的相關函式
    還是需要一些驅動程式碼
電腦通過串列埠與STM32交流,STM32通過串列埠與esp8266交流
    既然上面實現了電腦與STM32使用USART相互傳輸資料,即STM32可以接收電腦發來的不定長資料,那麼STM32也能接收esp8266返回的不定長資料(向esp8266傳送不同的指令,返回訊息不一樣,長度也不一樣)

對於接收esp8266返回的資訊也使用DMA加空閒中斷的方式,那麼向esp8266傳送資料要怎麼做呢?

        上面的程式碼已經可以接收來自電腦的不定長訊息,然後再發給電腦,那麼將這個訊息直接傳送給esp8266就可以了,兩個不同的串列埠有不同的例項,只需要指定好串列埠就可以向這個串列埠傳送資料了。【突然覺得自己寫的好亂,沒有條理,得改】
    其實具體的程式碼就是在什麼那個處理STM2與電腦使用USART通訊的程式碼上再增加一個STM與esp8266的USART交流流程就可以了,需要注意區分不同的串列埠,兩個流程的交匯點在main函式中,當STM32收到電腦發來的不定長資訊後,通過空閒中斷處理函式獲得長度,將該訊息直接使用串列埠傳送到連線esp8266的串列埠即可,如果STM32收到來自esp8266串列埠的訊息,一樣使用DMA加空閒中斷的方式獲得來自esp8266的不定長返回資訊,在這裡也是一樣通過這個串列埠的空閒中斷處理函式獲得返回資訊的長度,將這個返回資訊傳送給與電腦相連的串列埠就可以了,這樣就完成了通過STM32配置esp8266的整個流程。

其意義是什麼呢?

    這樣STM32本身就可以使用串列埠將獲取的感測器資訊通過esp8266傳送到指定伺服器,實現了STM32的聯網,一樣也實現了通過網路向STM32傳送指令控制感測器的功能。

相關推薦

使用esp8266實現STM32聯網簡單USART方法

上一篇 esp8266怎麼配置 esp8266和USB轉TTL連線 esp8266簡單介紹 esp8266連線路由器 esp8266通過路由器連線在同一區域網中的電腦,建立TCP連線 esp8266使用串列埠傳送資料到電腦上的網路除錯助手 esp826

esp8266實現STM32聯網簡單USART方法

上一篇 esp8266怎麼配置 esp8266和USB轉TTL連線 esp8266簡單介紹 esp8266連線路由器 esp8266通過路由器連線在同一區域網中的電腦,建立TCP連線 esp8266使用串列埠傳送資料到電腦上的網路除錯助手 esp8266使用串列

Django實現任意檔案上傳簡單方法

利用Django實現檔案上傳並且儲存到指定路徑下,其實並不困難,完全不需要用到django的forms,也不需要django的models,就可以實現,下面開始實現。 第一步:在模板檔案中,建立一個form表單,需要特別注意的是,在有檔案上傳的form表單中,method屬

Ubuntu14.04下安裝 boost boost_1.54 簡單方法

urn 分享 ubun 命令 寫入 return test 簡單的 logs 直接執行命令: sudo apt-get install libboost-dev 測試: 創建一個 boost_test.cpp 文件,寫入 #include <boost/lexi

Linux簡單的版本下安裝MySQL -筆者遇到一系列坑

首先先上傳安裝包:筆者使用的是rpm按章包: https://pan.baidu.com/s/171UVMHmPBQX6ObcoXeb2BA 我之前到處這這個安裝包,在官網上,我都沒找到這個rpm的安裝包。 MySQL的官網下載: https://dev.mysql.com/downlo

MAC OSX 新增環境變數簡單的方式

echo 'export PATH="/Users/aa/PostgreSQL/pg95/bin"' >> ~/.bash_profil 直接在命令列裡面執行以上命令即可,就是這麼簡單。 這裡是把 export PATH=" " 這行新增進了 ~/.bas

PHP實現MVC開發得簡單方法——單點入口

  很早前就想寫一些關於PHP實現MVC的新的體會。今天就開始詳細的寫寫我對MVC的一些理解,以及我在開發過程中實現自己的一個框架的一個流程。其中或許說的不正確,還望指正!    網站關於MVC的教材很多了,我這裡不具體說了,不明白的,推薦自己上百度搜索下“MVC",相信

python資料結構——連結串列簡單的解釋

對於連結串列,當初學C的時候就沒有理解的很清楚,現在又重新遇到,要把這個弄明白。 資料結構是電腦科學必須掌握的一門學問,很多的教材都是用C語言實現連結串列,因為C有指標,可以很方便的控制記憶體,很方便就實現連結串列,其他的語言,則沒那麼方便,有很多都是用模擬連結串列,因為p

一般二叉樹求最近公共祖先簡單的程式碼

當遍歷到一個root點的時候, 1.判斷root是不是null如果root為null,那麼就無所謂祖先節點,直接返回null就好了 2.如果root的左子樹存在p,右子樹存在q,那麼root肯定就是最近祖先 3.如果pq都在root的左子樹,那麼就需要遞迴

不同版本Notification的顯示問題簡單方法是把目標版本更改為4.4

目前在Android中通知的使用還是很常見的,為了做版本相容,常用相容包NotificationCompat.Builder和 Notification.Builder。 NotificationCompat.Builder位於v4擴充套件包內(version 4 Support Library)Notif

ubuntu下安裝man中文包我知道的簡單方法

當我們在ubuntu下使用命令,常常需要用到man命令來幫助檢視命令引數的意義。但是我們的英文水平不一,因此好多英文解釋根本看不懂。比如用該命令檢視 vi 的幫助,純英文很難懂:其實ubuntu有man的中文包,只需幾行命令安裝配置即可顯示中文幫助。命令如下:123apt-g

使脫排油煙機能夠聽懂你的話超級簡單方法

軟件設置 9.png p s 自動 自己 手機 簡單 現在 問題 由於樓房的設計問題,使用的公共煙道,在每天午飯晚飯時間(周一到周五,上班時間),發生油煙倒灌的情況,真是苦不堪言,修了好幾次都沒有修好,怎麽辦? 思路: 1、周一周五工作時間,中晚飯時段,自動開啟脫排油煙機。

小二乘法小平方法(generalized least squares)

       許多工程問題,常常需要根據兩個變數的幾組實驗數值:實驗資料,來找出這個兩個變數的函式關係的近似表示式。通常把這樣得到的函式的近似表示式叫做經驗公式。經驗公式建立以後,就可以把生產或實驗中所積累的某些經驗,提高到理論上加以分析。下面我們通過舉例介紹常用的一種建立

matlab 更改可用記憶體快速有效方法

一直搜尋如何調大或者減小matlab的可用記憶體,找了很多方法,試驗了很多次。覺得下面的這種方式是最簡單快捷的: 首先先檢視一下matlab的記憶體情況,在matlab命令列輸入memory即可。 1、查詢matlab根路徑.在matlab命令列中敲入:ma

visual studio 2015引入開源控件DockPanel(簡單方法

net 進入 子窗口 tools projects win doc ip控件 control 一、DockPanel簡介 DockPanel是一個開源控件,能夠實現子窗口的浮動,在官方給的demo有演示,在vs2017微軟已經集成進入常用控件中。我主要使用的是多窗

Atitit 單點登入實現幾種模式架構圖 目錄 1. 因此要點也就以下兩個:儲存信任驗證信任 1 1.1. 共享cookie 簡單 1 1.2. 通過 url帶token引數跳轉 1 1.3.

Atitit 單點登入實現幾種模式架構圖   目錄 1. 因此要點也就以下兩個:儲存信任驗證信任 1 1.1. 共享cookie (最簡單 1 1.2. 通過 url帶token引數跳轉 1 1.3. 頁面重定向(複雜 1 1.3.1. 父子應用重定向 2

footer固定在網頁底部且居中,超過一屏自動撐開簡單的CSS實現

html {height: 100%; } body {margin: 0;padding: 0;min-height: 100%;position: relative; } #footer{position: absolute;left: 0;right: 0;botto

eclipse下的tomcat配置https簡單得配置https

如果 希望 alias lib connector connect eclipse cnblogs itl 近期公司列出一大堆的東西,其中包括https,啥也不想說,你們是無法理解的苦逼的我的 關於https這些通道可以去百度Google其原理,不廢話,自動生成秘鑰,需要使

js實現星級評分效果短代碼

實現 動態顯示 turn 單行 ctype ref sts near 分系統 1. 前言 此方案受到JS單行寫一個評級組件啟發,自己寫了一個簡單Demo。 功能有正常滑動,動態顯示實心星星個數;當點擊確認,則保持當前的實心星星個數;再移動時為點擊,則離開後還是保持之前的狀態

【轉】使用git將項目上傳到github簡單方法

名稱 posit gitignore nor this strong 共享 window mas 原文地址:http://www.cnblogs.com/cxk1995/p/5800196.html 首先你需要一個github賬號,所有還沒有的話先去註冊吧! https:/