
本文是对《无线充电中继_嵌入式实现文档.md》的增量补丁。第一节是改哪几处其余照抄即可原文件其它部分不动。一、对原 md 的改动清单只改这 5 处改动 1 · 全局宏第 0 节效率分类里加一个 case在#define EFF_BAT_OVER_IN 3后面加一行#define EFF_COIL_RX_OVER_TX 4 /* η P_RX线圈 / P_TX线圈 纯线圈效率(两处交流有效功率之比) */改动 2 · 新增线圈标定宏放在原 1.3 那批标定宏后面/* TX/RX 线圈两处的电压/电流采样标定按实际分压比、采样电阻、运放增益改*/ #define VTX_DIV 4.0f /* TX 线圈电压分压比 */ #define ITX_RS 0.05f /* TX 线圈电流采样电阻(Ω) */ #define ITX_G 20.0f /* TX 电流运放增益 */ #define VRX_DIV 4.0f /* RX 线圈电压分压比 */ #define IRX_RS 0.05f #define IRX_G 20.0f改动 3 · 替换Measure()函数原 1.7 里那一个把原来的Measure()整个换成下面这版只是多了一个#if分支直流各 case 走原路线圈 case 走同步采样void Measure(float *pin, float *pout, float *eff){ #if EFFICIENCY_CASEEFF_COIL_RX_OVER_TX float ptx, prx; Coil_Power(ptx, prx); /* 纯线圈pinTX有效功率, poutRX有效功率 */ *pin ptx; *pout prx; *eff (ptx0.001f)? (prx/ptx) : 0.0f; #else *pin Power_In(); *pout Power_Out(); *eff (*pin0.001f)? (*pout / *pin) : 0.0f; #endif }改动 4 · ADC 外设配置原 1.3 之外新增双 ADC 同步配置见本文件第三节 3.3。要点再启用 ADC2ADC1 设为Regular simultaneous modeADC2 自动成从机ADC1 采两路电压(Vtx,Vrx)、ADC2 采两路电流(Itx,Irx)DMA 32 位循环。仅当EFFICIENCY_CASEEFF_COIL_RX_OVER_TX时用这套采样其余 case 仍用原 ADC1 单机多通道扫描。改动 5 ·USER CODE BEGIN 4新增Coil_Power() 采样启动/* 纯线圈效率双ADC同步采样缓冲交错存 even(Vtx,Itx) odd(Vrx,Irx) */ #define COIL_SETS 128 uint32_t coil_buf[2*COIL_SETS]; /* 每个字低16ADC1(电压) 高16ADC2(电流) */ void Coil_Sampling_Start(void){ HAL_ADCEx_Calibration_Start(hadc1); HAL_ADCEx_Calibration_Start(hadc2); HAL_ADCEx_MultiModeStart_DMA(hadc1, (uint32_t*)coil_buf, 2*COIL_SETS); } /* 分别算 TX/RX 线圈有效功率去直流后 mean(v·i)自带功率因数 cosφ */ void Coil_Power(float *ptx, float *prx){ double svt0,sit0,svr0,sir0; for(uint16_t k0;kCOIL_SETS;k){ uint32_t acoil_buf[2*k], bcoil_buf[2*k1]; svt(a0xFFFF); sit((a16)0xFFFF); svr(b0xFFFF); sir((b16)0xFFFF); } float vtmsvt/COIL_SETS, itmsit/COIL_SETS, vrmsvr/COIL_SETS, irmsir/COIL_SETS; double pt0, pr0; for(uint16_t k0;kCOIL_SETS;k){ uint32_t acoil_buf[2*k], bcoil_buf[2*k1]; float vt((float)(a0xFFFF) -vtm)*(VREF/ADC_FS)*VTX_DIV; /* TX电压(与TX电流同刻) */ float it((float)((a16)0xFFFF)-itm)*(VREF/ADC_FS)/ITX_G/ITX_RS;/* TX电流 */ float vr((float)(b0xFFFF) -vrm)*(VREF/ADC_FS)*VRX_DIV; /* RX电压(与RX电流同刻) */ float ir((float)((b16)0xFFFF)-irm)*(VREF/ADC_FS)/IRX_G/IRX_RS;/* RX电流 */ pt(double)vt*it; pr(double)vr*ir; } *ptx(float)(pt/COIL_SETS); /* Urms·Irms·cosφ (有效功率) */ *prx(float)(pr/COIL_SETS); } /* 想单独上报可选cosφ P/(Vrms·Irms)Vrms√(mean((v-v̄)²)) */并在main()的USER CODE BEGIN 2里把原来的ADC_StartAll();按 case 二选一#if EFFICIENCY_CASEEFF_COIL_RX_OVER_TX Coil_Sampling_Start(); /* 线圈效率双ADC同步 */ #else ADC_StartAll(); /* 其余ADC1单机多通道 */ #endif改完这 5 处#define EFFICIENCY_CASE EFF_COIL_RX_OVER_TX即启用纯线圈效率其它三种直流 case 不受影响。二、纯线圈效率原理线圈两端都是高频交流有效(有功)功率 Vrms·Irms·cosφ。cosφ 是电压电流相位差的余弦你说的 Q。直接测 Urms、Irms 再乘 cosφ 要单独测相位麻烦用同步采样的瞬时乘积平均P (1/N)Σ v·i一步到位自动含 cosφ。$$\eta{coil}\frac{P{RX}}{P{TX}}\frac{\frac1N\sum v{rx}i{rx}}{\frac1N\sum v{tx}i_{tx}}$$关键前提每个线圈的 V 和 I 必须同一时刻采样否则相位错开功率全错。所以用双 ADC 同步模式——ADC1 采电压、ADC2 采电流硬件保证同刻。TX 和 RX 之间不要求同刻它们是两个独立的功率。⚠️ F1 采样密度的现实150kHz 周期 6.7µs。双 ADC 各扫 2 路(电压两路/电流两路)一组要 2 次转换≈2.3µs每周期只有约 3 个点误差偏大。想更准就分两次测先只测 TX(ADC1Vtx, ADC2Itx单路)、再只测 RX各自每周期 5~6 点。能在低压直流侧测就优先测直流。三、ADC 详细配置手册3.1 F1 三条铁律ADC 时钟 ≤ 14MHzClock Config → ADC Prescaler /672→12MHz。两个 ADC 都受此限。上电必校准HAL_ADCEx_Calibration_Start()每个用到的 ADC 都要。采样时间高阻源选长239.5 Cycles提精度要速度才选短。3.2 单 ADC 多通道 DMA原文档用的测各直流轨CubeMXADC1 → ScanEnableContinuousEnableNumber Of ConversionN逐个 Rank 配 Channel Sampling TimeDMA Settings → Add → DMA1ModeCircularData WidthHalf Word。常用函数 日常用法/* —— 启动一次性开始后台循环刷新数组 —— */ HAL_ADCEx_Calibration_Start(hadc1); HAL_ADC_Start_DMA(hadc1, (uint32_t*)adc_raw, N); // N通道数×过采样 /* —— 使用随时直接读数组不用再 Start/Stop —— */ uint16_t raw adc_raw[R_VIN]; // 取某通道 /* 过采样均值见原文档 adc_avg() */ /* —— 停止一般不用—— */ HAL_ADC_Stop_DMA(hadc1);不带 DMA 的轮询多通道要用HAL_ADC_ConfigChannel()每次重配 Rank1 才能切通道很容易忘→读的全是同一路。多通道一律上 DMA。3.3 双 ADC 同步 DMA纯线圈效率用本文重点CubeMX启用ADC1 和 ADC2Clock Config 里 ADC Prescaler /6。ADC1 →Mode 选Regular simultaneous mode only选中后 ADC2 自动变从机由 ADC1 触发同步。ADC1 规则序列Rank1Vtx、Rank2VrxADC2 规则序列Rank1Itx、Rank2Irx两 ADC 转换次数必须相同。各通道 Sampling Time 选短(如 1.5 或 7.5 Cycles)以提采样率。ADC1ContinuousEnable。DMA 挂在 ADC1→ DMA1ModeCircularData WidthWord(32位)。 同步模式下 ADC1 的数据寄存器高 16 位ADC2 结果、低 16 位ADC1 结果DMA 一次搬 32 位。同步后的数据排布对应改动 5 的缓冲一次转换一个32位字 低16电压(ADC1) 高16电流(ADC2) coil_buf[0] (Vtx | Itx16) ← ADC1/2 的 Rank1同刻 coil_buf[1] (Vrx | Irx16) ← Rank2同刻 coil_buf[2] (Vtx | Itx16) ← 下一轮… → 偶数下标TX对奇数下标RX对常用函数 日常用法/* —— 启动双ADC同步DMA见 Coil_Sampling_Start—— */ HAL_ADCEx_Calibration_Start(hadc1); HAL_ADCEx_Calibration_Start(hadc2); HAL_ADCEx_MultiModeStart_DMA(hadc1, (uint32_t*)coil_buf, 2*COIL_SETS); /* 之后 coil_buf 后台循环刷新Coil_Power() 直接算 */ /* —— 停止 —— */ HAL_ADCEx_MultiModeStop_DMA(hadc1);读缓冲和 DMA 写缓冲有并发要更严谨就用半满/全满回调做乒乓原文档任务2那套ConvHalfCplt/ConvCplt标志处理前半时 DMA 写后半不会读到脏数据。3.4 定时器触发 ADC要精确采样率时连续模式采样率不精确、和 PWM 不同步。要精确就让TIM 触发 ADCCubeMX → ADC1 External Trigger Conversion Source 选某 TIM 的 TRGOTIM 配定时溢出→TRGOUpdate。这样每个定时点采一次速率精确、可与 PWM 对齐。3.5 ADC 常用函数速查函数用途HAL_ADCEx_Calibration_Start(hadc)F1 开机必调校准HAL_ADC_Start / Stop轮询启停HAL_ADC_PollForConversion(hadc,to)等转换完成HAL_ADC_GetValue(hadc)取结果HAL_ADC_Start_DMA / Stop_DMA单ADC DMA 连采HAL_ADCEx_MultiModeStart_DMA / Stop_DMA双ADC同步 DMAHAL_ADC_ConfigChannel(hadc,cfg)重配某 Rank 通道HAL_ADC_ConvCpltCallback/ConvHalfCpltCallbackDMA 全满/半满回调四、PWM 详细配置手册4.1 通用公式频率f TIM_CLK / ((PSC1)(ARR1))PSC0 →ARR 72e6/f − 1。占空比Duty CCR/(ARR1)。死区DTG round(死区ns / 13.89ns)72MHz, CKD1第一区间 DTG 0~127500ns→36。4.2 普通多通道 PWM一个定时器 4 路无互补CubeMXTIM3 → Channel1~4 PWM Generation CHx设 PSC/ARR各通道 Pulse。HAL_TIM_PWM_Start(htim3, TIM_CHANNEL_1); // 4 路各启一次 HAL_TIM_PWM_Start(htim3, TIM_CHANNEL_2); HAL_TIM_PWM_Start(htim3, TIM_CHANNEL_3); HAL_TIM_PWM_Start(htim3, TIM_CHANNEL_4); __HAL_TIM_SET_COMPARE(htim3, TIM_CHANNEL_1, ccr); // 改占空比 __HAL_TIM_SET_AUTORELOAD(htim3, arr); // 改频率(4路共用)4.3 一个全桥 4 路互补带死区TIM1原文档用的CubeMXTIM1 → CH1PWM Generation CH1 CH1NCH2PWM Generation CH2 CH2NCH2 的 Mode 选 PWM mode 2使 B 臂反相Break And Dead Time设 Dead TimeCounter Settings →auto-reload preloadEnableAutomatic Output StateEnable。/* 死区(见原文档 PWM_Start 用 HAL_TIMEx_ConfigBreakDeadTime) */ HAL_TIM_PWM_Start (htim1, TIM_CHANNEL_1); // A臂高侧 HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_1); // A臂低侧(互补,注意PWMN) HAL_TIM_PWM_Start (htim1, TIM_CHANNEL_2); // B臂高侧 HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_2); // B臂低侧4.4 两个全桥 8 路互补带死区TIM1 TIM8 主从同步★两个全桥需要8 个 PWM 两组{CHx/CHxN}互补带死区。F1 上带互补死区的高级定时器只有TIM1 和 TIM8TIM8 仅大容量型号有如 F103xC/D/EC8T6 等中容量没有 TIM8见 4.5 备选。CubeMX桥1 → TIM1CH1/CH1N、CH2/CH2NCH2PWM2 反相设死区。桥2 → TIM8CH1/CH1N、CH2/CH2NCH2PWM2设死区。两桥同步关键否则两桥相位漂移TIM1主→ Trigger Output(TRGO) 选Enable或Update。TIM8从→ Slave Mode Trigger ModeTrigger Source ITR0ITR0 内部连到 TIM1。两定时器 PSC/ARR 必须完全相同靠同一时钟锁相。/* 两桥的死区各自设一次 */ HAL_TIMEx_ConfigBreakDeadTime(htim1, bd1); // bd1.DeadTimedeadtime_dtg(DEADTIME_NS) HAL_TIMEx_ConfigBreakDeadTime(htim8, bd2); // bd2.DeadTime 同上(两桥可用同一死区宏) /* 先起从机(等主触发)再起主机 —— 主机CEN一置位就触发从机两桥同起 */ HAL_TIM_PWM_Start (htim8, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(htim8, TIM_CHANNEL_1); HAL_TIM_PWM_Start (htim8, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(htim8, TIM_CHANNEL_2); HAL_TIM_PWM_Start (htim1, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start (htim1, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(htim1, TIM_CHANNEL_2); /* 扫频/调频两桥一起改保持同频 */ void PWM2_SetFreq(uint32_t hz){ uint32_t arr 72000000UL/hz - 1; __HAL_TIM_SET_AUTORELOAD(htim1, arr); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, (arr1)/2); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_2, (arr1)/2); __HAL_TIM_SET_AUTORELOAD(htim8, arr); __HAL_TIM_SET_COMPARE(htim8, TIM_CHANNEL_1, (arr1)/2); __HAL_TIM_SET_COMPARE(htim8, TIM_CHANNEL_2, (arr1)/2); }想让桥2相对桥1移相(移相全桥调功)让 TIM8 的 CCR 相对 TIM1 偏移或用从机的计数器偏置。基础赛用同相 50% 方波即可移相是进阶。4.5 没有 TIM8 时的备选中容量 F103方案A推荐用带死区的栅极驱动 IC如半桥驱动器自带死区MCU 每臂只出 1 路普通 PWM死区交给硬件。这样一个 TIM1 的 CH1~CH4 就能出 4 路给两个全桥每桥 2 路互补和死区由驱动 IC 生成。方案B换大容量芯片(带 TIM8)。4.6 PWM 常用函数速查函数用途HAL_TIM_PWM_Start / Stop(htim,CH)启停某通道主输出HAL_TIMEx_PWMN_Start / Stop(htim,CH)启停互补 N 输出__HAL_TIM_SET_COMPARE(htim,CH,ccr)改占空比(改 CCR)__HAL_TIM_SET_AUTORELOAD(htim,arr)改频率(改 ARR配 preload)HAL_TIMEx_ConfigBreakDeadTime(htim,bd)配死区/刹车__HAL_TIM_MOE_ENABLE / DISABLE(htim)主输出总开关一键切断保护用__HAL_TIM_GET_COUNTER(htim)读计数器4.7 PWM 现场坑互补输出忘了PWMN_Start→ 只有高侧动桥不工作。全桥 B 臂没设 PWM mode 2 → 两臂同相不换流。改频率没开auto-reload preload→ 中途毛刺冲击 MOS。两桥没做主从同步 → 相位漂移功率不稳。死区太小 → 上下管直通烧管从 500ns 起示波器确认不重叠。保护动作用__HAL_TIM_MOE_DISABLE最快切断所有输出。