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

📄 main.c

📁 凌阳单片机毕设题目的代码
💻 C
字号:
///========================================================
//	工程名称:	DC_SpeedCtrl
//	功能描述:	直流电机速度测量与调节
//========================================================


#include "SPCE061A.h"
#include "DCMotor.h"
#include "Dig.h"
#include "Key.h"
#include "a2000.h"

#define SPEED_MAX	62							    	// 最高设定速度
#define	SPEED_MIN	10									// 最低设定速度
#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 playspeed(unsigned int TempNum);
//========================================================================
//	语法格式:	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)
//========================================================================
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>=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)
//========================================================================
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;
			case KEY_4:	                                // Key,播报转速
		    	playspeed(g_Speed);
				break;
			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;
		}
	}
}
//===============================================================================
//语法格式:void PlaySnd_Auto(unsigned int uiSndIndex)
//自动播放语音函数
//==============================================================================
void PlaySnd_Auto(unsigned int uiSndIndex)
{
	SACM_A2000_Initial(1);						//初始化为自动播放方式
	SACM_A2000_Play(uiSndIndex,3,3);	            //播放
	while((SACM_A2000_Status() & 0x0001) != 0)
	{											//判断播放状态,如还在播放则继续循环
		SACM_A2000_ServiceLoop();				//播放系统服务程序
		*P_Watchdog_Clear = 0x0001;			
	}	
	SACM_A2000_Stop();							//停止播放
}
//===============================================================================
// 播报语音
//===============================================================================
void playspeed(unsigned int TempNum)
{
	int iShow[4];	
	unsigned int KeyCode;
	iShow[3]=TempNum/1000;                       //计算转速的千位数
	iShow[2]=(TempNum/100)%10;                   //计算转速的百位数
	iShow[1]=(TempNum/10)%10;                    //计算转速的十位数
   	iShow[0]=TempNum%10;				 //计算转速的个位数	
	KeyCode = Key_Get();     

		PlaySnd_Auto(12);
		PlaySnd_Auto(iShow[1]);
		PlaySnd_Auto(10);
		if (iShow[0]!=0) 
		PlaySnd_Auto(iShow[0]);
		PlaySnd_Auto(14);	
			
		*P_Watchdog_Clear = 0x0001;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -