日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > RISC-V單片機快速入門05-玩轉(zhuǎn)ESP8266 WIFI模塊②

          RISC-V單片機快速入門05-玩轉(zhuǎn)ESP8266 WIFI模塊②

          作者:一葉孤沙 時間:2020-06-28 來源:知乎 收藏

          前言:

          本文引用地址:http://yuyingmama.com.cn/article/202006/414785.htm

          上一節(jié),我們使用發(fā)送AT指令操作ESP-01S,本節(jié),使用代替?zhèn)髋脊ぞ咄瓿珊?a class="contentlabel" href="http://yuyingmama.com.cn/news/listbylabel/label/ESP-01S模塊">ESP-01S模塊的交互過程。

          一、基礎知識

          1.交互流程簡介

          (1)設備上電,先控制8266的復位引腳為低電平,讓模塊復位

          (2)發(fā)送指令:ATE0,取消回顯

          (3)發(fā)送指令:AT+CWMODE=2,設置ESP01S為AP模式

          (4)發(fā)送指令:AT+CIPMUX=1,設置多路連接,AP模式最多支持5個設備連接

          (5)發(fā)送指令:AT+CWSAP="ESP01S_test","12345678",1,3,啟動一個WIFI熱點

          (6)發(fā)送指令:AT+CIPSERVER=1,8089,啟動TCP Server

          (7)發(fā)送指令:AT+CIPSERVER=1,8089,啟動TCP Server

          (8)大循環(huán)中檢測是否收到ESP01S數(shù)據(jù),收到數(shù)據(jù)后立刻返回。

          2.程序框架簡介

          程序主要包括如下4個功能模塊:ESP01S初始化、串口處理、Event回調(diào)函數(shù)、事件處理;串口處理模塊包括串口接收和定時器判斷一幀數(shù)據(jù)是否接收完成功能,Event回調(diào)函數(shù)主要用來通知應用層系統(tǒng)的狀態(tài),方便應用層做出相應,比如設備檢測到其他TCP Client客戶端接入模塊,可以控制LED狀態(tài),事件處理模塊主要包含應用程序大循環(huán),大循環(huán)中檢測系統(tǒng)事件狀態(tài),根據(jù)事件狀態(tài)再大循環(huán)中做出響應。

          二、系統(tǒng)功能模塊詳述

          1.Event回調(diào)函數(shù)

          本程序使用了函數(shù)指針,應用層將事件處理函數(shù)傳到hal_common.c中int hal_sys_contex_init(sys_status_fun fun, void *user_data)函數(shù)

          void system_status_callback(int sock, int event)
          {
              system_context->sock_id = sock;
              system_context->event = event;
           switch (event)
              {
           case STA_CONNECTED:
                  rt_kprintf("Sock %d connected!rn", sock);
           break;
           case STA_CLOSED:
                  rt_kprintf("Sock %d closed!rn", sock);
           break;
           case STA_DATA_ARRIVED:
                  rt_kprintf("Sock %d data arrived!rn", sock);
           break;
           default:
           break;
              }
          }
          
          
          typedef enum {
              STA_CONNECTED,
              STA_CLOSED,
              STA_DATA_ARRIVED, // clients send data to 
              STA_EVENT_MAX,
          }sys_event_e;
          
          
          typedef void (*sys_status_fun)(int sock, int event);
          
          
          typedef struct sys_ctx{
           int sock_id;
              sys_event_e event;
           char data_buf[SYS_CTX_UART_RECV_SIZE];
              sys_status_fun sys_status_cb;
           void *user_data;
          }sys_ctx_t;
          
          
          int hal_sys_contex_init(sys_status_fun fun, void *user_data)
          {
              sys_contex.sys_status_cb = fun;
              sys_contex.user_data = user_data;
           return 0;
          }
          
          int main(void)
          {
              hal_sys_contex_init(system_status_callback, RT_NULL);
           
           while(1)
              {
           
              }
          }

          2.串口處理

          串口處理模塊包括串口接收和定時器判斷一幀數(shù)據(jù)是否接收完成功能,串口接收函數(shù)代碼如下:

          #define RX_BUF_MAX_LEN     1024         //最大接收緩存字節(jié)數(shù)
          
          
          struct STRUCT_USART_Fram_S             //串口數(shù)據(jù)幀的處理結(jié)構(gòu)體
          {
           char  Data_RX_BUF [ RX_BUF_MAX_LEN ];
           uint16_t FramLength;
           struct {
           uint8_t FramStartFlag;
           uint8_t FramFinishFlag;
              } InfBit;
          } ;
          
          
          struct STRUCT_USART_Fram_S Esp8266_Frame_Record;
          
          
          void USART2_IRQHandler()
          {
           uint8_t ch = -1;
           if(RESET != usart_interrupt_flag_get(EVAL_COM2, USART_INT_FLAG_RBNE))
              {
                  ch =  usart_data_receive(EVAL_COM2);
          //      if ( Esp8266_Frame_Record.FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //預留1個字節(jié)寫結(jié)束符
          //      {
                      Esp8266_Frame_Record .Data_RX_BUF [ Esp8266_Frame_Record.FramLength ]  = ch;
          //      }
                  Esp8266_Frame_Record.FramLength ++;
           if (Esp8266_Frame_Record.FramLength >= 1024)
                  {
                      Esp8266_Frame_Record.FramLength = 0;
                  }
                  cnt = Esp8266_Frame_Record.FramLength;
          //      rt_kprintf(".......uart recv : %c, count is %drn", ch, cnt);
                  Esp8266_Frame_Record.InfBit.FramStartFlag = 1;
              }
          }

          中斷處理函數(shù)中,將接收的數(shù)據(jù)放到Esp8266_Frame_Record .Data_RX_BUF中,然后將

          Esp8266_Frame_Record.InfBit.FramStartFlag置1,這個標志位再定時器中會用到,可以用來判斷接收一幀數(shù)據(jù)是否完成。

          一幀數(shù)據(jù)接收是否完成的判斷邏輯是:定時器會定期檢測,如果FramStartFlag為1,說明串口正在接收數(shù)據(jù),沒接收一個數(shù)據(jù),F(xiàn)ramLength加1,因此,當進入定時器中斷函數(shù),判斷FramStartFlag為1情況下FrameLength如果不再增加,說明一幀數(shù)據(jù)接收完成。

          static void timeout1(void *parameter)
          {
           int sock_id = -1;
              char buff[128] = { 0x00 };
           int len = 0;
              sys_event_e event = STA_EVENT_MAX;
           
          //  rt_kprintf("timer's cnt is %d, FrameLength is %drn", cnt, Esp8266_Frame_Record.FramLength);
           if (1 == Esp8266_Frame_Record.InfBit.FramStartFlag)
              {
           if (cnt == Esp8266_Frame_Record.FramLength && cnt != 0)
                  {
                      cnt = 0;
                      Esp8266_Frame_Record .Data_RX_BUF [ Esp8266_Frame_Record.FramLength ]  = 0x00;
                      rt_kprintf("timer --------> data %srn", Esp8266_Frame_Record.Data_RX_BUF);
           if (rt_strstr(Esp8266_Frame_Record.Data_RX_BUF, "CONNECT"))
                      {
                          sscanf(Esp8266_Frame_Record.Data_RX_BUF, "%d,%s", &sock_id, buff);
                          event = STA_CONNECTED;
                      }else if (rt_strstr(Esp8266_Frame_Record.Data_RX_BUF, "CLOSED"))
                      {
                          sscanf(Esp8266_Frame_Record.Data_RX_BUF, "%d,%s", &sock_id, buff);
                          event = STA_CLOSED;
                      }else if (rt_strstr(Esp8266_Frame_Record.Data_RX_BUF, "+IPD"))
                      {
                          rt_memset(hal_sys_contex_get()->data_buf, 0x00, SYS_CTX_UART_RECV_SIZE);
                          sscanf(Esp8266_Frame_Record.Data_RX_BUF, "%*[^+]+IPD,%d,%d:%[^r]", &sock_id, &len, hal_sys_contex_get()->data_buf);
                          event = STA_DATA_ARRIVED;
                          rt_kprintf("parsed +IPD :%srn", hal_sys_contex_get()->data_buf);
                      }
                      // call sys_status_cb
           if (hal_sys_contex_get()->sys_status_cb)
                      {
                          hal_sys_contex_get()->sys_status_cb(sock_id, event);
                      }
           
                      Esp8266_Frame_Record.InfBit.FramFinishFlag = 1;
                      Esp8266_Frame_Record.InfBit.FramStartFlag = 0;
                  }else
                  {
                      cnt = Esp8266_Frame_Record.FramLength;
                  }
              }else
              {
                  cnt = 0;
                  Esp8266_Frame_Record.FramLength = 0;
              }
          }

          注意:事件處理本質(zhì)上是在此調(diào)用hal_sys_contex_get()->sys_status_cb(sock_id, event)映射到應用層的void system_status_callback(int sock, int event)函數(shù)。

          3.事件處理

          事件處理的核心再while(1)中,根據(jù)系統(tǒng)當前事件狀態(tài)做出響應,本節(jié)是檢測到事件為數(shù)據(jù)類型時候,將數(shù)據(jù)原路返回。

          int main(void)
          {
           /* enable the LED clock */
              rcu_periph_clock_enable(RCU_GPIOA);
           /* configure LED GPIO port */
              gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
              gpio_bit_reset(GPIOA, GPIO_PIN_1);
           // create iwdt_thread
              dynamic_thread = rt_thread_create("led_thread", led_process_thread_entry,
                                                  RT_NULL, 512, 2, 10);
              rt_thread_startup(dynamic_thread);
           // init sys_ctx
              hal_sys_contex_init(system_status_callback, RT_NULL);
              system_context = hal_sys_contex_get();
              hal_timer_init();
              ESP8266_Init();
              rt_thread_mdelay(1000);
              ESP8266_Ate0();
              tcp_server_init();
              tcp_server_start();
           
           while(1)
              {
           if (STA_DATA_ARRIVED == system_context->event)
                  {
           // send back
                      ESP8266_SendString ( DISABLE, system_context->data_buf, rt_strlen(system_context->data_buf), system_context->sock_id );
                  }
                  rt_thread_mdelay(10);
              }
           return 0;
          }

          三、運行

          下載程序完畢后,重啟設備,ESP01S啟動一個WIFI熱點,并啟動TCP Server,log如下:

          電腦連接熱點,使用網(wǎng)絡助手連接192.168.4.1:8089

          網(wǎng)絡助手發(fā)送數(shù)據(jù)給ESP01S


          關閉網(wǎng)絡助手,應用程序也可以檢測到,如下Log所示





          評論


          相關推薦

          技術(shù)專區(qū)

          關閉