📄 control.zip.c
字号:
Init_IC_and_CN();
InitMCPWM();
for(;;)
{
if ((Switch_2) && (!Flags.MotorRunning)) //如果而者都不为0,MotorRunning=1;
{
while(!Switch_2);
RunMotor(); // 如果电机停止+按扭电机运转
}
else if ((Switch_2) && (Flags.MotorRunning))
{
while(!Switch_2);
StopMotor(); //如果电机运转+按扭电机停止
}
}
return 0;
}
//*********************************************//
// 上电充电程序
//**********************************************//
void ChargeBootstraps(void) //先充电10MS函数
{
unsigned int i;
OVDCON = 0x0015; // 打开低端三桥臂
for (i = 0; i < 30; i++) // 10豪秒研时程序20MIPS
;
OVDCON = 0x0000; //关6个IGBT
return;
}
/*********************************************************************
////当第一次去运行电机和电机先前是停止的,将充,将初始化应用变量,并势能所有的中断服务程序
*********************************************************************/
void RunMotor(void) //电机启动运行函数
{
ChargeBootstraps();//调用充电函数
//////////////初始化变量////////////////////////
ControlDifference[0] = 0; // K的误差
ControlDifference[1] = 0; // K-1的误差
ControlDifference[2] = 0; // k-2的误差
PIDCoefficients[0] = Kp + Ki + Kd;
PIDCoefficients[1] = -(Kp + 2*Kd);
PIDCoefficients[2] = Kd;
TMR1 = 0; // 清零速度调节器用T1。
TMR3 = 0; //清零速度控制T3
ActualCapture = MAXPERIOD; // 初始化最小速度60RPM的扑捉,MAXPERIOD=31250
PastCapture = 0;
Period = MAXPERIOD;
while (IC7CONbits.ICBNE) //等待缓冲器是空的。
IC7BUF; //清空。
/////////////////////////////////////////////////////////////////////////////////////////////////
// 初始化需要的方向。
// 注意ADC没有停止.
HallValue = (unsigned int)((PORTB >> 3) & 0x0007); // 读霍儿数值
LastSector = Sector = SectorTable[HallValue]; // 初始化霍尔数据变量
if (RefSpeed > 0) //如果参考速度大于零
{
ControlOutput = 0; //是不是非要输出0呢????????????得澄清。
Current_Direction = Required_Direction = CW;//当前的方向是正转。
Speed = MINABSSPEED;
}
else
{
ControlOutput = 0;
Current_Direction = Required_Direction = CCW;
Speed = -MINABSSPEED;
}
SpeedAbsValue = MINABSSPEED;
MotorStalledCounter = 0; // 复位电机停止保护计数器//。
// 清除所有的中断标志。
IFS0bits.T1IF = 0;
IFS0bits.CNIF = 0;
IFS1bits.IC7IF = 0;
IFS1bits.IC8IF = 0;
// 势能所有的中断标志
__asm__ volatile("DISI #5");
IEC0bits.T1IE = 1;
IEC0bits.CNIE = 1;
IEC1bits.IC7IE = 1;
IEC1bits.IC8IE = 1;
Flags.MotorRunning = 1; // 电机已经开始运行。
return;
}
/*********************************************************************
// 停止程序
*********************************************************************/
void StopMotor(void)
{
OVDCON = 0x0000; // 关闭所有IGBT
/////////////////////////////
//关所有中断/////
__asm__ volatile("DISI #5");
IEC0bits.T1IE = 0; // 关T1中断
IEC0bits.CNIE = 0; // 关电平变化中断/HALLA
IEC1bits.IC7IE = 0; // 关电平捕捉中断/HALLB
IEC1bits.IC8IE = 0; // 关电平捕捉中断/HALLC
Flags.MotorRunning = 0; // 表示电机已经停止
return;
}
//********************************************************************
// 这个子程序依照转子状态信息对应的表数执行6啪换向,
//********************************************************************/
void SixStepComm(int _Sector, int _Voltage)
{
if (_Voltage >= 0)
{
// 装载相同的占空比到所有的PDC寄存器.
// 选择适当的IGBT工作。
// 通过OVDCON的数值改变MCPWM的IGBT逻辑关系。
PDC1 = PDC2 = PDC3 = (unsigned int)_Voltage / 16;
if (_Sector == -1)
OVDCON = 0x0000; // 无效的SECTOR关6个IGBT。
else
OVDCON = StateLoTable[_Sector];
}
else
{
// 装载占空比数值到3个PDC寄存器.
// 选择合适的一对IGBT工作。
// 通过OVDCON的数值改变MCPWM的IGBT逻辑关系。
PDC1 = PDC2 = PDC3 = (unsigned int)(-(_Voltage+1)) / 16;
if (_Sector == -1)
OVDCON = 0x0000; // 无效的霍儿状态关6个IGBT。
else
OVDCON = StateLoTable[(_Sector + 3) % 6];
}
return;
}
/*********************************************************************
这个功能是每次电机不能产生电平变化中断,这就意味着电机运行的太慢
或者是堵转,如是堵转电机就停止,但如果只是太慢,这个函数是调用并基于实际
的霍尔位置和转子需要的方向强制一个换相。
*********************************************************************/
void ForceCommutation(void) //在每次更新PWM占空比之前先判断指令方向,在T1中断里面调用,用语堵转保护。
{
HallValue = (unsigned int)((PORTB >> 3) & 0x0007); // 读霍尔状态数值。
Sector = SectorTable[HallValue]; // 查表获取读霍尔对应数值(1-5)。
if (Sector != -1) //如果SECTOR是无效的就什么事情不做,见SECTOR数组。
{
// 依照方向转换相位。
if (Required_Direction == CW)
{
SixStepComm(Sector, ControlOutput);
}
else
{
SixStepComm(Sector, -(ControlOutput + 1));
}
}
return;
}
/*******************************************************************
ADC初始化程序
*********************************************************************/
void InitADC10(void) //ADC初始化程序
{
ADPCFG = 0xFFF8; // RB3, RB4, and RB5 是数字口
ADCON1 = 0x026E; // PWM开始转换无符号小数转换
ADCON2 = 0x0000;
ADCHS = 0x0002; // ADC连接到AN2
ADCON3 = 0x0003;
IFS0bits.ADIF = 0; // 清除ADC中断标志
IEC0bits.ADIE = 1; // 势能ADC中断
ADCON1bits.ADON = 1; // 开ADC
return;
}
/********************************************************************
MCPWM初始化程序
*********************************************************************/
void InitMCPWM(void)
{
TRISE = 0x0100; // 配置PWM为输出,故障A为输入
PTPER = FCY/FPWM - 1;// 根据CPU速度计算时基周期寄存器的数值
OVDCON = 0x0000; // 通过改写控制寄存器关1-4通道PWM驱动输出.
PWMCON1 = 0x0777; // 通过PWM控制寄存器势能1-3通道低端和高端输出并配置成互补输出模式
PDC1 = 0; // 通过占空比寄存器清零占空比值
PDC2 = 0; //
PDC3 = 0; //
SEVTCMP = PTPER; // 把时基周期寄存器的数赋给特殊时间比较寄存器
PWMCON2 = 0x0F00; //PWM特殊事件触发器输出后分频为1:16// 16 postscale values, for achieving 20 kHz
PTCON = 0x8000; // PWM实际开启,边缘对齐模式/
return;
}
/********************************************************************
初始化电瓶变化和输入捕捉程序配置霍而传感器输入端,一个电平变化和两个扑捉输入,IC7/RB4/HALLB
实际扑捉值是用进一步计算周期。
*********************************************************************/
void Init_IC_and_CN(void)
{
//Hall A -> CN5. Hall A 只用于换相.
//Hall B -> IC7. Hall B 用于换相和速度测量.
//Hall C -> IC8. Hall C 只用于换相.
////////// 初始化电平变化通知5/HALLA/RB3////////
TRISB |= 0x38; // 设置RB3,4,5是输入方向。
CNPU1 = 0; // 关所有的CN弱上拉。
CNEN1 = 0x20; //允许CN5电平变化中断。
IFS0bits.CNIF = 0; // 清除所有电平变化中断标志。
//////////////初始化捕捉输入7/IC7/RB4/HALLB////////
IC7CON = 0x0001; // 设置每个边缘(包括上升和下降)捕捉一次,用T3做时基。
IFS1bits.IC7IF = 0; // 清除捕捉IC7中断标志。
////////////初始化捕捉输入8/IC8/RB5/HALLC////////
IC8CON = 0x0001; // 设置每个边缘(包括上升和下降)捕捉一次,用T3做时基。
IFS1bits.IC8IF = 0; // 清除捕捉IC8中断标志。
return;
}
/********************************************************************
T1初始化程序为 1 ms ,速度控制,杜撰保护,如果惦记太慢进行强制换相,杜撰停机保护
*********************************************************************/
void InitTMR1(void)
{
T1CON = 0x0020; // 预分频是1:64
TMR1 = 0; //T1清零
PR1 = 313; //在 20 MIPS定时1ms设定T1的比较数值。
T1CONbits.TON = 1; // 开 T1
return;
}
/************************************************************************
T3初始化程序为捕捉和计算周期的实际
*************************************************************************/
void InitTMR3(void)
{
T3CON = 0x0020; //预分频是1:64
TMR3 = 0;
PR3 = 0xFFFF;
T3CONbits.TON = 1; // 开T3
return;
}
/************************************************************************
初始化用到的I/O
*************************************************************************/
void InitUserInt(void)
{
TRISC |= 0x4000; // 设置RC14为输入
// AD转换口已经在ADC初始化函数处理
PORTF = 0x0008; // RS232 初始化数值
TRISF = 0xFFF7; // F口。3 TX为232输出,其它为输入
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -