• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

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

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

    作者:一葉孤沙 時(shí)間:2020-06-28 來(lái)源:知乎 收藏

    前言:

    本文引用地址:http://www.czjhyjcfj.com/article/202006/414785.htm

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

    一、基礎(chǔ)知識(shí)

    1.交互流程簡(jiǎn)介

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

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

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

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

    (5)發(fā)送指令:AT+CWSAP="ESP01S_test","12345678",1,3,啟動(dòng)一個(gè)WIFI熱點(diǎn)

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

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

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

    2.程序框架簡(jiǎn)介

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

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

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

    本程序使用了函數(shù)指針,應(yīng)用層將事件處理函數(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í)器判斷一幀數(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 ) )                       //預(yù)留1個(gè)字節(jié)寫(xiě)結(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,這個(gè)標(biāo)志位再定時(shí)器中會(huì)用到,可以用來(lái)判斷接收一幀數(shù)據(jù)是否完成。

    一幀數(shù)據(jù)接收是否完成的判斷邏輯是:定時(shí)器會(huì)定期檢測(cè),如果FramStartFlag為1,說(shuō)明串口正在接收數(shù)據(jù),沒(méi)接收一個(gè)數(shù)據(jù),F(xiàn)ramLength加1,因此,當(dāng)進(jìn)入定時(shí)器中斷函數(shù),判斷FramStartFlag為1情況下FrameLength如果不再增加,說(shuō)明一幀數(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)映射到應(yīng)用層的void system_status_callback(int sock, int event)函數(shù)。

    3.事件處理

    事件處理的核心再while(1)中,根據(jù)系統(tǒng)當(dāng)前事件狀態(tài)做出響應(yīng),本節(jié)是檢測(cè)到事件為數(shù)據(jù)類型時(shí)候,將數(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;
    }

    三、運(yùn)行

    下載程序完畢后,重啟設(shè)備,ESP01S啟動(dòng)一個(gè)WIFI熱點(diǎn),并啟動(dòng)TCP Server,log如下:

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

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


    關(guān)閉網(wǎng)絡(luò)助手,應(yīng)用程序也可以檢測(cè)到,如下Log所示





    評(píng)論


    相關(guān)推薦

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

    關(guān)閉
    主站蜘蛛池模板: 广南县| 连云港市| 宁夏| 开阳县| 乌鲁木齐县| 铁力市| 腾冲县| 绥棱县| 南澳县| 麻阳| 敖汉旗| 宁武县| 襄汾县| 定安县| 洛川县| 射洪县| 海南省| 东阿县| 三河市| 岐山县| 万年县| 丰都县| 天气| 天门市| 吴堡县| 乌鲁木齐县| 蚌埠市| 沁阳市| 五常市| 青龙| 阿勒泰市| 城固县| 永新县| 平遥县| 汝州市| 双流县| 福州市| 巢湖市| 阜阳市| 大荔县| 广水市|