基于DSP28335写一个EPWM错误联防模块
时间: 2024-03-03 12:53:27 浏览: 180
EPWM错误联防模块的实现需要考虑以下几个方面:
1. ADC采集电流信号:首先需要将电流信号输入到DSP28335的ADC模块中进行采样,并将采样结果存储到相应的寄存器中。
2. 比较电流误差值:将ADC采集到的电流值与设定电流值进行比较,计算得到电流误差值,并将其存储到相应的寄存器中。
3. PID控制:将电流误差值传入PID控制器中进行控制,得到控制量,并将其作为EPWM模块的占空比输入,控制系统输出电流。
4. 过流保护:若电流误差值超过一定阈值,说明系统出现过流情况,此时EPWM错误联防模块将通过GPIO口向外部发送错误信号,同时停止系统输出电流。
5. 错误恢复:在过流情况消除后,EPWM错误联防模块将自动恢复系统输出电流,继续进行正常工作。
下面是一个基于DSP28335的EPWM错误联防模块的示例代码:
```
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#define PWM_PERIOD 1000 // PWM周期
#define MAX_CURRENT 5 // 最大电流值
#define KP 0.5 // PID控制器的P参数
#define KI 0.2 // PID控制器的I参数
#define KD 0.1 // PID控制器的D参数
#define THRESHOLD 0.1 // 过流保护阈值
float32 adc_result; // ADC采样结果
float32 set_current; // 设定电流值
float32 current_error; // 电流误差值
float32 last_error; // 上一时刻的电流误差值
float32 pid_out; // PID控制器输出
float32 duty_cycle; // PWM占空比
void InitEPwm(void)
{
EPwm1Regs.TBPRD = PWM_PERIOD; // PWM周期
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // up-down计数模式
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 分频系数为1
EPwm1Regs.CMPA.half.CMPA = 0; // 初始占空比为0
EPwm1Regs.AQCTLA.bit.CAU = 2; // 当计数器计数到CMPA时,PWM输出高电平
EPwm1Regs.AQCTLA.bit.CAD = 1; // 当计数器计数到CMPA时,PWM输出低电平
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能SOCA
EPwm1Regs.ETSEL.bit.SOCASEL = 2; // 计数器计数到零点时触发SOCA
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // SOCA触发一次后重新计数
EPwm1Regs.TBCTL.bit.PHSEN = 1; // 使能相位补偿
}
void InitADC(void)
{
AdcRegs.ADCTRL1.bit.ADCREFSEL = 1; // 内部基准电压
AdcRegs.ADCTRL1.bit.ADCBGPWD = 1; // 使能内部参考电压缓冲电路
AdcRegs.ADCTRL1.bit.ADCPWDN = 1; // 使能ADC模块
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0; // 只采集一个通道
AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // 选择ADCINA0通道
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // PWM触发ADC采样
AdcRegs.ADCSOC0CTL.bit.ACQPS = 14; // 采样周期为15个ADC时钟周期
AdcRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // 选择ADCINT1中断
AdcRegs.ADCINTSEL1N2.bit.INT1E = 1; // 使能ADCINT1中断
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; // 中断触发一次后自动清除
}
void InitPID(void)
{
last_error = 0;
pid_out = 0;
}
void InitGPIO(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // 将GPIO0配置为GPIO模式
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; // 配置GPIO0为输出模式
EDIS;
}
void InitSystem(void)
{
InitEPwm();
InitADC();
InitGPIO();
InitPID();
}
void CalculatePID(void)
{
current_error = set_current - adc_result; // 计算电流误差值
pid_out = KP * current_error + KI * (current_error + last_error) + KD * (current_error - last_error); // PID控制器输出
last_error = current_error; // 保存当前误差值
}
void SetDutyCycle(void)
{
if (pid_out > 1) pid_out = 1; // 控制占空比在0~1之间
if (pid_out < 0) pid_out = 0;
duty_cycle = pid_out * PWM_PERIOD; // 计算PWM占空比
EPwm1Regs.CMPA.half.CMPA = (Uint16)duty_cycle; // 设置PWM占空比
}
void CheckOverCurrent(void)
{
if (current_error > THRESHOLD) { // 电流误差值超过阈值,触发过流保护
EPwm1Regs.AQCTLA.bit.CAU = 1; // 停止输出PWM信号
GpioDataRegs.GPASET.bit.GPIO0 = 1; // 设置GPIO0输出高电平
}
else {
EPwm1Regs.AQCTLA.bit.CAU = 2; // 恢复输出PWM信号
GpioDataRegs.GPACLEAR.bit.GPIO0 = 1; // 设置GPIO0输出低电平
}
}
__interrupt void ADC_ISR(void)
{
adc_result = AdcResult.ADCRESULT0 * 3.3 / 4096; // 计算ADC采样结果
CalculatePID();
SetDutyCycle();
CheckOverCurrent();
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // 清除ADC中断标志位
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 清除PIE中断标志位
}
int main(void)
{
InitSysCtrl();
InitPieCtrl();
IER = M_INT1;
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
InitSystem();
EINT;
ERTM;
while(1);
return 0;
}
```
以上代码仅为示例,具体实现过程可能会因具体应用场景而有所不同。在实际应用中,还需要根据具体需求进行相应的调试和优化。
阅读全文
相关推荐
















