- ESP32 收到此控制帧后,将能够使用共享密钥和安全配置对通信数据进行加密和解密。
- 手机将BluFi中定义的帧格式部分定义的数据帧连同Wi-Fi配置信息发送到ESP32,包括SSID、密码等。
- 手机向ESP32发送Wi-Fi连接请求的控制帧。ESP32 收到此控制帧后,会认为基本信息的通信已完成,并准备连接到 Wi-Fi。
- 连接到 Wi-Fi 后,ESP32 会向手机发送 Wi-Fi 连接状态报告控制帧,以报告连接状态。至此,组网过程完成。
简化例程代码
代码源路径:Espressif\frameworks\esp-idf-v4.4.2\examples\bluetooth\blufi
主程序
void app\_main(void)
{
esp\_err\_t ret;
// Initialize NVS 初始化NVS
ret = nvs\_flash\_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP\_ERROR\_CHECK(nvs\_flash\_erase());
ret = nvs\_flash\_init();
}
ESP\_ERROR\_CHECK( ret );
initialise\_wifi();//初始化WiFi
//释放蓝牙控制器内存
ESP\_ERROR\_CHECK(esp\_bt\_controller\_mem\_release(ESP_BT_MODE_CLASSIC_BT));
//esp\_bt\_controller\_config\_t 是蓝牙控制器配置结构体,这里使用了一个默认的参数
esp\_bt\_controller\_config\_t bt_cfg = BT\_CONTROLLER\_INIT\_CONFIG\_DEFAULT();
//初始化蓝牙控制器,此函数只能被调用一次,且必须在其他蓝牙功能被调用之前调用
ret = esp\_bt\_controller\_init(&bt_cfg);
if (ret) {
BLUFI\_ERROR("%s initialize bt controller failed: %s\n", \_\_func\_\_, esp\_err\_to\_name(ret));
}
//使能蓝牙控制器,mode是蓝牙模式,如果想要动态改变蓝牙模式不能直接调用该函数
//应该先用disable关闭蓝牙再使用该API来改变蓝牙模式
ret = esp\_bt\_controller\_enable(ESP_BT_MODE_BLE);
if (ret) {
BLUFI\_ERROR("%s enable bt controller failed: %s\n", \_\_func\_\_, esp\_err\_to\_name(ret));
return;
}
//
ret = esp\_blufi\_host\_and\_cb\_init(&example_callbacks);
if (ret) {
BLUFI\_ERROR("%s initialise failed: %s\n", \_\_func\_\_, esp\_err\_to\_name(ret));
return;
}
//获取blufi版本号
BLUFI\_INFO("BLUFI VERSION %04x\n", esp\_blufi\_get\_version());
}
蓝牙初始化程序
esp\_err\_t esp\_blufi\_host\_and\_cb\_init(esp\_blufi\_callbacks\_t \*example_callbacks)
{
esp\_err\_t ret = ESP_OK;
//包括 bluedroid 初始化和使能
ret = esp\_blufi\_host\_init();
if (ret) {
BLUFI\_ERROR("%s initialise host failed: %s\n", \_\_func\_\_, esp\_err\_to\_name(ret));
return ret;
}
//创建blufi事件,注册blue回调函数
ret = esp\_blufi\_register\_callbacks(example_callbacks);
if(ret){
BLUFI\_ERROR("%s blufi register failed, error code = %x\n", \_\_func\_\_, ret);
return ret;
}
//建立蓝牙的FSM(有限状态机)
//这里使用回调函数来控制每个状态下的响应,需要将其在GAP层的回调函数注册
//esp\_gap\_cb 处理蓝牙栈可能发生的所有情况,达到FSM的效果
ret = esp\_blufi\_gap\_register\_callback();
if(ret){
BLUFI\_ERROR("%s gap register failed, error code = %x\n", \_\_func\_\_, ret);
return ret;
}
return ESP_OK;
}
esp\_err\_t esp\_blufi\_host\_init(void)
{
int ret;
//初始化蓝牙并分配系统资源,应该被第一个调用
//蓝牙栈 bluedroid stack 包括了 BT 和 BLE 使用的基本的define和API
//初始化蓝牙栈以后并不能直接使用蓝牙功能
//还需要FSM管理蓝牙连接情况
ret = esp\_bluedroid\_init();
if (ret) {
BLUFI\_ERROR("%s init bluedroid failed: %s\n", \_\_func\_\_, esp\_err\_to\_name(ret));
return ESP_FAIL;
}
//使能蓝牙栈
ret = esp\_bluedroid\_enable();
if (ret) {
BLUFI\_ERROR("%s init bluedroid failed: %s\n", \_\_func\_\_, esp\_err\_to\_name(ret));
return ESP_FAIL;
}
//获取蓝牙地址
BLUFI\_INFO("BD ADDR: "ESP_BD_ADDR_STR"\n", ESP\_BD\_ADDR\_HEX(esp\_bt\_dev\_get\_address()));
return ESP_OK;
}
初始化WiFi
执行流程:
- 初始化tcp/ip协议栈
- 创建一个FreeRTOS的事件组,事件组是一个16bit的数据,可以表示16个事件的状态,一个任务使用xEventGroupSetBits可以设置相应的事件标志,另一个任务使用xEventGroupWaitBits阻塞等待某个事件位被置位,从而实现多任务的同步。
- 创建一个event loop,并且注册wifi和ip的回调函数,用于处理相应的wifi、ip事件。
- 初始化wifi外设、设置wifi的工作模式、启动wifi。
static void initialise\_wifi(void)
{
ESP\_ERROR\_CHECK(esp\_netif\_init());
wifi_event_group = xEventGroupCreate();
ESP\_ERROR\_CHECK(esp\_event\_loop\_create\_default());
esp\_netif\_t \*sta_netif = esp\_netif\_create\_default\_wifi\_sta();
assert(sta_netif);
esp\_netif\_t \*ap_netif = esp\_netif\_create\_default\_wifi\_ap();
assert(ap_netif);
ESP\_ERROR\_CHECK(esp\_event\_handler\_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
ESP\_ERROR\_CHECK(esp\_event\_handler\_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
wifi\_init\_config\_t cfg = WIFI\_INIT\_CONFIG\_DEFAULT();
ESP\_ERROR\_CHECK( esp\_wifi\_init(&cfg) );
ESP\_ERROR\_CHECK( esp\_wifi\_set\_mode(WIFI_MODE_STA) );
ESP\_ERROR\_CHECK( esp\_wifi\_start() );
}
WiFi部分事件处理
主要负责WiFi的连接、断开重连、扫描
static void wifi\_event\_handler(void\* arg, esp\_event\_base\_t event_base,
int32\_t event_id, void\* event_data)
{
wifi\_event\_sta\_connected\_t \*event;
wifi\_mode\_t mode;
switch (event_id) {
case WIFI_EVENT_STA_START:
esp\_wifi\_connect();
break;
case WIFI_EVENT_STA_CONNECTED:
gl_sta_connected = true;
event = (wifi\_event\_sta\_connected\_t\*) event_data;
memcpy(gl_sta_bssid, event->bssid, 6);
memcpy(gl_sta_ssid, event->ssid, event->ssid_len);
gl_sta_ssid_len = event->ssid_len;
break;
case WIFI_EVENT_STA_DISCONNECTED:
/\* This is a workaround as ESP32 WiFi libs don't currently
auto-reassociate. \*/
gl_sta_connected = false;
memset(gl_sta_ssid, 0, 32);
memset(gl_sta_bssid, 0, 6);
gl_sta_ssid_len = 0;
esp\_wifi\_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
case WIFI_EVENT_AP_START:
esp\_wifi\_get\_mode(&mode);
/\* TODO: get config or information of softap, then set to report extra\_info \*/
if (ble_is_connected == true) {
if (gl_sta_connected) {
esp\_blufi\_send\_wifi\_conn\_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, softap\_get\_current\_connection\_number(), NULL);
} else {
esp\_blufi\_send\_wifi\_conn\_report(mode, ESP_BLUFI_STA_CONN_FAIL, softap\_get\_current\_connection\_number(), NULL);
}
} else {
BLUFI\_INFO("BLUFI BLE is not connected yet\n");
}
break;
case WIFI_EVENT_SCAN_DONE: {
uint16\_t apCount = 0;
esp\_wifi\_scan\_get\_ap\_num(&apCount);
if (apCount == 0) {
BLUFI\_INFO("Nothing AP found");
break;
}
wifi\_ap\_record\_t \*ap_list = (wifi\_ap\_record\_t \*)malloc(sizeof(wifi\_ap\_record\_t) \* apCount);
if (!ap_list) {
BLUFI\_ERROR("malloc error, ap\_list is NULL");
break;
}
ESP\_ERROR\_CHECK(esp\_wifi\_scan\_get\_ap\_records(&apCount, ap_list));
esp\_blufi\_ap\_record\_t \* blufi_ap_list = (esp\_blufi\_ap\_record\_t \*)malloc(apCount \* sizeof(esp\_blufi\_ap\_record\_t));
if (!blufi_ap_list) {
if (ap_list) {
free(ap_list);
}
BLUFI\_ERROR("malloc error, blufi\_ap\_list is NULL");
break;
}
for (int i = 0; i < apCount; ++i)
{
blufi_ap_list[i].rssi = ap_list[i].rssi;
memcpy(blufi_ap_list[i].ssid, ap_list[i].ssid, sizeof(ap_list[i].ssid));
}
if (ble_is_connected == true) {
esp\_blufi\_send\_wifi\_list(apCount, blufi_ap_list);
} else {
BLUFI\_INFO("BLUFI BLE is not connected yet\n");
}
esp\_wifi\_scan\_stop();
free(ap_list);
free(blufi_ap_list);
break;
}
case WIFI_EVENT_AP_STACONNECTED: {
wifi\_event\_ap\_staconnected\_t\* event = (wifi\_event\_ap\_staconnected\_t\*) event_data;
BLUFI\_INFO("station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid);
break;
}
case WIFI_EVENT_AP_STADISCONNECTED: {
wifi\_event\_ap\_stadisconnected\_t\* event = (wifi\_event\_ap\_stadisconnected\_t\*) event_data;
BLUFI\_INFO("station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid);
break;
}
default:
break;
}
return;
}
NETIF部分事件处理
获取网络 IP 地址,完成 IP 接口搭建
static void ip\_event\_handler(void\* arg, esp\_event\_base\_t event_base,
int32\_t event_id, void\* event_data)
{
wifi\_mode\_t mode;
switch (event_id) {
case IP_EVENT_STA_GOT_IP: {
esp\_blufi\_extra\_info\_t info;
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
esp\_wifi\_get\_mode(&mode);
memset(&info, 0, sizeof(esp\_blufi\_extra\_info\_t));
memcpy(info.sta_bssid, gl_sta_bssid, 6);
info.sta_bssid_set = true;
info.sta_ssid = gl_sta_ssid;
info.sta_ssid_len = gl_sta_ssid_len;
if (ble_is_connected == true) {
esp\_blufi\_send\_wifi\_conn\_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, softap\_get\_current\_connection\_number(), &info);
} else {
BLUFI\_INFO("BLUFI BLE is not connected yet\n");
}
break;
}
default:
break;
}
return;
}
BLUFI配网部分事件处理
此过程事件的处理均按照收到的请求做相应的功能处理,可按照个人需求进行修改
- ESP_BLUFI_EVENT_INIT_FINISH:完成blufi功能初始化,设置设备名称(Device Name) 并发送特定的 adv data 广播;
- ESP_BLUFI_EVENT_DEINIT_FINISH:处理deinit配置事件;
- ESP_BLUFI_EVENT_BLE_CONNECT:连接Blufi Ble,并设备进入安全模式;
- ESP_BLUFI_EVENT_BLE_DISCONNECT:设置ble断开重连;
- ESP_BLUFI_EVENT_SET_WIFI_OPMODE:设置WiFi进入运行模式——op_mode;
- ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP:设置断开原有的WiFi连接,并连接指定WiFi;
- ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP:断开当前WiIFi连接到的AP;
- ESP_BLUFI_EVENT_REPORT_ERROR:上报错误信息;
- ESP_BLUFI_EVENT_GET_WIFI_STATUS:获取WiFi状态信息,包括:WiFi当前模式、以及是否连接成功;
- ESP_BLUFI_EVENT_RECV_SLAVE_DISCONNECT_BLE:关闭blufi的gatt服务连接;
- ESP_BLUFI_EVENT_RECV_STA_BSSID:设置进入STA模式,获取目标AP的bssid;
- ESP_BLUFI_EVENT_RECV_STA_SSID:设置进入STA模式,获取目标AP的WiFi账号;
- ESP_BLUFI_EVENT_RECV_STA_PASSWD:设置进入STA模式,获取目标AP的WiFi密码;
- ESP_BLUFI_EVENT_RECV_SOFTAP_SSID:设置进入Soft AP模式,获取AP自定义账号;
- ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD:设置进入Soft AP模式,获取AP自定义密码;
- ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM:设置Soft AP模式下最大可连接设备数量;
- ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE:设置Soft AP模式下进入认证模式;
- ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL:设置Soft AP模式下的通讯通道;
- ESP_BLUFI_EVENT_GET_WIFI_LIST:获取扫描到的空中WiFi账号、通信通道以及站点MAC地址;
- ESP_BLUFI_EVENT_RECV_CUSTOM_DATA:将接收到的数据打印出来;
static void example\_event\_callback(esp\_blufi\_cb\_event\_t event, esp\_blufi\_cb\_param\_t \*param)
{
/\* actually, should post to blufi\_task handle the procedure,
\* now, as a example, we do it more simply \*/
switch (event) {
case ESP_BLUFI_EVENT_INIT_FINISH:
BLUFI\_INFO("BLUFI init finish\n");
esp\_blufi\_adv\_start();
break;
case ESP_BLUFI_EVENT_DEINIT_FINISH:
BLUFI\_INFO("BLUFI deinit finish\n");
## 最后
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**
**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/9c13ea1ecaae2e4484da31dced5dcf21.png)
![img](https://img-blog.csdnimg.cn/img_convert/8d4549f9eecbd4ab3de03ad3b4970b8b.jpeg)
![img](https://img-blog.csdnimg.cn/img_convert/76e771d08de27162df4291f9d64970b0.png)
![img](https://img-blog.csdnimg.cn/img_convert/c79d503a1134ffdd43ec8b57825f6335.png)
![img](https://img-blog.csdnimg.cn/img_convert/2ffa8efcdd2ee231592bcb04d83eaf0a.png)
![img](https://img-blog.csdnimg.cn/img_convert/ecb67f62e9892705f0df4210329388c3.png)
![](https://img-blog.csdnimg.cn/img_convert/aba9c29f51178b0322b21906a7af85a8.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**
[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!
2)]
[外链图片转存中...(img-4sNsdka3-1715555989402)]
[外链图片转存中...(img-TNGqV4eI-1715555989403)]
[外链图片转存中...(img-Xm0BlzAv-1715555989403)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**
[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!