有线学习笔记(A)

发布时间:2026/7/5 8:57:11
有线学习笔记(A) ## 5. 任务四固定频率最佳位姿换负载测功率/效率**目标**保持任务2频率、任务3最佳位姿换不同充电笔换负载算各负载下功率与效率并打印。**原理**负载变化改变 RX 反射阻抗与工作点效率随负载变。此题看不同负载下系统表现。cvoid Task4_Loop(uint8_t pen){float pin,pout,eff; Measure(pin,pout,eff);printf([T4 load-test] Pin%.2fW Pout%.2fW eff%.1f%% ← 换笔记录此组数据 pen%d\r\n,pin, pout, eff*100, pen);}---## 6. 附加任务欠压 / 过压 / 过流保护与任意任务共存Protection_Check() 已在 1.8 给出主循环里每圈调用命中即 PWM_Stop() 切断输出并闪灯报警见总代码。---## 7. 总代码 main.c宏切换任务 只贴 USER CODE 区应填的内容MX_xxx_Init()、句柄 htim1/hadc1/huart1/hi2c1/hspi1 由 CubeMX 生成。把上面各函数放进 main.c 的 USER CODE BEGIN 4 区。c/* USER CODE BEGIN Includes */#include stdio.h#include math.h/* USER CODE END Includes *//* 全局宏见第0节此处照抄 */#define TASK_NUM 1#define ENABLE_PROTECTION 1#define BRIDGE_HALF 0#define BRIDGE_FULL 1#define BRIDGE_TYPE BRIDGE_FULL#define DEADTIME_NS 500#define PWM_INIT_HZ 150000UL#define TIM_CLK_HZ 72000000UL#define SWEEP_FMAX 205000UL#define SWEEP_FMIN 110000UL#define SWEEP_STEP 1000UL#define SWEEP_SETTLE_MS 3#define BEST_FREQ_HZ 145000UL#define HALL_DIGITAL 0#define HALL_LINEAR 1#define HALL_TYPE HALL_DIGITAL#define HALL_ACTIVE GPIO_PIN_RESET#define HALL_ON_V 2.0f#define HALL_OFF_V 1.6f#define EFF_RECT_OVER_IN 1#define EFF_VOUT_OVER_IN 2#define EFF_BAT_OVER_IN 3#define EFFICIENCY_CASE EFF_RECT_OVER_IN#define UV_VIN 4.5f#define OV_VIN 6.5f#define OV_VRECT 6.0f#define OC_IIN 2.0f#define VREF 3.30f#define ADC_FS 4096.0f#define VRECT_OK_V 3.0f#define P_L1 0.5f#define P_L2 1.0f#define P_L3 1.5f#define P_L4 2.0f#define VIN_DIV 11.0f#define IIN_RS 0.05f#define IIN_G 20.0f#define VRECT_DIV 3.0f#define IRECT_RS 0.05f#define IRECT_G 20.0f#define VOUT_DIV 2.0f#define IOUT_RS 0.05f#define IOUT_G 20.0f#define VBAT_DIV 2.0f#define ICHG_RS 0.05f#define ICHG_G 20.0f/* USER CODE BEGIN PV */#if HALL_TYPEHALL_LINEAR#define ADC_NCH 9#define R_HALL 8#else#define ADC_NCH 8#endif#define R_VIN 0#define R_IIN 1#define R_VRECT 2#define R_IRECT 3#define R_VOUT 4#define R_IOUT 5#define R_VBAT 6#define R_ICHG 7#define ADC_OVS 16uint16_t adc_raw[ADC_NCH*ADC_OVS];/* USER CODE END PV *//* USER CODE BEGIN 4 */int __io_putchar(int ch){ HAL_UART_Transmit(huart1,(uint8_t*)ch,1,10); return ch; }static uint8_t deadtime_dtg(uint32_t ns){float step 1000.0f/(TIM_CLK_HZ/1000000.0f);uint32_t d(uint32_t)(ns/step0.5f); if(d127)d127; return (uint8_t)d;}void PWM_SetFreq(uint32_t hz){uint32_t arr(uint32_t)(TIM_CLK_HZ/hz)-1;__HAL_TIM_SET_AUTORELOAD(htim1,arr);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,(arr1)/2);#if BRIDGE_TYPEBRIDGE_FULL__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,(arr1)/2);#endif}void PWM_Start(void){TIM_BreakDeadTimeConfigTypeDef bd{0};bd.OffStateRunModeTIM_OSSR_DISABLE; bd.OffStateIDLEModeTIM_OSSI_DISABLE;bd.LockLevelTIM_LOCKLEVEL_OFF; bd.DeadTimedeadtime_dtg(DEADTIME_NS);bd.BreakStateTIM_BREAK_DISABLE; bd.BreakPolarityTIM_BREAKPOLARITY_HIGH;bd.AutomaticOutputTIM_AUTOMATICOUTPUT_ENABLE;HAL_TIMEx_ConfigBreakDeadTime(htim1,bd);PWM_SetFreq(PWM_INIT_HZ);HAL_TIM_PWM_Start(htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(htim1,TIM_CHANNEL_1);#if BRIDGE_TYPEBRIDGE_FULLHAL_TIM_PWM_Start(htim1,TIM_CHANNEL_2);HAL_TIMEx_PWMN_Start(htim1,TIM_CHANNEL_2);#endif}void PWM_Stop(void){ __HAL_TIM_MOE_DISABLE(htim1); }void ADC_StartAll(void){HAL_ADCEx_Calibration_Start(hadc1);HAL_ADC_Start_DMA(hadc1,(uint32_t*)adc_raw,ADC_NCH*ADC_OVS);}static float adc_avg(uint8_t r){ uint32_t s0; for(uint8_t k0;kADC_OVS;k) sadc_raw[rk*ADC_NCH]; return (float)s/ADC_OVS; }static float rank_volt(uint8_t r,float div){ return adc_avg(r)*(VREF/ADC_FS)*div; }static float shunt_amp(uint8_t r,float rs,float g){ return adc_avg(r)*(VREF/ADC_FS)/g/rs; }static float Power_In(void){ return rank_volt(R_VIN,VIN_DIV)*shunt_amp(R_IIN,IIN_RS,IIN_G); }static float Power_Out(void){#if EFFICIENCY_CASEEFF_RECT_OVER_INreturn rank_volt(R_VRECT,VRECT_DIV)*shunt_amp(R_IRECT,IRECT_RS,IRECT_G);#elif EFFICIENCY_CASEEFF_VOUT_OVER_INreturn rank_volt(R_VOUT,VOUT_DIV)*shunt_amp(R_IOUT,IOUT_RS,IOUT_G);#elif EFFICIENCY_CASEEFF_BAT_OVER_INreturn rank_volt(R_VBAT,VBAT_DIV)*shunt_amp(R_ICHG,ICHG_RS,ICHG_G);#endif}void Measure(float *pin,float *pout,float *eff){*pinPower_In(); *poutPower_Out(); *eff(*pin0.001f)?(*pout/ *pin):0.0f;}uint8_t Hall_PenOK(void){#if HALL_TYPEHALL_DIGITALstatic uint8_t st0,c0;uint8_t now(HAL_GPIO_ReadPin(HALL_GPIO_Port,HALL_Pin)HALL_ACTIVE);if(now!st){ if(c5){stnow;c0;} } else c0; return st;#elsestatic uint8_t p0; float vrank_volt(R_HALL,1.0f);if(!pvHALL_ON_V)p1; if(pvHALL_OFF_V)p0; return p;#endif}static void LED_SetBar(uint8_t n){HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,n1);HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,n2);HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,n3);HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,n4);}void LED_Update(uint8_t pen,float pout,uint8_t fault){if(fault){ uint8_t b(HAL_GetTick()/200)1; LED_SetBar(b?4:0); return; }if(!pen){ LED_SetBar(0); return; }uint8_t npoutP_L4?4:poutP_L3?3:poutP_L2?2:poutP_L1?1:0; LED_SetBar(n);}uint8_t Protection_Check(void){float vinrank_volt(R_VIN,VIN_DIV), vrrank_volt(R_VRECT,VRECT_DIV), iinshunt_amp(R_IIN,IIN_RS,IIN_G);if(vinUV_VIN)return 1; if(vinOV_VIN)return 2; if(vrOV_VRECT)return 3; if(iinOC_IIN)return 4; return 0;}#if TASK_NUM2uint32_t Task2_SweepBestFreq(void){float bestEff0; uint32_t bestFPWM_INIT_HZ;for(uint32_t fSWEEP_FMAX;fSWEEP_FMIN;f-SWEEP_STEP){PWM_SetFreq(f); HAL_Delay(SWEEP_SETTLE_MS);float pin,pout,eff; Measure(pin,pout,eff);printf([T2] f%lukHz Pin%.2f Pout%.2f eff%.1f%%\r\n,f/1000,pin,pout,eff*100);if(effbestEffpin0.1f){bestEffeff;bestFf;}#if ENABLE_PROTECTIONif(Protection_Check()){PWM_Stop();break;}#endif}PWM_SetFreq(bestF);printf([T2] BEST f%lukHz eff%.1f%% \r\n,bestF/1000,bestEff*100);return bestF;}#endif/* USER CODE END 4 */int main(void){HAL_Init(); SystemClock_Config();MX_GPIO_Init(); MX_DMA_Init(); MX_ADC1_Init(); MX_TIM1_Init();MX_USART1_UART_Init(); MX_I2C1_Init(); MX_SPI1_Init();/* USER CODE BEGIN 2 */setvbuf(stdout,NULL,_IONBF,0);ADC_StartAll();printf( WPT Relay boot | TASK%d | EFF_CASE%d | %s bridge | DT%dns \r\n,TASK_NUM, EFFICIENCY_CASE,(BRIDGE_TYPEBRIDGE_FULL)?FULL:HALF, DEADTIME_NS);PWM_Start();#if (TASK_NUM3)||(TASK_NUM4)PWM_SetFreq(BEST_FREQ_HZ); /* 任务3/4 直接锁任务2最佳频率 */#endif/* USER CODE END 2 */while(1){/* ---- USER CODE BEGIN 3 ---- */uint8_t pen Hall_PenOK();float pin,pout,eff; Measure(pin,pout,eff);uint8_t fault0;#if ENABLE_PROTECTIONfault Protection_Check();if(fault){ PWM_Stop(); printf(!! PROTECT trip code%d (UV/OV/OVR/OC)\r\n, fault); }#endif#if TASK_NUM1{ /* 任务1出口检测器件判断 */float vrectrank_volt(R_VRECT,VRECT_DIV);if(vrectVRECT_OK_V)printf([T1] RUN VRECT%.2fV Pin%.2f Pout%.2f pen%d\r\n,vrect,pin,pout,pen);elseprintf([T1] NO POWER VRECT%.2fV 查桥/死区/线圈/整流 pen%d\r\n,vrect,pen);}#elif TASK_NUM2{ /* 任务2只扫频一次之后保持最佳频率 */static uint8_t done0;if(!done !fault){ Task2_SweepBestFreq(); done1; }printf([T2] hold-best Pin%.2f Pout%.2f eff%.1f%% pen%d\r\n,pin,pout,eff*100,pen);}#elif TASK_NUM3printf([T3 coil-tune] Pin%.2f Pout%.2f eff%.1f%% ←调线圈 pen%d\r\n,pin,pout,eff*100,pen);#elif TASK_NUM4printf([T4 load-test] Pin%.2f Pout%.2f eff%.1f%% ←换笔记录 pen%d\r\n,pin,pout,eff*100,pen);#endifLED_Update(pen, pout, fault); /* 4灯故障闪/离位灭/在位按功率1~4颗 */HAL_Delay(200);/* ---- USER CODE END 3 ---- */}}---## 附录 A交流点 RMS仅当检测点确为交流线圈侧时用 F1 采不动 150kHz需双 ADC 同步 定时器触发 DMA 批采见之前的采样方案。DC 点不要用这个。c/* 对同步采样缓冲(低16V,高16I)算 Vrms/Irms/有功P先减均值去直流 */void RMS_FromBuf(const uint32_t *buf, uint16_t n,float divV, float rs, float g,float *Vrms, float *Irms, float *P){uint32_t sv0,si0;for(uint16_t k0;kn;k){ sv(buf[k]0xFFFF); si((buf[k]16)0xFFFF); }float vm(float)sv/n, im(float)si/n;double aV0,aI0,aP0;for(uint16_t k0;kn;k){float v((float)(buf[k]0xFFFF)-vm)*(VREF/ADC_FS)*divV;float i((float)((buf[k]16)0xFFFF)-im)*(VREF/ADC_FS)/g/rs;aV(double)v*v; aI(double)i*i; aP(double)v*i; /* double防溢出 */}*Vrmssqrtf(aV/n); *Irmssqrtf(aI/n); *P(float)(aP/n); /* P自带功率因数 */}---## 附录 B现场踩坑速记1. **全桥 B 臂不反相** → 两臂同相不换流没能量。CubeMX 里 CH2 必须设 **PWM mode 2**。2. **死区忘设/太小** → 上下管直通烧 MOS。DEADTIME_NS 从 500ns 起示波器确认上下管驱动不重叠。3. **改频率出毛刺脉冲** → TIM1 Counter Settings 里 **auto-reload preload Enable**。4. **ADC 乱跳/不准** → ADC 时钟没 /6超 14MHz、没校准、采样时间太短。5. **扫频扫过谐振点** → 一定 **高频→低频**SWEEP_FMIN 别低于谐振容性区会炸管。6. **功率算成视在功率** → 交流点必须 mean(v·i)直流点用 Vdc×Idc。别用 Vrms×Irms 当有功。7. **printf 无输出** → CubeIDE 重写 __io_putchar不是 fputc/MicroLIB并 setvbuf 关缓冲。8. **保护误触发** → 阈值留裕量对采样值做均值滤波避免开关噪声瞬时误判。