无线通信与快充协议适配指南
无线通信与快充协议适配指南
目录
- [蓝牙/BLE 无线通信模块](#1-蓝牙 ble 无线通信模块)
- 1.1 模块选型
- 1.2 NRF52 系列初始化配置
- 1.3 [ESP8266 Wi-Fi 模块配置](#13-esp8266-wi-fi 模块配置)
- 1.4 数据透传实现
- [USB/Type-C 接口协议](#2-usbc-type-c 接口协议)
- 2.1 [USB 2.0/3.0 数据传输](#21-usb-2030 数据传输)
- 2.2 [Type-C 正反插检测](#22-type-c 正反插检测)
- 2.3 [PD 功率传输协议](#23-pd 功率传输协议)
- 快充协议实现
- 3.1 [QC 3.0 协议握手流程](#31-qc-30 协议握手流程)
- 3.2 [PD 2.0 协议握手流程](#32-pd-20 协议握手流程)
- 3.3 电压电流调节逻辑
- 3.4 [沁恒 CH224 芯片使用](#34-沁恒-ch224 芯片使用)
1. 蓝牙/BLE 无线通信模块
1.1 模块选型
1.1.1 主流蓝牙/BLE 模块对比
| 模块型号 | 厂商 | 协议 | 传输距离 | 功耗 | 成本 | 适用场景 |
|---|---|---|---|---|---|---|
| NRF52832 | Nordic | BLE 5.0 | 100m | 超低 | 中 | 可穿戴设备、传感器 |
| NRF52840 | Nordic | BLE 5.0/Thread | 200m | 超低 | 高 | 高端 IoT 设备 |
| HC-05 | CSR | 经典蓝牙 | 10m | 中 | 低 | 简单串口透传 |
| HM-10 | TI | BLE 4.0 | 30m | 低 | 低 | 低功耗应用 |
| ESP32 | Espressif | 双模蓝牙+Wi-Fi | 100m | 中 | 中 | 多功能 IoT 设备 |
1.1.2 选型建议
选择 NRF52 系列的理由:
- 超低功耗,适合电池供电设备
- 完善的 SDK 和生态系统
- 支持 BLE 5.0,传输速率高达 2Mbps
- 丰富的 GPIO 和外设接口
选择 ESP8266/ESP32 的理由:
- 集成 Wi-Fi 功能
- 成本低廉
- 社区活跃,资料丰富
- 适合需要云端连接的应用
1.2 NRF52 系列初始化配置
1.2.1 硬件连接说明
NRF52832 最小系统连接:
VCC → 3.3V
GND → GND
P0.0 → UART RX
P0.1 → UART TX
P0.2 → LED 指示
P0.3 → 按键输入
1.2.2 工程配置步骤
下面是基于 Nordic SDK 的初始化代码示例:
/**
* @file main.c
* @brief NRF52832 BLE 初始化配置示例
*
* 本示例展示如何配置 NRF52832 的 BLE 外设,
* 包括时钟、GPIO、UART 和 BLE 协议栈的初始化
*/
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_sdm.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "ble_advdata.h"
#include "ble_conn_params.h"
#include "app_timer.h"
#include "app_uart.h"
#include "app_error.h"
#include "nrf_clock.h"
// 定义引脚配置
#define LED_PIN NRF_GPIO_PIN_MAP(0, 2) // LED 连接到 P0.2
#define BUTTON_PIN NRF_GPIO_PIN_MAP(0, 3) // 按键连接到 P0.3
#define UART_RX_PIN NRF_GPIO_PIN_MAP(0, 9) // UART RX 连接到 P0.9
#define UART_TX_PIN NRF_GPIO_PIN_MAP(0, 10) // UART TX 连接到 P0.10
// BLE 配置参数
#define APP_BLE_CONN_CFG_TAG 1 // BLE 连接配置标签
#define APP_BLE_OBSERVER_PRIO 3 // BLE 观察者优先级
#define DEVICE_NAME "Nordic_Ble" // 设备名称
#define ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) // 广播间隔 100ms
// 创建 BLE 堆栈事件处理函数
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
// 已连接到中央设备
nrf_gpio_pin_set(LED_PIN); // 点亮 LED
break;
case BLE_GAP_EVT_DISCONNECTED:
// 与中央设备断开连接
nrf_gpio_pin_clear(LED_PIN); // 熄灭 LED
// 重新开始广播
advertising_start();
break;
default:
break;
}
}
/**
* @brief 初始化 SoftDevice(BLE 协议栈)
*
* SoftDevice 是 Nordic 的 BLE 协议栈固件,
* 需要在应用运行前加载到芯片中
*/
static void softdevice_init(void)
{
ret_code_t err_code;
// 使能外部高速时钟
nrf_clock_external_xtal_enabled_set(true);
// SoftDevice 配置结构体
nrf_clock_lf_cfg_t clock_config = NRF_CLOCK_LFCLKCONFIG;
// 初始化 SDH (SoftDevice Handler)
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// 配置 BLE 协议栈
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// 启用 BLE 协议栈
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// 注册 BLE 事件处理回调
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
/**
* @brief 初始化 GPIO 引脚
*
* 配置 LED 为输出模式,按键为输入模式
*/
static void gpio_init(void)
{
// 配置 LED 引脚为输出模式
nrf_gpio_cfg_output(LED_PIN);
// 配置按键引脚为输入模式,带上拉电阻
nrf_gpio_cfg_sense_input(BUTTON_PIN,
NRF_GPIO_PIN_PULLUP,
NRF_GPIO_PIN_SENSE_LOW);
// 初始状态:熄灭 LED
nrf_gpio_pin_clear(LED_PIN);
}
/**
* @brief 初始化 UART 串口通信
*
* 用于调试信息输出和 AT 命令交互
*/
static void uart_init(void)
{
ret_code_t err_code;
// UART 配置结构体
const app_uart_comm_params_t comm_params =
{
.rx_pin_no = UART_RX_PIN,
.tx_pin_no = UART_TX_PIN,
.rts_pin_no = NRF_UART_PSEL_DISCONNECTED,
.cts_pin_no = NRF_UART_PSEL_DISCONNECTED,
.flow_control = APP_UART_FLOW_CONTROL_DISABLED,
.use_parity = false,
.baud_rate = NRF_UART_BAUDRATE_115200
};
// 初始化 UART
APP_UART_FIFO_INIT(&comm_params,
APP_UART_DRIVER_INSTANCE,
uart_event_handle,
APP_SCHEDULER_EVENT_SIZE,
APP_TIMER_QUEUES_SIZE,
err_code);
APP_ERROR_CHECK(err_code);
}
/**
* @brief 初始化 BLE 广播
*
* 配置广播数据包,让其他设备能够发现本设备
*/
static void advertising_init(void)
{
ret_code_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
// 配置广播类型
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
// 配置广播参数
init.config.interval_sec = 0;
init.config.timeout_sec = 0;
init.mode_first = BLE_ADV_MODE_FAST;
init.fast_interval = ADV_INTERVAL;
// 初始化广播模块
err_code = ble_advertising_init(&init);
APP_ERROR_CHECK(err_code);
}
/**
* @brief 开始 BLE 广播
*/
static void advertising_start(void)
{
ret_code_t err_code;
err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
}
/**
* @brief 主函数
*
* 程序入口点,依次初始化各个模块
*/
int main(void)
{
// 1. 初始化 GPIO
gpio_init();
// 2. 初始化定时器
app_timer_init();
// 3. 初始化 UART
uart_init();
// 4. 初始化 SoftDevice(BLE 协议栈)
softdevice_init();
// 5. 初始化 BLE 广播
advertising_init();
// 6. 开始广播
advertising_start();
printf("NRF52832 BLE 初始化完成\r\n");
// 主循环
while (true)
{
// 进入低功耗模式,等待事件唤醒
__WFE();
}
}
代码说明:
上述代码完成了 NRF52832 的完整初始化流程:
-
softdevice_init(): 初始化 BLE 协议栈,这是 Nordic 芯片特有的设计。SoftDevice 是一个预编译的 BLE 协议栈二进制文件,运行在独立的内核空间,应用程序通过 API 与之通信。
-
gpio_init(): 配置 GPIO 引脚的工作模式。LED 配置为推挽输出模式,按键配置为上拉输入模式,这样可以检测按键按下 (低电平)。
-
uart_init(): 初始化 UART 串口通信,用于打印调试信息和接收 AT 命令。这里使用 115200 波特率,无流控。
-
advertising_init(): 配置 BLE 广播参数。广播是让其他 BLE 中央设备 (如手机) 能够发现本设备的过程。
-
advertising_start(): 启动广播,设备开始对外发送广播包。
1.3 ESP8266 Wi-Fi 模块配置
1.3.1 硬件连接
ESP8266 NodeMCU 引脚定义:
VIN → 5V (或 3.3V)
GND → GND
D1 → I2C SCL
D2 → I2C SDA
D5 → SPI SCK
D6 → SPI MISO
D7 → SPI MOSI
TX → UART 连接到 MCU RX
RX → UART 连接到 MCU TX
1.3.2 Arduino IDE 环境配置
/**
* @file esp8266_wifi.ino
* @brief ESP8266 Wi-Fi 客户端配置示例
*
* 实现 ESP8266 连接 Wi-Fi 网络并通过 TCP 发送数据
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
// Wi-Fi 配置
const char* ssid = "YourWiFi_SSID";
const char* password = "YourWiFi_Password";
// 服务器配置
const char* server_host = "192.168.1.100";
const int server_port = 8080;
// LED 指示灯
#define LED_PIN 2 // ESP8266 板载 LED 连接到 GPIO2
/**
* @brief Wi-Fi 连接函数
*
* 尝试连接到指定的 Wi-Fi 网络,
* 连接成功后会通过串口打印 IP 地址
*/
void connectWiFi() {
Serial.println("开始连接 Wi-Fi...");
WiFi.begin(ssid, password);
// 等待连接,最多尝试 20 次
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWi-Fi 连接成功!");
Serial.print("IP 地址:");
Serial.println(WiFi.localIP());
// 快速闪烁 3 次表示成功
for(int i = 0; i < 3; i++) {
digitalWrite(LED_PIN, HIGH);
delay(100);
digitalWrite(LED_PIN, LOW);
delay(100);
}
} else {
Serial.println("\nWi-Fi 连接失败!");
// 慢速闪烁表示失败
while(true) {
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
delay(500);
}
}
}
/**
* @brief 发送 HTTP GET 请求
*
* 向指定服务器发送 HTTP GET 请求并获取响应
*/
void sendHttpRequest() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// 构建 URL
String url = "http://" + String(server_host) + ":" + String(server_port) + "/api/data";
Serial.println("发送 HTTP 请求:" + url);
// 发起 HTTP GET 请求
http.begin(url);
int httpCode = http.GET();
// 检查响应码
if (httpCode > 0) {
Serial.printf("HTTP 响应码:%d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println("响应内容:");
Serial.println(payload);
}
} else {
Serial.printf("HTTP 请求失败,错误码:%d\n", httpCode);
}
http.end(); // 关闭连接
} else {
Serial.println("Wi-Fi 未连接,无法发送 HTTP 请求");
}
}
/**
* @brief 建立 TCP 连接并发送数据
*
* 使用 WiFiClient 直接建立 TCP 连接发送原始数据
*/
void sendTcpData(const char* data) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wi-Fi 未连接");
return;
}
WiFiClient client;
Serial.print("连接到服务器 ");
Serial.print(server_host);
Serial.print(":");
Serial.println(server_port);
// 尝试连接服务器
if (!client.connect(server_host, server_port)) {
Serial.println("连接服务器失败");
return;
}
Serial.println("服务器连接成功");
// 发送数据
client.print(data);
Serial.print("已发送数据:");
Serial.println(data);
// 等待服务器响应
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println("服务器响应超时");
client.stop();
return;
}
}
// 读取响应
while (client.available()) {
String response = client.readStringUntil('\r');
Serial.print(response);
}
Serial.println("\n连接关闭");
client.stop();
}
void setup() {
// 初始化串口
Serial.begin(115200);
delay(100);
// 配置 LED
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.println("\n=== ESP8266 Wi-Fi 配置示例 ===");
// 连接 Wi-Fi
connectWiFi();
}
void loop() {
// 每 5 秒发送一次 HTTP 请求
sendHttpRequest();
delay(5000);
}
代码说明:
这段 Arduino 代码展示了 ESP8266 的 Wi-Fi 客户端功能:
-
connectWiFi(): 实现 Wi-Fi 连接的完整流程,包含重试机制和状态指示。
-
sendHttpRequest(): 使用 HTTPClient 库发送 HTTP GET 请求,适用于 RESTful API 调用。
-
sendTcpData(): 使用底层的 WiFiClient 直接建立 TCP 连接,适合自定义协议通信。
1.4 数据透传实现
1.4.1 蓝牙串口透传 (SPP over BLE)
BLE 串口透传允许设备与手机之间进行双向串口数据传输,类似于传统蓝牙的 SPP 协议。
实现要点:
- 使用 Nordic UART Service (NUS) 或类似服务
- 定义 RX/TX 两个特征
- RX 特征用于接收数据 (写操作)
- TX 特征用于发送数据 (通知)
1.4.2 Wi-Fi TCP 透传
Wi-Fi TCP 透传实现设备与服务器之间的长连接双向通信。
实现要点:
- 建立稳定的 TCP 连接
- 实现自动重连机制
- 处理数据缓冲和流量控制
- 支持心跳包保持连接
2. USB/Type-C 接口协议
2.1 USB 2.0/3.0 数据传输
2.1.1 USB 通信基础
USB (Universal Serial Bus) 是一种通用的串行总线标准,支持即插即用和热插拔功能。
USB 2.0 vs USB 3.0 对比:
| 特性 | USB 2.0 | USB 3.0 |
|---|---|---|
| 最大传输速率 | 480 Mbps | 5 Gbps |
| 数据线数量 | 2 (D+, D-) | 5 (D+, D-, Tx+, Tx-, Rx+, Rx-) |
| 供电能力 | 5V/0.5A (2.5W) | 5V/0.9A (4.5W) |
| 连接器类型 | Type-A, Type-B, Mini, Micro | Type-A, Type-B, Type-C |
| 全双工通信 | 否 (半双工) | 是 (全双工) |
2.1.2 STM32 USB 设备实现
STM32 微控制器内置 USB 外设,可以配置为 USB 设备、主机或 OTG 模式。
配置步骤:
- 使用 STM32CubeMX 配置 USB 外设
- 选择 USB Device 模式
- 选择 CDC (虚拟串口) 类
- 生成代码并添加应用逻辑
2.2 Type-C 正反插检测
2.2.1 Type-C 接口电气特性
Type-C 接口的关键特性:
- 支持正反插拔
- 通过 CC (Configuration Channel) 引脚检测连接方向
- 支持 USB PD 功率传输协议
- 最大支持 20V/5A (100W) 功率传输
2.2.2 CC 引脚检测原理
Type-C 插头内部在 CC 引脚上有上拉电阻 (源端) 或下拉电阻 (设备端)。通过检测 CC 引脚的电压可以判断:
- 是否有设备连接
- 插头的方向 (正向或反向)
- 附件类型
电压判断逻辑:
- 未连接: CC1 和 CC2 都接近 0V
- 正向插入: CC1 高电平 (约 5V),CC2 低电平
- 反向插入: CC2 高电平,CC1 低电平
- 调试附件: CC1 和 CC2 都高电平
2.3 PD 功率传输协议
2.3.1 USB PD 协议基础
USB Power Delivery (PD) 是一种智能功率传输协议,允许设备之间协商电压和电流。
PD 协议关键特性:
- 支持电压:5V, 9V, 15V, 20V
- 支持电流:最高 5A
- 最大功率:100W (20V×5A)
- 通信方式:通过 CC 引脚使用 BMC 编码
2.3.2 PD 通信物理层
BMC 编码 (Biphase Mark Code) 是 PD 协议的物理层编码方式:
- 每个位周期中间都有跳变
- 逻辑 1 在位周期开始时有额外跳变
- 逻辑 0 在位周期开始时无跳变
- 位时间:1μs
3. 快充协议实现
3.1 QC 3.0 协议握手流程
3.1.1 QC 协议概述
Quick Charge (QC) 是高通公司开发的快充协议,QC 3.0 支持 3.6V-20V 范围内的动态电压调节。
QC 3.0 关键特性:
- 电压范围:3.6V - 20V (以 200mV 步进)
- 最大电流:3A
- 向下兼容:QC 2.0、普通 USB
- 通信方式:通过 D+ 线电压脉冲调制
3.1.2 QC 3.0 握手流程
步骤 1:检测 QC 充电器
- 检测设备是否连接到 QC 充电器
- D+ 电压特征识别
步骤 2:握手请求
- 发送连续脉冲序列
- 告知充电器设备支持 QC 协议
步骤 3:电压请求
- 发送特定数量的脉冲
- 每个脉冲代表一个电压等级
步骤 4:电压确认
- 充电器调整输出电压
- 设备检测确认电压正确
3.2 PD 2.0 协议握手流程
3.2.1 PD 通信消息类型
PD 协议定义了多种消息类型:
- Source_Capabilities: 电源提供能力
- Request: 电源请求
- Accept: 接受请求
- PS_RDY: 电源就绪
- Get_Status: 获取状态
3.2.2 完整握手流程
设备 充电器
| |
|←-- Source_Capabilities --| (充电器发送支持的能力)
| |
|------- Request --------->| (设备请求特定电压电流)
| |
|←------- Accept ----------| (充电器接受请求)
| |
|←------- PS_RDY ---------| (充电器准备就绪,开始输出)
| |
|-- GoodCRC -------------->| (确认收到)
| |
3.3 电压电流调节逻辑
3.3.1 闭环反馈控制
为保证输出电压稳定,需要使用闭环反馈控制:
- ADC 采样: 实时采集输出电压
- 误差计算: 与目标电压比较得到误差
- PID 调节: 通过 PID 算法调节 PWM 占空比
- PWM 输出: 控制 DC-DC 变换器
3.3.2 PID 控制算法
// PID 控制结构体
typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float setpoint; // 设定值
float integral; // 积分项
float prev_error; // 上次误差
float output_max; // 输出限幅
} PID_Controller_t;
// PID 计算函数
float PID_Calculate(PID_Controller_t* pid, float measured_value)
{
float error = pid->setpoint - measured_value;
// 比例项
float proportional = pid->Kp * error;
// 积分项 (带抗饱和)
pid->integral += error;
if (pid->integral > pid->output_max) {
pid->integral = pid->output_max;
}
float integral_term = pid->Ki * pid->integral;
// 微分项
float derivative = pid->Kd * (error - pid->prev_error);
pid->prev_error = error;
// 计算总输出
float output = proportional + integral_term + derivative;
// 输出限幅
if (output > pid->output_max) {
output = pid->output_max;
}
if (output < -pid->output_max) {
output = -pid->output_max;
}
return output;
}
3.4 沁恒 CH224 芯片使用
3.4.1 CH224K 简介
CH224K 是沁恒微电子推出的 USB PD 受电端协议芯片,支持:
- USB PD 2.0/3.0协议
- QC 2.0/3.0协议
- 支持 5V/9V/12V/15V/20V 电压请求
- 内置 VBUS 放电电路
- SOP 物理层集成
3.4.2 硬件连接
CH224K 典型应用电路:
VBUS → 电源输入 (5-20V)
GND → 地
D+ → USB D+ 数据线
D- → USB D- 数据线
CC → Type-C CC 引脚
OUT → 协议请求输出 (控制 DC-DC)
3.4.3 配置方法
CH224K 通过外围电阻配置请求电压:
| 请求电压 | R1 阻值 | R2 阻值 |
|---|---|---|
| 5V | 不焊接 | 200kΩ |
| 9V | 51kΩ | 200kΩ |
| 12V | 100kΩ | 200kΩ |
| 15V | 150kΩ | 200kΩ |
| 20V | 200kΩ | 200kΩ |
3.4.4 应用电路示例
Type-C 接口 ──→ CH224K ──→ DC-DC 变换器 ──→ 负载
│
├─→ VBUS 检测
├─→ CC 通信
└─→ OUT 控制信号
工作原理:
- CH224K 通过 CC 引脚与充电器进行 PD 通信
- 根据配置的电阻值请求相应电压
- 握手成功后,OUT 引脚输出控制信号
- DC-DC 变换器将 VBUS 转换为设备所需电压
总结
本指南详细介绍了无线通信 (蓝牙/BLE/Wi-Fi) 和快充协议 (QC/PD) 的实现方法,包括:
- 模块选型与初始化: NRF52、ESP8266等主流模块的配置
- 数据透传: BLE 串口和 Wi-Fi TCP 的双向通信实现
- USB/Type-C: 接口检测、PD 协议物理层
- 快充协议: QC 3.0、PD 2.0 的完整握手流程和电压调节
- 实用芯片: CH224K 等协议芯片的使用方法
更多推荐
所有评论(0)