本程序主要还是要实现的是数字电源的控制,主要使用到的是epwm+compare+CLA+Sci fifo,控制的方式是电压电流双环的模式,将外环电压环的运行放在定时器中执行(执行的频率是65kHz),内环电流环的执行频率是 185kHz,为我将其放在了CLA中执行。
电源的过流方式是是使用OST模式,使用DAC级联compare级联epwm模式进行pwm的关断。使用两组epwm波产生两组互补带死去的PWM波来进行逆变的驱动。使用一组pwm波进行Buck开关管的控制。OST的触发挂在Buck的这组PWM波上
通讯上使用SCI+FIFO的方式进行通讯。将需要发送的数据装填到FIFO中,达到一定的容量之后再进行数据的发送,这样可以避免频繁的进入到发送中断当中去。使用modbus 的通信方式,便于程序后期的上板调试。
1. 定时器和CLA部分
使用C2000微控制器CLA(控制律加速器)配置界面。
说明:
CLA模块核心功能
多任务并行调度
8个独立任务(Task 1-8)可同时启用,每个任务支持:
专用中断向量(如CLA_MVECT_1对应Task1)。
独立触发源(如ADCB1触发Task1)。
优先级配置(通过中断向量号隐式定义)。
硬件加速控制算法
实时计算:CLA作为协处理器,独立于主CPU运行PID、FOC等算法。
低延迟响应:中断触发到任务执行的延迟<100ns(典型值)。
外设直接交互
数据输入:直接从ADC(如ADCB1)获取采样数据,无需CPU介入。
输出控制:通过PWM/XBAR模块直接驱动功率器件。
配置界面关键操作
全局参数设置
时钟分频:调节CLA内核时钟(与主CPU时钟同步/异步)。
内存保护:配置CLA代码/数据区的访问权限。
任务级配置
中断绑定:为每个任务选择触发源(如EPWM、ADC、GPIO)。
代码链接:指定任务函数入口(如Cla1Task1对应汇编/C函数)。
资源管理
寄存器映射:查看CLA专用寄存器(如MR0-MR3)的分配状态。
共享内存:配置CLA与主CPU的数据交换缓冲区。
CLA sysconfig代码配置
// Loop1控制任务定义在共享文件中,供CPU和CLA共同调用,避免代码重复 static inline void loop1_task(void) { // GCK注释:使用过采样(4次采样取平均)降低ADC噪声 sense_data.loop1 = (ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER0) + ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER1) + ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER2) + ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER3)) >> 2; // 右移2位等效于除以4 // 仅在软件标志位完成且模式开关为1时执行控制(安全条件判断) if ((soft_Flag_Finish == 1) && (MODE_SWITCH == 1)) { // GCK注释:使用位置式PID计算电流环输出,内部已做输出限幅 // 输入:PID结构体指针、电流参考值、实际电流值(0.04 * 3.3为电压系数,4096为ADC满量程) control_out_data.loop1 = Dcl_runPI_L4(&pi_loop1, ref_data.loop1, (0.04f * 3.30f * (sense_data.loop1 / 4096.0f))); // 计算PWM占空比(1.0f为比例系数,可根据硬件调整) duty_loop1 = 1.0f * control_out_data.loop1; // 将控制输出存入缓冲区(用于后续分析或调试) duty_buffer[cnt] = control_out_data.loop1; cnt++; // 每3次中断计算一次移动平均值(进一步平滑输出) if (cnt == 3) { cnt = 0; // 可在此添加平均值计算逻辑(如:duty_avg = (duty_buffer[0]+duty_buffer[1]+duty_buffer[2])/3) } } }
求和与PWM占空比更新逻辑代码
// ==== 高效求均值与饱和处理 ==== // 1. 计算3次中断的占空比总和(避免多次除法提升效率) sum = duty_buffer[0] + duty_buffer[1] + duty_buffer[2]; // 2. 使用乘法替代除法求均值(0.333f ≈ 1/3,编译器可能优化为快速浮点乘) average_duty = sum * 0.333f; // 3. 上下限饱和保护(防止PWM占空比超限) average_duty = (average_duty > 0.9f) ? 0.8f : average_duty; // 超上限时强制降为80% average_duty = (average_duty < 0.1f) ? 0.1f : average_duty; // 超下限时锁定10% // ==== PWM占空比更新 ==== // 4. 更新EPWM1的COMPA寄存器(互补PWM场景) // 公式:(1.0f - duty) * PERIOD 用于生成互补对称波形(如H桥驱动) EPWM_setCounterCompareValue( EPWM1_BASE, EPWM_COUNTER_COMPARE_A, (uint16_t)((1.0f - average_duty) * EPWM1_PERIOD) // 硬件自动重装载 ); // 5. 更新BUCK变换器的PWM占空比(非互补模式) // 直接写入占空比(占空比 = 高电平时间 / 周期) EPWM_setCounterCompareValue( BUCK_BASE, EPWM_COUNTER_COMPARE_A, (uint16_t)(average_duty * BUCK_PERIOD) // 如BUCK_PERIOD=1000,duty=0.5 → 500 );
CLA的中断函数
CLA的触发源为ADCB1定时器,我的ADCB1采样的是Buck上的电流。
ADC_BUCK_VoI 和 ADC_PFC_VoI_In 的配置信息
多通道高优先级采样
双通道独立配置,ADC_BUCK_VoI:用于BUCK变换器输出电压采样。ADC_PFC_VoI_In:用于PFC(功率因数校正)输入电压/电流采样。
高优先级模式(High Priority Mode SOCs),确保关键信号的采样实时性,抢占普通ADC任务资源。
硬件触发与中断协同
触发源灵活配置,通过 Start of Conversion Configurations 绑定PWM或GPIO触发信号。
中断驱动处理,使能 ADC Interrupt 2(INT_ADC_BUCK_VoI2),触发后执行 loop2ISR 服务程序。脉冲模式(Pulse Mode):中断仅触发一次,需重新使能(降低CPU负载)。
电压采样ADC中断的配置
ADC中断服务程序
interrupt void loop2ISR(void) { // 1. 测试IO(调试用,可注释掉) GPIO_writePin(myGPIO0, 1); // 触发示波器捕获中断时刻 // 2. 读取4次ADC过采样结果并求平均(降噪) sense_data.loop2 = (ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0) + ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER1) + ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER2) + ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER3)) >> 2; // 右移2位等效于除以4 // 3. 电压值计算(两种等效方式) // 方式1:分步计算(清晰但稍慢) control_out_data.voltage = (float)(((sense_data.loop2 / 4096.0f) * 3.3f) * 0.801f) * 235000.0f; // 方式2:合并系数(快速版,0.1893f = 3.3 * 0.801 * 235000/4096) control_out_data.voltage = (float)(sense_data.loop2 * 0.1893f); // 4. 软启动完成且模式开关为恒压模式时执行控制 if ((soft_Flag_Finish == 1) && (MODE_SWITCH == 1)) { // 外环电压控制(Type3控制器输出) control_out_data.loop2 = type3_control(ref_data.loop2, control_out_data.voltage); // 5. 电流环参考值计算(补偿-0.15V并限流) // 优化:用整数运算避免浮点耗时(3us -> 0.5us) ref_data.loop1 = (100 * control_out_data.loop2 - 15) * 0.01f; // 等效于 (loop2 - 0.15) // 注:电流环限流已在type3_control()内部实现,此处无需重复 } // 6. 清除中断标志(根据硬件手册要求) ADC_clearInterrupt(ADCARESULT_BASE, ADC_INT_NUMBER2); GPIO_writePin(myGPIO0, 0); // 调试IO复位 }
// 空行或注释行(图中未显示具体内容) // 内环电流参考值(ref_data.loop1)的限幅处理 // - 上限保护:超过40.0时钳位到60.0(防止过流损坏硬件) // - 下限保护:低于1.0时钳位到1.0(维持最小工作电流) ref_data.loop1 = (ref_data.loop1 > 40.0f) ? 60.0f : ref_data.loop1; // 上限60.0A ref_data.loop1 = (ref_data.loop1 < 1.0f) ? 1.0f : ref_data.loop1; // 下限1.0A // 调试GPIO复位(标记中断结束) GPIO_writePin(myGPIO0, 0); // 拉低GPIO电平,用于示波器测量中断执行时间 // 清除ADC中断标志位 ADC_clearInterruptStatus(ADC_BUCK_VoL_BASE, ADC_INT_NUMBER1); // 清除ADC模块中断标志 // 清除PIE中断组应答标志 Interrupt_clearACKGroup(INT_ADC_BUCK_VoL_2_INTERRUPT_ACK_GROUP); // 允许后续中断触发 // 重新使能全局中断(若之前有禁用) EINT; // 等效于 __enable_irq()(恢复中断响应)
电压采样ADC中断函数
这里使用ADCB的中断来进行电压环type3控制器函数的运算。
CLA执行时序和ADC中断执行时序逻辑分析仪测试
上图中,第一个通道是CLA执行的时序,第二个通道是ADC中断执行的时序,基本上CLA执行三次,ADC中断执行一次,这样可以保证我内环电流环的运行频率比外环电压环的频率快。