ESP8266 基础篇:国家码使用

来源:互联网 发布:淘宝 企业店铺转让 编辑:程序博客网 时间:2024/06/03 23:06

一:简介

WiFi 设备工作在 2.4G 频段或 5G 频段,由于无线信号的开放性,不同的无线设备间会存在相互干扰。因此,不同国家对 WiFi 设备都有一定的要求和限制。主要体现在频谱、射频功率、安全性及其他方面。因此,在不同国家销售的 WiFi 设备应遵循该国家或地区的要求。在 ESP8266 和 ESP32 中,国家码主要就是针对不同国家可使用的频率不同而设计的。因为 WiFi 协议中将可发射的频率划分为不同的信道,所以也可以理解为国家码就是针对不同国家的信道要求而设计。因为 ESP8266 和 ESP32 目前只支持 2.4G 频段,所以本文就以 2.4G 频段中的信道为例来说明。

国家码

下图是主要国家对于 2.4G 频段的信道要求,不同的国家对信道要求不同,如中国和欧洲支持的信道为 1-13(所以欧洲的路由器在中国是可以直接使用的),而北美只支持 1-11,日本则支持 1-14。

image

因为国内支持的信道为 1-13,所以在使用国内的路由器时,WiFi 信道只能在 1-13 之间任选;

image

美国所支持的信道是 1-11,那么路由器中只可以使用 1-11,12 和 13 即为非法信道。如果将国内的路由器带到美国,并设置信道为 12,那么用美国的手机将扫描不到这个路由器的信息。所以如果不能自由转换国家码,必然会对售往不同国家的 WiFi 设备产生影响。

二:国家码接口

在 ESP32 中,国家码相关的接口主要包含设置国家码和获取国家码

/**  * @brief     configure country info  *  * @attention 1. The default country is {.cc="CN", .schan=1, .nchan=13, policy=WIFI_COUNTRY_POLICY_AUTO}  *  * @param     wifi_country_t *country: the configured country info  *  * @return  *    - ESP_OK: succeed  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init  *    - ESP_ERR_WIFI_ARG: invalid argument  */esp_err_t esp_wifi_set_country(const wifi_country_t *country);/**  * @brief     get the current country info  *  * @param     country  country info  *  * @return  *    - ESP_OK: succeed  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init  *    - ESP_ERR_WIFI_ARG: invalid argument  */esp_err_t esp_wifi_get_country(wifi_country_t *country);

其中 esp_wifi_set_country (ESP8266 中称为 wifi_set_country) 用来设置国家码信息,esp_wifi_get_country (ESP8266 中称为 wifi_get_country) 用来获取当前的国家码信息。国家码参数信息 wifi_country_t 主要由以下几部分组成:

typedef struct {    char cc[3];               /**< country code string */    uint8_t schan;            /**< start channel */    uint8_t nchan;            /**< total channel number */    uint8_t policy;           /**< country policy */} wifi_country_t;

其中 cc 为国家代码,如中国的国家代码为 CN,美国为 US;schan 为起始信道,nchan 为总信道数,如美国的起始信道为 1,信道数为 11,policy 为国家码选项,目前只支持如下两种:

typedef enum {    WIFI_COUNTRY_POLICY_AUTO,   /**< Country policy is auto, use the country info of AP to which the station is connected */    WIFI_COUNTRY_POLICY_MANUAL, /**< Country policy is manual, always use the configured country info */} WIFI_COUNTRY_POLICY;

如果选择 auto 那么将会使用所连接 AP 的国家码信息,而 manual 表示由用户配置信息决定。

三:国家码使用

3.1 STATION 模式

当国家码 policy 为 auto 时,STA 的国家码信息由所连接的 AP 决定,如果 AP 中不含国家码信
息,则使用默认值 {“CN”, 1, 13}。比如国家码设置为 {“US”, 1, 11},连接中国的路由器后,其国家码会被自动更新为 {“CN”, 1, 13}。

当国家码 policy 为 manual 时,STA 的国家码信息由 esp_wifi_set_country 中配置信息决定,
仅扫描国家码规定的信道。

3.2 SOFTAP 模式

在 AP 模式下,国家码 policy 不会生效,可以省略,如果配置了国家为 {“US”, 1, 11},则AP可配置的信道范围为 1~11。默认的国家码信息为 {“CN”, 1, 13}。

需要注意的是配置的国家码信息会对 AP 参数的配置有影响,例如在 ESP32 中,esp_wifi_set_config 能够配置的信道范围就是由配置的国家码决定的。

3.3 AP + STATION 模式

当国家码 policy 为 auto 时,AP 的国家码信息跟随 STA 所连接的外部 AP 的国家码信息,此时
AP 会动态更新 beacon/probe response 中的国家码信息。当 STA 连接的外部 AP 的国家码信息
与 AP 配置的国家码信息不同时,会打出一条 Warning 信息,如果 STA 与连接的 AP 断开连接,
国家码依然使用最近连接过的 AP 的国家码。

当国家码 policy 为 manual 时,AP 的国家码信息由配置所决定

四:运行分析

本文以ESP8266 RTOS 的 AP + STATION 模式下的 一个 ConnectAP 的 Demo (Conn_AP_DEMO)来分析国家码的具体实现。
根据这个 demo,主要修改代码如下:

void wifi_handle_event_cb(System_Event_t *evt){    switch (evt->event_id) {        case EVENT_STAMODE_CONNECTED:            printf("connect to ssid %s, channel %d\n", evt->event_info.connected.ssid,                    evt->event_info.connected.channel);        wifi_country_t config_country;        wifi_get_country(&config_country);        printf("Country info:CC:%c%c,SC:%d,NC:%d\n",config_country.cc[0],config_country.cc[1],config_country.schan,config_country.nchan);            break;        case EVENT_STAMODE_DISCONNECTED:            printf("disconnect from ssid %s, reason %d\n", evt->event_info.disconnected.ssid,                    evt->event_info.disconnected.reason);            break;        ......    }}void conn_ap_init(void){   // wifi_country_t config_country = {.cc="US", .schan=1, .nchan=11, WIFI_COUNTRY_POLICY_AUTO};    wifi_country_t config_country = {.cc="US", .schan=1, .nchan=11, WIFI_COUNTRY_POLICY_MANUAL};    wifi_set_country(&config_country);    wifi_set_opmode(STATIONAP_MODE);     struct station_config config;    memset(&config, 0, sizeof(config));  //set value of config from address of &config to width of size to be value '0'    sprintf(config.ssid, DEMO_AP_SSID);    sprintf(config.password, DEMO_AP_PASSWORD);    wifi_station_set_config(&config);    wifi_set_event_handler_cb(wifi_handle_event_cb);    wifi_station_connect();}

代码中设置的国家码为美国,policy 为 manual,如果路由器的信道为 11,运行程序,程序可以正常连接到路由,并打印如下信息:

image

可以看到此时通过 wifi_get_country 获得的国家码为代码中设置的国家码。使用 OmniPeak 抓包,发现 ESP32 上 AP 的国家码信息也会设置为美国。

image

如果将路由器的信道更改为 12,此时重新运行程序,会发现无法连接到此路由器,串口会打印如下信息:

image

因为程序根据设置的国家码要求在信道 1-11 扫描,但路由器是在信道 12 上广播的,所以没有办法扫描到 SSID。

如果将国家码 policy 从 WIFI_COUNTRY_POLICY_MANUAL 设置为 WIFI_COUNTRY_POLICY_AUTO,重新运行程序,会发现即使路由器信道改为 12 依然可以连接上,在 wifi_get_country 中打印的信息为路由器中的国家码信息。

image

此时使用OmniPeek抓取空中包,发现 ESP32 上的 softap 回复的 Probe Rsp 包中的国家码信息已经变成路由器中的国家码信息。

image

原创粉丝点击