【面试01】WIFI协议

一、简介

      这里对wifi的802.11协议中比较常见的知识做一个基本的总结和整理以及对ESP8266的使用,本篇文章适合新手学习,以及应对面试需要。 

        WiFi协议标准包括802.11a(第一代)、802.11n(第四代,同时运行在2.4Ghz和5Ghz双频段),802.11ac(第五代),而只有采用802.11ac协议的WiFi才是真正5G WiFi),第六代技术标准也就是我们俗称的wifi6,用的是802.11ax协议。

二、WIFI基本知识

        1.常见术语
(1)LAN:即局域网,是路由和主机组成的内部局域网,一般为有线网络。

(2)WAN:即广域网,是外部一个更大的局域网。

(3)WLAN(Wireless LAN,即无线局域网):前面我们说过LAN是局域网,其实大多数指的是有线网络中的局域网,无线网络中的局域网,一般用WLAN。

(4)AP:全称 Wireless Access Point, 即无线AP,用来连接 STA 和 有线网络的网络设备。类似于手机热点。

(5)Station(STA):即工作站,是指配有无线网卡的无线终端,比如:手机、电脑等。

(6)Assosiate:连接。如果一个Station想要加入到无线网络中,需要和这个无线网络中的AP关联(即Assosiate)。

(7)SSID:用来标识一个无线网络,后面会详细介绍,我们这里只需了解,每个无线网络都有它自己的SSID。

(8)BSSID:用来标识一个BSS,其格式和MAC地址一样,是48位的地址格式。一般来说,它就是所处的无线接入点的MAC地址。某种程度来说,它的作用和SSID类似,但是SSID是网络的名字,是给人看的,BSSID是给机器看的,BSSID类似MAC地址。
        2. Wi-Fi安全协议 

         Wi-Fi安全协议扮演着至关重要的角色,它们是网络世界的守护者,保护着我们的隐私和数据免受未经授权的访问和窃听。WEP、WPA、WPA2以及最新推出的WPA3。

        (1)WEP:

        WEP最早于1997年推出,是为了保护无线网络上的数据通信而设计的。当时,Wi-Fi技术还处于起步阶段,人们开始意识到需要一种安全协议来防止未经授权的访问和窃听。WEP被认为是一个里程碑,因为它是第一个为Wi-Fi网络提供安全保护的标准。WEP的工作原理是利用加密算法对无线网络传输的数据进行加密。它使用64位和128位的密钥来加密数据,并通过这些密钥来验证和解密数据包。WEP采用静态密钥,这意味着同一网络上的所有设备都使用相同的密钥进行通信。虽然这种方法可以确保消息内容对未经授权的用户来说是隐藏的,但它也正是WEP安全性的一个致命弱点。

        (2)WPA:

        WPA的发布是为了解决WEP存在的严重安全漏洞。WEP曾经是Wi-Fi网络最早采用的加密标准之一,但它的静态密钥和易受攻击的加密算法使得网络数据容易被窃取和篡改。WPA的问世填补了WEP的安全漏洞,并为无线网络提供了更可靠的保护。

        (3)WPA2:

        WPA2是一种无线安全协议,是WPA(Wi-Fi Protected Access)协议的升级版本。它于2004年推出,旨在提供更加安全的无线网络连接。WPA2采用了先进的加密标准和身份验证机制,以确保Wi-Fi网络的安全性和保密性。WPA2通过加密和身份验证机制来保护Wi-Fi网络的安全。当设备连接到受保护的Wi-Fi网络时,首先进行身份验证,确保只有授权用户才能访问网络。随后,数据通过AES加密算法进行加密,保证传输过程中的数据安全性。同时,WPA2还使用密码块链消息验证代码协议(CCMP)的计数器模式来验证数据的完整性,防止数据被篡改或损坏。

        (4)WPA3

        WPA3是Wi-Fi联盟于2018年发布的最新一代Wi-Fi安全协议。作为WPA2的后继者,WPA3旨在提供更强大的安全保护,解决WPA2中存在的一些安全漏洞和攻击手法,为个人和企业用户提供更安全的Wi-Fi连接。

        WEP、WPA、WPA2以及WPA3 四者总结关系。

三、ESP8266简介

        本次使用的是正点原子的串口WIFI模块。

        ESP8266 是串口型 WIFI,速度比较低,不能用来传输图像或者视频这些大容量的数据,主要应用于数据量传输比较少的场合,比如温湿度信息,一些传感器的开关量等。

        1.三种模式说明

ATK-MW8266D 模块支持三种工作模式,分别为: STA、 AP、 STA+AP。

(1)STA 模式
        在此模式下, ATK-MW8266D 模块可连接其他设备提供的无线网络, 例如通过 WIFI 连接至路由器, 从而可以访问互联网,进而实现手机或电脑通过互联网实现对设备的远程控制。
(2)AP 模式
        AP 模式为默认的模式,在此模式下, ATK-MW8266D 模块将作为热点供其他设备连接,从而让手机或电脑直接与模块进行通讯,实现局域网的无线控制。
(3)STA+AP 模式
        该模式为 STA 模式与 AP 模式共存的一种模式, ATK-MW8266D 模块既能连接至其他设备提供的无线网络,又能作为热点,供其他设备连接,以实现广域网与局域网的无缝切换,方便操作使用。

        除了上述的三种工作模式外, ATK-MW8266D 模块在进行 UDP 连接或作为 TCP 客户端连接时,能够进入透传模式,进入透传模式后, ATK-MW8266D 将会原封不动地把从 TCP服务器或其他 UDP 终端接收到的消息,通过 UART 发送至与之连接的设备。 

         2.重要概念

        透传,即透明传输功能。Host 通过 uart 将数据发给 ESP8266,ESP8266 再通过无线网络将数据传出去;ESP8266 通过无线网络接收到的数据。ESP8266 只负责将数据传到目标地址,不对数据进行处理,发送方和接收方的数据内容、长度完全一致,传输过程就好像透明一样。

        TCP/UDP通信,可以在B站上面了解。

        3.常用指令集
ESP8266指令集:
	AT+RESTORE 恢复出厂设置
	AT+CIPCLOSE 关闭 TCP 连接、 UDP 传输或 SSL 连接

	AT+CWMODE=1
	AT+RST
	AT+CWJAP="guilin88","12345678"
	AT+CIPMUX=0 		开启单连接
	AT+CIPSTART="TCP","192.168.147.95",6688	建立 TCP 连接到 192.168.4.XXX:8086
	AT+CIPMODE=1 开启透传模式(仅单连接 Client 时支持)
	AT+CIPSEND 开始发送数据

四、代码编写

        1.atk_mw8266d.c
#include "atk_mw8266d.h"
#include "main.h"
#include <string.h>
#include <stdio.h>
#include <usart.h>

/**
 * @brief       ATK-MW8266D硬件初始化
 * @param       无
 * @retval      无
 */
static void atk_mw8266d_hw_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    ATK_MW8266D_RST_GPIO_CLK_ENABLE();
    
    gpio_init_struct.Pin = ATK_MW8266D_RST_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init_struct.Pull = GPIO_NOPULL;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(ATK_MW8266D_RST_GPIO_PORT, &gpio_init_struct);
}

/**
 * @brief       ATK-MW8266D硬件复位
 * @param       无
 * @retval      无
 */
void atk_mw8266d_hw_reset(void)
{
    ATK_MW8266D_RST(0);
    HAL_Delay(100);
    ATK_MW8266D_RST(1);
    HAL_Delay(500);
}

//自己写的发送指令函数
uint8_t atk_mw8266d_send_at_cmd(char *cmd, char *ack, uint32_t timeout)
{     
    atk_mw8266d_uart_printf("%s\r\n", cmd);
	return ATK_MW8266D_EOK;
}

/**
 * @brief       ATK-MW8266D初始化
 * @param       baudrate: ATK-MW8266D UART通讯波特率
 * @retval      ATK_MW8266D_EOK  : ATK-MW8266D初始化成功,函数执行成功
 *              ATK_MW8266D_ERROR: ATK-MW8266D初始化失败,函数执行失败
 */
uint8_t atk_mw8266d_init(uint32_t baudrate)
{
    atk_mw8266d_hw_init();                          /* ATK-MW8266D硬件初始化 */
    atk_mw8266d_hw_reset();                         /* ATK-MW8266D硬件复位 */
    atk_mw8266d_uart_init(baudrate);                /* ATK-MW8266D UART初始化 */
    //printf("开始AT测试指令...");
    if (atk_mw8266d_at_test() != ATK_MW8266D_EOK)   /* ATK-MW8266D AT指令测试 */
    {
        return ATK_MW8266D_ERROR;
    }
    
    return ATK_MW8266D_EOK;
}

/**
 * @brief       ATK-MW8266D恢复出厂设置
 * @param       无
 * @retval      ATK_MW8266D_EOK  : 恢复出场设置成功
 *              ATK_MW8266D_ERROR: 恢复出场设置失败
 */
uint8_t atk_mw8266d_restore(void)
{
    uint8_t ret;
    
    ret = atk_mw8266d_send_at_cmd("AT+RESTORE", "ready", 3000);
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D AT指令测试
 * @param       无
 * @retval      ATK_MW8266D_EOK  : AT指令测试成功
 *              ATK_MW8266D_ERROR: AT指令测试失败
 */
uint8_t atk_mw8266d_at_test(void)
{
    uint8_t ret;
    uint8_t i;
    
    for (i=0; i<2; i++)
    {
        ret = atk_mw8266d_send_at_cmd("AT", "OK", 500);
        if (ret == ATK_MW8266D_EOK)
        {
            return ATK_MW8266D_EOK;
        }
    }
    
    return ATK_MW8266D_ERROR;
}

/**
 * @brief       设置ATK-MW8266D工作模式
 * @param       mode: 1,Station模式
 *                    2,AP模式
 *                    3,AP+Station模式
 * @retval      ATK_MW8266D_EOK   : 工作模式设置成功
 *              ATK_MW8266D_ERROR : 工作模式设置失败
 *              ATK_MW8266D_EINVAL: mode参数错误,工作模式设置失败
 */
uint8_t atk_mw8266d_set_mode(uint8_t mode)
{
    uint8_t ret;
    
    switch (mode)
    {
        case 1:
        {
            ret = atk_mw8266d_send_at_cmd("AT+CWMODE=1", "OK", 500);    /* Station模式 */
            break;
        }
        case 2:
        {
            ret = atk_mw8266d_send_at_cmd("AT+CWMODE=2", "OK", 500);    /* AP模式 */
            break;
        }
        case 3:
        {
            ret = atk_mw8266d_send_at_cmd("AT+CWMODE=3", "OK", 500);    /* AP+Station模式 */
            break;
        }
        default:
        {
            return ATK_MW8266D_EINVAL;
        }
    }
    
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D软件复位
 * @param       无
 * @retval      ATK_MW8266D_EOK  : 软件复位成功
 *              ATK_MW8266D_ERROR: 软件复位失败
 */
uint8_t atk_mw8266d_sw_reset(void)
{
    uint8_t ret;
    
    ret = atk_mw8266d_send_at_cmd("AT+RST", "OK", 500);
    if (ret == ATK_MW8266D_EOK)
    {
        HAL_Delay(1000);
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D设置回显模式
 * @param       cfg: 0,关闭回显
 *                   1,打开回显
 * @retval      ATK_MW8266D_EOK  : 设置回显模式成功
 *              ATK_MW8266D_ERROR: 设置回显模式失败
 */
uint8_t atk_mw8266d_ate_config(uint8_t cfg)
{
    uint8_t ret;
    
    switch (cfg)
    {
        case 0:
        {
            ret = atk_mw8266d_send_at_cmd("ATE0", "OK", 500);   /* 关闭回显 */
            break;
        }
        case 1:
        {
            ret = atk_mw8266d_send_at_cmd("ATE1", "OK", 500);   /* 打开回显 */
            break;
        }
        default:
        {
            return ATK_MW8266D_EINVAL;
        }
    }
    
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D连接WIFI
 * @param       ssid: WIFI名称
 *              pwd : WIFI密码
 * @retval      ATK_MW8266D_EOK  : WIFI连接成功
 *              ATK_MW8266D_ERROR: WIFI连接失败
 */
uint8_t atk_mw8266d_join_ap(char *ssid, char *pwd)
{
    uint8_t ret;
    char cmd[64];
    
    sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, pwd);
    ret = atk_mw8266d_send_at_cmd(cmd, "WIFI GOT IP", 10000);
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D获取IP地址
 * @param       buf: IP地址,需要16字节内存空间
 * @retval      ATK_MW8266D_EOK  : 获取IP地址成功
 *              ATK_MW8266D_ERROR: 获取IP地址失败
 */
uint8_t atk_mw8266d_get_ip(char *buf)
{
    uint8_t ret;
    char *p_start;
    char *p_end;
    
    ret = atk_mw8266d_send_at_cmd("AT+CIFSR", "OK", 500);
    if (ret != ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_ERROR;
    }
    
    p_start = strstr((const char *)atk_mw8266d_uart_rx_get_frame(), "\"");
    p_end = strstr(p_start + 1, "\"");
    *p_end = '\0';
    sprintf(buf, "%s", p_start + 1);
    
    return ATK_MW8266D_EOK;
}

/**
 * @brief       ATK-MW8266D连接TCP服务器
 * @param       server_ip  : TCP服务器IP地址
 *              server_port: TCP服务器端口号
 * @retval      ATK_MW8266D_EOK  : 连接TCP服务器成功
 *              ATK_MW8266D_ERROR: 连接TCP服务器失败
 */
uint8_t atk_mw8266d_connect_tcp_server(char *server_ip, char *server_port)
{
    uint8_t ret;
    char cmd[64];
    
    sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s", server_ip, server_port);
    ret = atk_mw8266d_send_at_cmd(cmd, "CONNECT", 5000);
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D进入透传
 * @param       无
 * @retval      ATK_MW8266D_EOK  : 进入透传成功
 *              ATK_MW8266D_ERROR: 进入透传失败
 */
uint8_t atk_mw8266d_enter_unvarnished(void)
{
    uint8_t ret;
    
    ret  = atk_mw8266d_send_at_cmd("AT+CIPMODE=1", "OK", 500);
    ret += atk_mw8266d_send_at_cmd("AT+CIPSEND", ">", 500);
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D退出透传
 * @param       无
 * @retval      无
 */
void atk_mw8266d_exit_unvarnished(void)
{
    atk_mw8266d_uart_printf("+++");
}

/**
 * @brief       ATK-MW8266D连接原子云服务器
 * @param       id : 原子云设备编号
 *              pwd: 原子云设备密码
 * @retval      ATK_MW8266D_EOK  : 连接原子云服务器成功
 *              ATK_MW8266D_ERROR: 连接原子云服务器失败
 */
uint8_t atk_mw8266d_connect_atkcld(char *id, char *pwd)
{
    uint8_t ret;
    char cmd[64];
    
    sprintf(cmd, "AT+ATKCLDSTA=\"%s\",\"%s\"", id, pwd);
    ret = atk_mw8266d_send_at_cmd(cmd, "CLOUD CONNECTED", 10000);
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}

/**
 * @brief       ATK-MW8266D断开原子云服务器连接
 * @param       无
 * @retval      ATK_MW8266D_EOK  : 断开原子云服务器连接成功
 *              ATK_MW8266D_ERROR: 断开原子云服务器连接失败
 */
uint8_t atk_mw8266d_disconnect_atkcld(void)
{
    uint8_t ret;
    
    ret = atk_mw8266d_send_at_cmd("AT+ATKCLDCLS", "CLOUD DISCONNECT", 500);
    if (ret == ATK_MW8266D_EOK)
    {
        return ATK_MW8266D_EOK;
    }
    else
    {
        return ATK_MW8266D_ERROR;
    }
}
        2.atk_mw8266d_usart.c
#include "atk_mw8266d_usart.h"
#include "usart.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

static UART_HandleTypeDef g_uart_handle;                    /* ATK-MW8266D UART */
static struct
{
    uint8_t buf[ATK_MW8266D_UART_RX_BUF_SIZE];              /* 帧接收缓冲 */
    struct
    {
        uint16_t len    : 15;                               /* 帧接收长度,sta[14:0] */
        uint16_t finsh  : 1;                                /* 帧接收完成标志,sta[15] */
    } sta;                                                  /* 帧状态信息 */
} g_uart_rx_frame = {0};                                    /* ATK-MW8266D UART接收帧缓冲信息结构体 */
static uint8_t g_uart_tx_buf[ATK_MW8266D_UART_TX_BUF_SIZE]; /* ATK-MW8266D UART发送缓冲 */

/**
 * @brief       ATK-MW8266D UART printf
 * @param       fmt: 待打印的数据
 * @retval      无
 */
void atk_mw8266d_uart_printf(char *fmt, ...)
{
    va_list ap;
    uint16_t len;
    
    va_start(ap, fmt);
    vsprintf((char *)g_uart_tx_buf, fmt, ap);
    va_end(ap);
    
    len = strlen((const char *)g_uart_tx_buf);
    // HAL_UART_Transmit(&g_uart_handle, g_uart_tx_buf, len, HAL_MAX_DELAY);

    HAL_UART_Transmit_DMA(&huart1, (uint8_t *)g_uart_tx_buf, len);
	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)g_uart_tx_buf, len);
}

/**
 * @brief       ATK-MW8266D UART重新开始接收数据
 * @param       无
 * @retval      无
 */
void atk_mw8266d_uart_rx_restart(void)
{
    g_uart_rx_frame.sta.len     = 0;
    g_uart_rx_frame.sta.finsh   = 0;
}

/**
 * @brief       获取ATK-MW8266D UART接收到的一帧数据
 * @param       无
 * @retval      NULL: 未接收到一帧数据
 *              其他: 接收到的一帧数据
 */
uint8_t *atk_mw8266d_uart_rx_get_frame(void)
{
    if (g_uart_rx_frame.sta.finsh == 1)
    {
        g_uart_rx_frame.buf[g_uart_rx_frame.sta.len] = '\0';
        return g_uart_rx_frame.buf;
    }
    else
    {
        return NULL;
    }
}

/**
 * @brief       获取ATK-MW8266D UART接收到的一帧数据的长度
 * @param       无
 * @retval      0   : 未接收到一帧数据
 *              其他: 接收到的一帧数据的长度
 */
uint16_t atk_mw8266d_uart_rx_get_frame_len(void)
{
    if (g_uart_rx_frame.sta.finsh == 1)
    {
        return g_uart_rx_frame.sta.len;
    }
    else
    {
        return 0;
    }
}

/**
 * @brief       ATK-MW8266D UART初始化
 * @param       baudrate: UART通讯波特率
 * @retval      无
 */
void atk_mw8266d_uart_init(uint32_t baudrate)
{
    g_uart_handle.Instance          = ATK_MW8266D_UART_INTERFACE;   /* ATK-MW8266D UART */
    g_uart_handle.Init.BaudRate     = baudrate;                     /* 波特率 */
    g_uart_handle.Init.WordLength   = UART_WORDLENGTH_8B;           /* 数据位 */
    g_uart_handle.Init.StopBits     = UART_STOPBITS_1;              /* 停止位 */
    g_uart_handle.Init.Parity       = UART_PARITY_NONE;             /* 校验位 */
    g_uart_handle.Init.Mode         = UART_MODE_TX_RX;              /* 收发模式 */
    g_uart_handle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;          /* 无硬件流控 */
    g_uart_handle.Init.OverSampling = UART_OVERSAMPLING_16;         /* 过采样 */
    HAL_UART_Init(&g_uart_handle);                                  /* 使能ATK-MW8266D UART
                                                                     * HAL_UART_Init()会调用函数HAL_UART_MspInit()
                                                                     * 该函数定义在文件usart.c中
                                                                     */
}

/**
 * @brief       ATK-MW8266D UART中断回调函数
 * @param       无
 * @retval      无
 */
void ATK_MW8266D_UART_IRQHandler(void)
{
    uint8_t tmp;
    
    if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_ORE) != RESET)        /* UART接收过载错误中断 */
    {
        __HAL_UART_CLEAR_OREFLAG(&g_uart_handle);                           /* 清除接收过载错误中断标志 */
        (void)g_uart_handle.Instance->ISR;                                  /* I先读SR寄存器,再读RDR寄存器 */
        (void)g_uart_handle.Instance->RDR;
    }
    
    if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_RXNE) != RESET)       /* UART接收中断 */
    {
        HAL_UART_Receive(&g_uart_handle, &tmp, 1, HAL_MAX_DELAY);           /* UART接收数据 */
        
        if (g_uart_rx_frame.sta.len < (ATK_MW8266D_UART_RX_BUF_SIZE - 1))   /* 判断UART接收缓冲是否溢出
                                                                             * 留出一位给结束符'\0'
                                                                             */
        {
            g_uart_rx_frame.buf[g_uart_rx_frame.sta.len] = tmp;             /* 将接收到的数据写入缓冲 */
            g_uart_rx_frame.sta.len++;                                      /* 更新接收到的数据长度 */
        }
        else                                                                /* UART接收缓冲溢出 */
        {
            g_uart_rx_frame.sta.len = 0;                                    /* 覆盖之前收到的数据 */
            g_uart_rx_frame.buf[g_uart_rx_frame.sta.len] = tmp;             /* 将接收到的数据写入缓冲 */
            g_uart_rx_frame.sta.len++;                                      /* 更新接收到的数据长度 */
        }
    }
    
    if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_IDLE) != RESET)       /* UART总线空闲中断 */
    {
        g_uart_rx_frame.sta.finsh = 1;                                      /* 标记帧接收完成 */
        HAL_UART_Transmit_DMA(&huart1, g_uart_rx_frame.buf, sizeof(g_uart_rx_frame.buf));
        __HAL_UART_CLEAR_IDLEFLAG(&g_uart_handle);                          /* 清除UART总线空闲中断 */
    }
}
        3.功能编辑
#include "myTask_ATK8266D.h"
#include "atk_mw8266d.h"
#include "usart.h"
#include "main.h"
#include "stdio.h"
#include "string.h"

#define DEMO_WIFI_SSID          "guilin88"
#define DEMO_WIFI_PWD           "12345678"
#define DEMO_TCP_SERVER_IP      "192.168.1.3"
#define DEMO_TCP_SERVER_PORT    "8080"


// static uint8_t AT_RESTORE[] = "AT+RESTORE\r\n"; //恢复出厂设置
// static uint8_t AT[] = "AT\r\n";//检查指令
// static uint8_t AT_MODESTA[] = "AT+CWMODE=1\r\n";//设置为STA模式
// static uint8_t AT_RST[] = "AT+RST\r\n";//重启生效

//连接WIFI的名称和密码
static uint8_t AT_JAP[] = "AT+CWJAP=\"guilin88\",\"12345678\"\r\n";//连接WIFI名称和密码,

static uint8_t AT_MUX0[] = "AT+CIPMUX=0\r\n";//开启单链接
static uint8_t AT_START[] = "AT+CIPSTART=\"TCP\",\"192.168.147.95\",6688\r\n";//建立TCP连接
static uint8_t AT_CIPMODE1[] = "AT+CIPMODE=1\r\n";//开启透传模式命令
static uint8_t AT_SEND[] = "AT+CIPSEND\r\n";//开始传输命令

// static uint8_t AT_QUIT[] = "+++"; //退出透传

void myTask_ATK8266D(void)
{   
//	printf("正在进入STA模式下的透传...\r\n");
//	printf("发送的指令是:");
//	// 1.恢复出厂设置	
//	//printf("发送的指令是:");
//	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_RESTORE, sizeof(AT_RESTORE));
//	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_RESTORE, sizeof(AT_RESTORE));
//	HAL_Delay(2000);

//	// 2.检查指令
//	printf("发送的指令是:");
//	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT, sizeof(AT));	
//	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT, sizeof(AT));
//	HAL_Delay(2000);

//	// 3.设置为STA模式
//	printf("发送的指令是:");
//	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_MODESTA, sizeof(AT_MODESTA));	
//	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_MODESTA, sizeof(AT_MODESTA));
//	HAL_Delay(2000);
//	HAL_Delay(2000);

//	// 4.重启生效
//	printf("发送的指令是:");
//	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_RST, sizeof(AT_RST));
//	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_RST, sizeof(AT_RST));
//	
//	HAL_Delay(2000);
//	HAL_Delay(1000);
//	HAL_Delay(1000);

	// 5.连接WIFI的名称和密码
	printf("发送的指令是:");
	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_JAP, sizeof(AT_JAP));
	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_JAP, sizeof(AT_JAP));
	HAL_Delay(2000);
	HAL_Delay(2000);
	HAL_Delay(2000);
	HAL_Delay(2000);
	HAL_Delay(2000);

	// 6.开启单链接
	printf("发送的指令是:");
	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_MUX0, sizeof(AT_MUX0));
	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_MUX0, sizeof(AT_MUX0));
	HAL_Delay(1000);

	// 7.建立TCP连接
	printf("发送的指令是:");
	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_START, sizeof(AT_START));
	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_START, sizeof(AT_START));
	HAL_Delay(1000);
	HAL_Delay(1000);

	// 8.开启透传模式命令

		printf("发送的指令是:");
		HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_CIPMODE1, sizeof(AT_CIPMODE1));
		HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_CIPMODE1, sizeof(AT_CIPMODE1));
		HAL_Delay(1000);


	// 9.开始传输命令
	//while(strstr((const char *)ATCmdRxBuffer, "<") == NULL){
		printf("发送的指令是:");
		HAL_UART_Transmit_DMA(&huart3, (uint8_t *)AT_SEND, sizeof(AT_SEND));
		HAL_UART_Transmit_DMA(&huart1, (uint8_t *)AT_SEND, sizeof(AT_SEND));
		HAL_Delay(1000);
}

 参考正点原子,附源代码。

  • 26
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
网络协议是Java面试中常被问到的热点话题,以下是一些常见的网络协议相关面试问题及其答案: 1. TCP和UDP的区别是什么? 答:TCP(传输控制协议)是一种面向连接、可靠的传输协议,提供数据的完整性和可靠性,数据传输时需要先建立连接,数据传输完毕后需要断开连接。UDP(用户数据报协议)是一种无连接、不可靠的传输协议,不保证数据传输的可靠性和完整性,数据传输时不需要建立连接和断开连接。 2. OSI七层模型和TCP/IP五层模型有什么区别? 答:OSI七层模型和TCP/IP五层模型都是用于描述计算机网络协议的模型,不同之处在于OSI模型将网络协议分为了七层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型将网络协议分为了五层,分别是物理层、数据链路层、网络层、传输层和应用层。TCP/IP模型中的传输层同时承担了OSI模型中的传输层和会话层的功能,表示层的功能则由应用层完成。 3. HTTP和HTTPS的区别是什么? 答:HTTP(超文本传输协议)是一种明文传输的协议,数据在传输过程中容易被窃听和篡改,不够安全。HTTPS(安全超文本传输协议)是一种基于SSL/TLS加密的安全协议,数据在传输过程中被加密,具有更高的安全性。 4. ARP协议的作用是什么? 答:ARP(地址解析协议)是一种用于将IP地址映射到物理地址的协议,它通过广播网络中的ARP请求,获取目标IP地址对应的物理地址。在发送数据包时,主机需要知道目标物理地址才能将数据包发送到目标主机,而ARP协议就是用来获取目标物理地址的。 5. ICMP协议的作用是什么? 答:ICMP(Internet控制报文协议)是一种用于传递控制信息的协议,主要用于网络故障诊断和控制。常见的ICMP消息有ping、traceroute等,通过发送ICMP消息可以检测网络中的主机是否可达、网络延迟等信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gui林

你的热爱是我更新的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值