【瑞萨BLE/WIFI模块测评】+ 6、DA14531配置Wifi连接信息
本帖最后由 eefocus_3896990 于 2026-10-7 20:18 编辑【瑞萨BLE/WIFI模块测评】+1、DA16200 模块 GUI Tool
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236549&fromuid=368655
(出处: 点点手机版网页打不开论坛)
【瑞萨BLE/WIFI模块测评】+ 2、H3003传感器数据读取
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236550&fromuid=368655
(出处: 点点手机版网页打不开论坛)
【瑞萨BLE/WIFI模块测评】+3、ISL29035光照传感器数据读取
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236551&fromuid=368655
(出处: 点点手机版网页打不开论坛)
【瑞萨BLE/WIFI模块测评】+4、DA16200 HTTP 显示传感器数据和监控按键
//m.qjumbo.com/forum/forum.php?mod=viewthread&tid=236552&fromuid=368655
(出处: 点点手机版网页打不开论坛)
【瑞萨BLE/WIFI模块测评】5、DA14531蓝牙模块数据接收
//m.qjumbo.com/forum/thread-236599-1-1.html
(出处: 点点手机版网页打不开论坛)
之前的帖子实现DA14531模块的数据接收,利用DA14531模块接收包含Wifi连接信息的JSON数据,提取其中包含的Wifi连接信息,用于DA16200模块连接到Wifi网络。
# 1、添加JSON解析
定义用缓存JSON数据的缓存帧结构体和帧处理的函数声明
```c
#ifndef FRAME_RX_H
#define FRAME_RX_H
#include <stdint.h>
#include <stdbool.h>
#define FRAME_MAX_LEN 256
typedef struct {
char buf;
uint16_t idx;
int depth;
bool in_frame;
bool in_str;
bool escape;
bool overflow;
} frame_rx_t;
void frame_rx_init(frame_rx_t *fr);
bool frame_rx_feed(frame_rx_t *fr, uint8_t byte);
const char *frame_rx_data(frame_rx_t *fr);
#endif
```
数据帧结构的初始化、数据输入与解析、数据帧缓存获取的函数定义如下。其中数据帧的解析用于存储获得的数据,并判断获取的数据是否满足完整的JSON数据结构。用于**的JSON数据解析。
```c
#include "frame_rx.h"
#include <string.h>
void frame_rx_init(frame_rx_t *fr) {
fr->idx = 0;
fr->depth = 0;
fr->in_frame = false;
fr->in_str = false;
fr->escape = false;
fr->overflow = false;
fr->buf = '\0';
}
bool frame_rx_feed(frame_rx_t *fr, uint8_t byte) {
/* ---------- 帧外 ---------- */
if (!fr->in_frame) {
if (byte == '{') {
fr->in_frame = true;
fr->depth = 1;
fr->in_str = false;
fr->escape = false;
fr->idx = 0;
fr->overflow = false;
fr->buf = '{';
}
return false; /* 其它字符忽略 */
}
/* ---------- 帧内 ---------- */
/* 忽略 CR/LF,避免被行结束误伤 */
if (byte == '\r' || byte == '\n') {
return false;
}
/* 转义处理 */
if (fr->escape) {
fr->escape = false;
} else if (byte == '\\') {
fr->escape = true;
} else if (byte == '"') {
fr->in_str = !fr->in_str;
} else if (!fr->in_str) {
if (byte == '{') {
fr->depth++;
} else if (byte == '}') {
fr->depth--;
}
}
/* 存入缓冲 */
if (fr->idx < FRAME_MAX_LEN - 1) {
fr->buf = (char)byte;
} else {
fr->overflow = true;
}
/* 一帧结束? */
if (fr->depth == 0) {
fr->buf = '\0';
fr->in_frame = false;
fr->in_str = false;
fr->escape = false;
if (fr->overflow) {
fr->overflow = false;
return false; /* 太长,丢弃 */
}
return true;
}
return false;
}
const char *frame_rx_data(frame_rx_t *fr) {
return fr->buf;
}
```
JSON数据的解析和其中Wifi连接获取的数据定义如下,能够处理`{"ssid":"WiFi SSID","pass":"WIFI_PASS"}`的JSON数据。
```c
int parse_wifi_json(const char *json, char *ssid, int ssid_len,char *pass, int pass_len);
/* 从 json 中提取 key 对应的字符串值到 out */
static bool json_get_str(const char *json, const char *key, char *out, int outlen) {
char pattern;
snprintf(pattern, sizeof(pattern), "\"%s\"", key);
const char *p = strstr(json, pattern);
if (!p) return false;
p += strlen(pattern);
while (*p == ' ' || *p == '\t') p++;
if (*p != ':') return false;
p++;
while (*p == ' ' || *p == '\t') p++;
if (*p != '"') return false;
p++;
int i = 0;
while (*p && *p != '"' && i < outlen-1) {
if (*p == '\\' && *(p+1)) { p++; } /* 简单转义处理 */
out = *p++;
}
out = '\0';
return (*p == '"');
}
/* 返回 0 成功,-1 失败 */
int parse_wifi_json(const char *json, char *ssid, int ssid_len,
char *pass, int pass_len) {
if (!json_get_str(json, "ssid", ssid, ssid_len)) return -1;
/* 密码允许为空,但字段要存在 */
if (!json_get_str(json, "pass", pass, pass_len)) {
pass = '\0';
}
return 0;
}
```
# 2、添加BLE配置Wifi连接的代码
定义用于存储BLE数据帧的结构体变量,用于存储SSID和PASS的数组、用于判断是否接收到Wifi配置信息的变量。
```c
char ssid_buffer, pass_buffer;
static frame_rx_t s_ble_frame;
int wifi_result;
```
添加以下代码,用于获取一次通过BLE传输获得Wfii配置信息,得到的信息存储在`ssid_buffer`和`pass_buffer`数组中。
```c
frame_rx_init(&s_ble_frame);
err = ble_transport_init();
while (!s_wifi_busy)
{
ble_transport_poll();
g_app_ble_connected = ble_transport_is_connected();
uint8_t b;
while (ble_get_byte(&b)) {
if (frame_rx_feed(&s_ble_frame, b)) {
const char *json = frame_rx_data(&s_ble_frame);
wifi_result=parse_wifi_json(json, ssid_buffer, sizeof(ssid_buffer),
pass_buffer, sizeof(pass_buffer));
if(wifi_result==0)
s_wifi_busy=true;
}
}
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
}
```
`da16200_AT.c`中,与Wifi连接的相关代码如下,利用获取的SSID和PASS信息,构造用于Wifi连接的字符串,用于AT指令中用于连接到Wifi网络中的WFJAP指令使用。
```c
#define AP_SSID_BUF_LEN30
#define AP_PASS_BUF_LEN30
char ap_ssid;
char ap_pw;
extern char ssid_buffer, pass_buffer;
/* ---------- 构造 AT 参数字符串 ---------- */
static bool build_ap_params(const char *ssid, const char *pass)
{
/* 安全检查:拒绝特殊字符 */
for (const char *p = ssid; *p; p++) {
if (*p == '\'' || *p == ',' || *p == '\\' || *p == '"') return false;
}
for (const char *p = pass; *p; p++) {
if (*p == '\'' || *p == ',' || *p == '\\' || *p == '"') return false;
}
int n = snprintf(ap_ssid, sizeof(ap_ssid), "'%s',", ssid);
if (n < 0 || n >= (int)sizeof(ap_ssid)) return false;
n = snprintf(ap_pw, sizeof(ap_pw), "%s", pass);
if (n < 0 || n >= (int)sizeof(ap_pw)) return false;
return true;
}
if (!build_ap_params(ssid_buffer, pass_buffer)) {
APP_PRINT("SSID/PASS invalid or too long\r\n");
return FSP_ERR_INVALID_ARGUMENT;
}
APP_PRINT("Connecting to AP: %s\r\n", ssid_buffer);
part_array = (uint32_t)ap_ssid;
part_array = (uint32_t)ap_pw;
part_array = (uint32_t)at_cmd_end;
At_cmd_combine(DA16200_AT_CMD_INDEX_AT_WFJAP, part_array, 3);
status = AT_cmd_rcv_data(DA16200_AT_CMD_INDEX_AT_WFJAP, 4000);
if(status != FSP_SUCCESS)
{
APP_PRINT("AT+WFJAPA command error!\r\n");
return status;
}
else
{
APP_PRINT("Connect to an AP successfully!\r\n");
}
```
# 3、总结
通过BLE模块接收串口数据,采用流控制的方式对接收到的数组进行JSON数据完整性检查和存储,接收到完整的JSON数据帧后,提取其中的Wifi连接信息用于Wifi连接。
页:
[1]