⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 control.zip.c

📁 该代码是完整的BLDC正旋波驱动解决办法,电机可以正常运行
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -