用C语言实现无线充电器的通信编程:符合WPC标准的双向数据交互
WPC Qi不是“放上去就充电”。接收端通过负载调制把数据包回传发射端,发射端解析后动态调整线圈驱动,才算合规通信。 BPP阶段基本是Rx→Tx单向; EPP里控制指令更完整,但工程上仍按“Rx发包、Tx解析、Tx调功率”的主线写代码最稳。
一、通信物理层要点
Qi带内通信靠Rx侧短暂改变负载,Tx检测电流纹波。 编码规则记住三条:
差分双相编码,约2kbps
字节格式:起始位+8数据位(LSB优先)+奇校验+停止位
数据包:前导码 + 包头 + 消息 + 校验和(异或)
校验和计算:
uint8_t qi_checksum(uint8_t hdr, const uint8_t*msg, int len){
uint8_t c = hdr;
for(int i=0;i<len;i++) c ^= msg[i];
return c;
}
收到包先校验和、再奇校验,任一项错直接丢弃,不回任何状态。
二、协议阶段状态机
Tx侧核心四态:
SELECT → PING → ID_CONFIG → POWER_TRANSFER
任意阶段超时/校验错/合同违约,回SELECT。
typedef enum {
ST_SELECT, ST_PING,
ST_ID_CFG, ST_POWER,
ST_FAULT
} qi_state_t;
static qi_state_t st = ST_SELECT;
static uint32_t state_ms;
void qi_poll(uint32_t now){
switch(st){
case ST_SELECT:
tx_driver_off();
if(object_detected()) st = ST_PING;
break;
case ST_PING:
digital_ping_start();
if(rx_packet_ready()){ // 收到Signal Strength
parse_rx_packet();
st = ST_ID_CFG;
}else if(now-state_ms > PING_TIMEOUT){
st = ST_SELECT; // 无响应放弃
}
break;
case ST_ID_CFG:
if(handle_id_config()){ // 识别包+配置包
build_power_contract();
st = ST_POWER;
}else{
st = ST_SELECT;
}
break;
case ST_POWER:
power_control_loop();
if(contract_violated()) st = ST_SELECT;
break;
}
}
状态机必须非阻塞,定时靠now-state_ms,别在状态里delay_ms。
三、Rx回传的关键包
功率传输阶段Rx主要发这几类:
Signal Strength (0x01):耦合强度,Ping阶段先发
Control Error (0x03):CEP,目标功率与当前功率误差,[-128,127]
Received Power (0x04):接收功率,供Tx做FOD比对
Charge Status (0x05):电量百分比
End Power Transfer (0x02):终止充电,带原因码
Rx侧发CE包示例:
void rx_send_control_error(int8_t ce){
uint8_t msg[1] = { (uint8_t)ce };
uint8_t hdr = 0x03;
uint8_t chk = qi_checksum(hdr, msg, 1);
qi_async_send(hdr, msg, 1, chk); // 负载调制输出
}
CEP计算用目标整流电压减当前值再归一化,负值表示降压、正值升压。
四、Tx功率控制闭环
收到CEP后调频率或占空比,别一步拉满:
static int8_t ce_last;
void power_control_loop(void){
if(!rx_packet_ready()) return;
qi_pkt_t*p = parse_rx_packet();
if(p->hdr == 0x03){
ce_last = p->msg[0];
int step = ce_last>>3; // 死区收窄
set_tx_freq(base_freq + step);
}else if(p->hdr == 0x02){
st = ST_SELECT; // EPT请求
}
}
CEP=0不调;|CEP|小的时候步进也小,避免抖动。FOD比对用Rx上报Received Power和Tx侧输入功率差,超阈值断充。
五、双向交互的工程边界
严格说Qi基础通信是Rx→Tx;Tx“回传”不是发应用数据包,而是通过调频率/功率响应。 EPP认证、私有协议包(0x18/0x19)才涉及更多交互。C代码里别幻想“Tx主动发文本指令给Rx”,正确闭环是:
Rx报误差 → Tx改驱动
Tx改Ping节奏/断电 → Rx感知掉电
私有通道走Proprietary包载荷
六、落坑清单
校验错还处理消息→功率误调
状态机里阻塞延时→Ping超时漏检
CEP每包都大幅调频→振荡发热
Rx在Ping前发配置包→时序不对
Tx不回SELECT→异物/超时卡死
负载调制脉宽不满足t_S/t_T→Tx解不出位
前导码同步位不够→包头起始位误判
收到EPT不立即停功率→续充违规
七、落地顺序
先调通负载调制bit收发(示波器看Tx电流纹波)
实现字节差分双相解码+奇校验
封装包解析:前导→头→消息→校验和
Tx状态机SELECT/PING/ID_CFG/POWER
Rx发Signal Strength→进入识别
功率阶段周期发CEP
Tx做频率闭环+死区
EPT/超时/合同违约回SELECT
FOD功率差比对
符合WPC的无线充电通信,本质就是“Rx用负载调制回报状态,Tx用状态机解析并调功率”。C语言实现不复杂:校验和丢弃错包、非阻塞状态机管阶段、CEP做慢闭环、EPT和安全事件兜底回待机。把协议分层收住,发射端就不会盲送功率,接收端也不会在耦合变化时掉合同——认证和量产稳定性都在这套状态机里。





