www.pudn.com > DC_SpeedCtrl.rar > main.c


//======================================================== 
//	The information contained herein is the exclusive property of 
//	Sunnnorth Technology Co. And shall not be distributed, reproduced, 
//	or disclosed in whole in part without prior written permission. 
//	(C) COPYRIGHT 2003 SUNNORTH TECHNOLOGY CO. 
//	ALL RIGHTS RESERVED 
//	The entire notice above must be reproduced on all authorized copies. 
//======================================================== 
 
//======================================================== 
//	工程名称:	DC_SpeedCtrl 
//	功能描述:	直流电机速度测量与调节 
//	涉及的库:	CMacro1016.lib 
//	组成文件:	main.c 
//              isr.asm, Dig.asm, Key.asm, DCMotor.asm 
//              Dig.inc, Key.inc, DCMotor.inc, SPCE061A.inc 
//              Dig.h,Key.h, DCMotor.h, SPCE061A.h 
//	硬件连接:	61板IOB高8位与电机模组J1连接 
//				61板IOA高8位与电机模组J2连接 
//				61板IOB低8位与电机模组J3连接 
//	维护记录:	2005-12-2	v1.0 
//======================================================== 
 
//======================================================== 
//	文件名称:	main.c 
//	功能描述:	数码管显示 
//	维护记录:	2005-09-12	v1.0 
//======================================================== 
#include "SPCE061A.h" 
#include "DCMotor.h" 
#include "Dig.h" 
#include "Key.h" 
 
#define SPEED_MAX	60									// 最高设定速度 
#define	SPEED_MIN	30									// 最低设定速度 
#define SPEED_STEP	2									// 速度设定步进值 
 
#define CP	8											// 比例常数 Proportional Const 
#define CI	3											// 积分常数 Integral Const 
#define	CD	1											// 微分常数 Derivative Const 
 
unsigned int g_Direction, g_Speed;						// 全局变量,保存设定的转动方向和速度 
 
 
//======================================================================== 
//	语法格式:	void System_Init(void) 
//	实现功能:	系统初始化(时钟、变量等) 
//	参数:		无 
//	返回值:	无 
//======================================================================== 
void System_Init(void) 
{ 
	*P_SystemClock = C_Fosc_49M|C_StrongMode;			// 系统时钟 
 
	DCMotor_Init(); 
	Key_Init(); 
	DIG_Init(); 
 
	g_Direction = 1;									// 初始设置为正转 
	g_Speed = 40; 
} 
 
//======================================================================== 
//	语法格式:	void DispNum(unsigned int Num) 
//	实现功能:	在4位数码管上显示整数 
//	参数:		Num - 要显示的数值,范围0~9999 
//	返回值:	无 
//======================================================================== 
const unsigned int DigNum[]={							// 0~9十个数字对应的数码管显示编码 
	0x3f,0x06,0x5b,0x4f,0x66, 
	0x6d,0x7d,0x27,0x7f,0x6f 
	}; 
 
void DispNum(unsigned int Num) 
{ 
	unsigned int TempNum = Num, k; 
 
	DIG_Clear();										// 清除数码管显示 
	if(Num>=1000)										// 千位 
	{ 
		k = TempNum/1000; 
		DIG_Set(1,DigNum[k]); 
		TempNum = TempNum - k * 1000; 
	} 
	if(Num>=100)										// 百位 
	{ 
		k = TempNum/100; 
		DIG_Set(2,DigNum[k]); 
		TempNum = TempNum - k * 100; 
	} 
	if(Num>=10)											// 十位 
	{ 
		k = TempNum/10; 
		DIG_Set(3,DigNum[k]); 
		TempNum = TempNum - k * 10; 
	} 
	DIG_Set(4,DigNum[TempNum]);							// 个位 
} 
 
//======================================================================== 
//	语法格式:	void DelayMS(unsigned ms) 
//	实现功能:	延时若干毫秒(不精确) 
//	参数:		ms - 毫秒数@49MHz 
//	返回值:	无 
//======================================================================== 
void DelayMS(unsigned ms) 
{ 
	unsigned i; 
	while(ms--)	 
	{ 
		for(i = 0; i < 1044; i++) 
			*P_Watchdog_Clear = 1; 
	} 
} 
 
//======================================================================== 
//	语法格式:	int DCMotor_Speed_PID(int SetSpeed, int CurSpeed) 
//	实现功能:	增量式PID计算: u0 = u1 + CP*(e0-e1) + CI*e0 + CD*(e0-2*e1+e2) 
//	参数:		SetSpeed:	设定的转速 
//				CurSpeed:	实际测得转速 
//	返回值:	直流电机速度等级(PWM占空比) 
//======================================================================== 
int DCMotor_Speed_PID(int SetSpeed, int CurSpeed) 
{ 
	int e0, u0; 
	static int u1 = 0;									// 前一次输出值(为避免浮点运算将该值扩大16倍) 
	static int e1 = 0, e2 = 0; 
	 
	e0 = SetSpeed - CurSpeed;							// 当前速度偏差 
	u0 = u1 											 
		 + CP * (e0 - e1)								// 比例项 
		 + CI * e0										// 积分项 
		 + CD * (e0 - e1 - e1 + e2);					// 微分项 
	 
	if(u0 > 1023) u0 = 1023;							// 输出值应小于64(扩大16倍) 
	if(u0 < 16) u0 = 16;								// 输出值应不小于1(扩大16倍) 
 
	u1 = u0;											// 更新u1、e1和e2 
	e2 = e1; 
	e1 = e0; 
	 
	return u0>>4;										// 返回u0/16 
} 
 
//======================================================================== 
//	语法格式:	void SetSpeed(void) 
//	实现功能:	设定转速 
//	参数:		无 
//	返回值:	无 
//======================================================================== 
void SetSpeed(void) 
{ 
	unsigned int KeyCode; 
 
	while(1) 
	{ 
		DispNum(g_Speed);								// 闪烁显示当前设定的转速 
		DelayMS(300); 
		DIG_Clear(); 
		DelayMS(300); 
		 
		KeyCode = Key_Get(); 
		switch(KeyCode) 
		{ 
			case KEY_1:									// Key1, 设定值增加 
				g_Speed += SPEED_STEP; 
				if(g_Speed > SPEED_MAX)g_Speed = SPEED_MIN; 
				break; 
			case KEY_2:									// Key2, 设定值减小 
				g_Speed -= SPEED_STEP; 
				if(g_Speed < SPEED_MIN)g_Speed = SPEED_MAX; 
				break; 
			case KEY_3:									// Key3, 确定 
				return; 
			default: 
		} 
	} 
} 
 
//======================================================================== 
//	语法格式:	void SetDirection(void) 
//	实现功能:	设定转动方向 
//	参数:		无 
//	返回值:	无 
//======================================================================== 
void SetDirection(void) 
{ 
	unsigned int KeyCode; 
	unsigned int i; 
 
	i = 1; 
	while(1) 
	{ 
		/// 在数码管上显示滚动的"-",表示电机转动方向 
		DIG_Clear();									// 清除显示 
		DIG_Set(i,0x40); 
		DelayMS(200); 
		i += g_Direction; 
		if(i>4)i=1; 
		if(i<1)i=4; 
		 
		KeyCode = Key_Get(); 
		switch(KeyCode) 
		{ 
			case KEY_1:									// Key1, 正转 
				g_Direction = 1; 
				break; 
			case KEY_2:									// Key2, 反转 
				g_Direction = -1; 
				break; 
			case KEY_3:									// Key3, 确定 
				return; 
			default: 
				break; 
		} 
	}		 
 
} 
 
//======================================================================== 
//	语法格式:	void StartMotor(void) 
//	实现功能:	直流电机转动控制 
//	参数:		无 
//	返回值:	无 
//======================================================================== 
void StartMotor(void) 
{ 
	unsigned int KeyCode; 
	unsigned int SpeedLevel, CurSpeed=0, PreSpeed=0; 
		 
	if(g_Direction==1)									// 确定转动方向 
		DCMotor_Forward(MOTOR_1+MOTOR_2); 
	else 
		DCMotor_Backward(MOTOR_1+MOTOR_2); 
 
	DispNum(CurSpeed); 
	while(1) 
	{ 
		if(CurSpeed != PreSpeed)						// 如果转速改变则更新显示 
		{ 
			DispNum(CurSpeed);							// 显示当前转速 
			PreSpeed = CurSpeed; 
		} 
		if(DCMotor_IsSpeedRdy())						// 如果已完成一次测速 
		{ 
			CurSpeed = DCMotor_GetSpeed();				// 获取转速 
			SpeedLevel = DCMotor_Speed_PID(g_Speed, CurSpeed);	// PID计算,得到新的PWM占空比 
			DCMotor_SetSpeed(MOTOR_1+MOTOR_2, SpeedLevel);		// 更新PWM占空比,调节转速 
		} 
		KeyCode = Key_Get(); 
		switch(KeyCode)	 
		{ 
			case KEY_1:									// Key1,速度增加 
				g_Speed += SPEED_STEP; 
				if(g_Speed > SPEED_MAX)g_Speed = SPEED_MIN; 
				break; 
			case KEY_2:									// Key2,速度减小 
				g_Speed -= SPEED_STEP; 
				if(g_Speed < SPEED_MIN)g_Speed = SPEED_MAX; 
				break; 
			case KEY_3:									// Key3,停止 
				DCMotor_Stop(MOTOR_1+MOTOR_2); 
				return; 
			default: 
				break; 
		} 
	} 
} 
 
//======================================================================== 
//	语法格式:	int main(void) 
//	实现功能:	主函数,通过按键选择不同功能 
//	参数:		无 
//	返回值:	无 
//======================================================================== 
int main(void) 
{ 
	unsigned int KeyCode, Flag_KeyEvent; 
	 
	System_Init();										// 系统初始化 
	Flag_KeyEvent = 1; 
	 
	while(1) 
	{ 
		if(Flag_KeyEvent==1) 
		{ 
			DispNum(g_Speed);							// 显示当前设定的转速 
			Flag_KeyEvent = 0; 
		} 
		KeyCode = Key_Get(); 
		switch(KeyCode) 
		{ 
			case KEY_1:									// Key1, 转速设定 
				SetSpeed(); 
				Flag_KeyEvent = 1; 
				break; 
			case KEY_2:									// Key2, 方向设定 
				SetDirection(); 
				Flag_KeyEvent = 1; 
				break; 
			case KEY_3:									// Key3, 启动电机 
				StartMotor(); 
				Flag_KeyEvent = 1; 
				break; 
			default: 
				break; 
		} 
	} 
}