1. 所选主题和项目介绍
1.1 项目主题
无线压力监测系统 - 基于STM32WBA25的BLE蓝牙气压采集与Web监控平台
1.2 项目背景
随着物联网技术的快速发展,无线传感器网络在工业监测、环境检测、智能家居等领域得到了广泛应用。传统的有线压力监测系统存在布线复杂、灵活性差、维护成本高等问题。本项目旨在设计一款基于低功耗蓝牙(BLE)技术的无线压力监测系统,用户可通过Web蓝牙接口实时查看压力数据,实现对大气压力或工业压力的远程监控。
1.3 项目目标
- 实现对10-115kPa范围压力的精确测量
- 通过BLE无线技术实时传输压力数据
- 开发Web蓝牙网页界面,实现跨平台监控
- 支持单次采集和连续采集两种工作模式
1.4 主要功能
功能 | 描述 |
单次采集 | 用户触发后立即采集并上传一次压力数据 |
连续采集 | 以1秒间隔自动采集并上传压力数据 |
停止采集 | 停止连续采集模式 |
LED指示 | 设备状态指示 |
2. 硬件介绍
主控芯片:STM32WBA25
- 核心架构: ARM Cortex-M33 32位处理器
- 工作电压: 1.71V ~ 3.6V
- 工作频率: 支持高达100MHz
- 蓝牙版本: BLE 6.2
- ADC分辨率: 12位
STM32WBA25是STMicroelectronics推出的新一代无线微控制器,集成完整的BLE 5.3协议栈,非常适合物联网传感器应用。
压力传感器:NSPAS3N115RRA1
参数 | 规格 |
压力范围 | 10 ~ 115 kPa |
输出电压 | 0.5 ~ 4.5V(对应10~115kPa) |
激励电压 | 5V(典型值) |
精度 | ±2.5%FS |
响应时间 | 2.5ms |
工作温度 | -30°C ~ +85°C |
NSPAS3N115RRA1是一款量程为10-115kPa的绝对压力传感器,采用MEMS技术制造,具有体积小、精度高、稳定性好的特点。
3. 方案框图和项目设计思路
3.1 系统架构框图

3.2 软件架构框图

3.3 设计思路
ADC采集策略
- 独立线程运行:ADC采集任务独立于BLE任务运行,避免相互干扰
- 定时器触发:使用100ms周期的硬件定时器触发ADC采集
- HAL polling模式:采用HAL_ADC_PollForConversion方式,避免中断复杂化
- 每次重新初始化:每次采集前重新初始化ADC,确保稳定性
BLE通信策略
- GATT服务端架构:设备作为GATT服务器,网页作为客户端
- 两个Characteristics:
- LED_C (Write): 接收控制命令 (0x01单次, 0x02连续, 0x03停止)
- SWITCH_C (Notify): 发送压力数据通知
- 小端序传输:4字节无符号整数表示压力值(Pa)
命令协议
命令码 | 功能 | 说明 |
0x01 | 单次采集 | 立即采集一次并上传 |
0x02 | 开启连续 | 启动1秒间隔连续上传 |
0x03 | 停止采集 | 停止连续上传模式 |
4. 原理图和PCB设计
传感器板原理图

理论分压比:分压比 = R2 / (R1 + R2) = 300k / (200k + 300k) = 0.6
关键设计分析:
- 选择200kΩ和300kΩ而非更小阻值,是为了降低传感器负载电流
- 总阻值500kΩ,传感器驱动电流仅约10μA(@5V)
- 300kΩ与200kΩ的比例确保3.3V系统下5V传感器输出不会超出ADC范围
传感器板PCB
硬件组成如下:

5. 软件设计
5.1 主程序流程图

5.2 关键代码分析
ADC采集任务核心代码
static void Pressure_ADC_Task(void)
{
uint32_t raw_adc;
uint32_t pressure_pa;
float voltage_sensor;
/* 每次采集前重新初始化ADC,确保稳定性 */
HAL_ADC_DeInit(&hadc4);
if (HAL_ADC_Init(&hadc4) != HAL_OK) { return; }
/* 配置ADC通道1 */
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc4, &sConfig) != HAL_OK) { return; }
/* 启动转换并轮询等待 */
if (HAL_ADC_Start(&hadc4) != HAL_OK) { return; }
if (HAL_ADC_PollForConversion(&hadc4, 100) != HAL_OK) { return; }
/* 读取ADC原始值 */
raw_adc = HAL_ADC_GetValue(&hadc4);
/* 计算传感器实际电压 (考虑分压比) */
voltage_sensor = (float)raw_adc * 3300.0f / 4095.0f;
voltage_sensor = voltage_sensor * 500.0f / 300.0f; /* 分压衰减 */
/* 计算压力值: 0-5V对应10-115kPa */
pressure_pa = (uint32_t)(voltage_sensor / 1000.0f / 5.0f * 105000.0f + 10000.0f);
/* 限幅保护 */
if (pressure_pa < 10000) pressure_pa = 10000;
if (pressure_pa > 115000) pressure_pa = 115000;
/* 更新共享变量 */
LatestPressure_Pa = pressure_pa;
ADC_Data_Ready = 1;
HAL_ADC_Stop(&hadc4);
}
代码分析:
- 每次采集前调用HAL_ADC_DeInit和HAL_ADC_Init是解决ADC不稳定的关键,这是经过多次调试发现的稳定方案
- 分压比计算500.0f/300.0f是正确的,因为传感器输出通过200K+300K分压后到达ADC
- 压力计算公式(voltage/5000)*105000+10000实现了0-5V到10-115kPa的线性映射
BLE通知发送函数
void P2P_SERVER_SendPressureNotification(void)
{
P2P_SERVER_Data_t p2p_server_notification_data;
uint32_t pressure_pa;
uint8_t data[4];
/* 检查通知是否已启用 */
if (P2P_SERVER_APP_Context.Switch_c_Notification_Status != Switch_c_NOTIFICATION_ON)
{
return;
}
/* 读取最新的ADC采集值 */
if (ADC_Data_Ready)
{
pressure_pa = LatestPressure_Pa;
}
else
{
pressure_pa = 0;
}
/* 4字节小端序打包 */
data[0] = (uint8_t)(pressure_pa & 0xFF);
data[1] = (uint8_t)((pressure_pa >> 8) & 0xFF);
data[2] = (uint8_t)((pressure_pa >> 16) & 0xFF);
data[3] = (uint8_t)((pressure_pa >> 24) & 0xFF);
/* 更新发送计数 */
P2P_SERVER_APP_Context.PressureCount++;
/* 发送GATT通知 */
p2p_server_notification_data.p_Payload = data;
p2p_server_notification_data.Length = 4;
P2P_SERVER_UpdateValue(P2P_SERVER_SWITCH_C, &p2p_server_notification_data);
}
代码分析:
- 使用4字节无符号整数传输压力值(Pa),网页端通过DataView.getUint32(0, true)解析
- 小端序(little-endian)确保与STM32内存布局一致
- 通过ble_send_busy标志防止GATT操作竞争
GATT特征值定义
/* p2p_server.c */
static const uint16_t SizeSwitch_C = 4; /* 必须与实际发送长度一致! */
ret = aci_gatt_add_char(P2P_SERVER_Context.P2p_serverSvcHdle,
UUID_TYPE_128,
(Char_UUID_t *) &uuid,
SizeSwitch_C, /* 4字节压力数据 */
CHAR_PROP_NOTIFY, /* 支持通知 */
ATTR_PERMISSION_NONE,
GATT_NOTIFY_ATTRIBUTE_WRITE,
0x10,
CHAR_VALUE_LEN_VARIABLE,
&(P2P_SERVER_Context.Switch_CCharHdle));
关键点:
- SizeSwitch_C必须设置为4,否则BLE协议栈会拒绝写入
- 使用CHAR_PROP_NOTIFY实现服务端主动推送
- UUID采用128位格式:0000FE42-8E22-4541-9D4C-21EDAE82ED19
5.3 Web蓝牙网页关键代码
// 连接并使能通知
await switchChar.startNotifications();
switchChar.addEventListener('characteristicvaluechanged', onPressureChanged);
// 解析BLE通知数据
function onPressureChanged(event) {
const value = event.target.value;
const dataView = new DataView(value.buffer);
// 读取4字节小端序无符号整数
const pressurePa = dataView.getUint32(0, true); // little-endian
// 显示压力 (转换为kPa)
const pressureKpa = (pressurePa / 1000).toFixed(1);
document.getElementById('pressureValue').textContent = pressureKpa;
}
// 发送控制命令
async function sendCommand(command) {
const data = new Uint8Array([0x00, command]); // [设备选择, 命令]
await ledChar.writeValue(data);
}
6. 硬件功能展示
硬件连接效果:
网页界面展示:
7. 设计中遇到的难题和解决方法
问题描述:
发送BLE通知时总是返回错误码0x92 (INSUFFICIENT_RESOURCES)
原因分析:
- SWITCH_C characteristic的SizeSwitch_C定义为2字节
- 实际发送的是4字节压力数据
- GATT协议栈拒绝超过定义长度的写入
解决方法:
修改p2p_server.c中的特征值大小定义:
static const uint16_t SizeSwitch_C = 4; // 从2改为4
8. 心得体会
本次无线压力监测系统项目成功实现了预期功能,通过STM32WBA55的BLE 5.3技术与Web Bluetooth的结合,打造了一个低功耗、易使用的无线压力监控方案。项目过程中解决了ADC稳定性、GATT协议配置、任务调度等多个技术难题,积累了宝贵的嵌入式开发经验。