dsp模拟电梯系统

今天在整理电脑文档的时候,发现了自己的上学期的dsp文件夹里还躺着上学期的课程设计。那是设计一个模拟电梯系统的dsp程序,用的c语言写的,平台是L138(实验室好像是这个平台)。第一次觉得模块化编程是高效的,当然也是不分程序语言的。在博客整理一下当时的思路和顺便记录。

实验室的L38板的数字按键只有9个,模拟电梯有四层楼,按键1到4为楼层按键;按键5和6表示楼层上下,按键7和8模拟开关门,按键9 终止程序。当然还有在显示屏上显示电梯的状态——楼层,电梯的上下状态,以及电梯门的开关状态。这部分显示用的是字模软件取字模,具体的字模软件可以自行百度。噢,还有步进电机的顺逆转动方向表示上下的电梯状态。具体的实现附上代码,代码内也有详细的注释:

#include "stdio.h"
#include "types.h"
#include "evmomapl138.h"
#include "evmomapl138_int.h"
#include "evmomapl138_int_timer.h"
#include "evmomapl138_int_gpio.h"
#include "evmomapl138_timer.h"
#include "evmomapl138_emif.h"
#include "evmomapl138_ctr.h"
#include "evmomapl138_ctr_lcd.h"
#include "evmomapl138_ctr_dcmotor.h"
#include "evmomapl138_ctr_keypad.h"
#include "evmomapl138_cpld.h"
#include "evmomapl138_led.h"
#include "evmomapl138_dip.h"
#include "test_ctr_dcmotor.h"

#define TEST_CTR_int_period (2000)
#define Maxfloor 4
#define Minfloor 1
enum	EleStatus{open,close};//电梯门状态
enum	EleStage{up,down,stop}; //电梯运行状态

static void TEST_ctr_keypad_isr(void);
static uint8_t key_code = 0xFF;

typedef struct {
	int floor;	//电梯所在层
	enum EleStatus status;	//电梯当前状态
	enum EleStage stage;	//电梯运行时期
	int CallUp[Maxfloor+1];//每层的Up按钮
	int CallDown[Maxfloor+1];//每层的Down按钮
	int CallCar[Maxfloor+1];//电梯内的目标层按钮
}Elevator;
Elevator E; //定义电梯为E
uint8_t dip;
uint8_t a=0;
uint8_t in=1;
static uint32_t TEST_CTR_toggle = 0;
static uint32_t TEST_CTR_duty = 30;
static uint32_t TEST_CTR_count = 0;

static uint8_t Clear[1][16] = {    //不显示任何东西
     {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
   };
//当前电梯门的开关转态,从上到下分别是对应汉字的字模 分别是门 开 关
static uint8_t door_state[3][32] = {
		  {0x00,0xF8,0x01,0x06,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00},
		  {0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00,0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00},
		  {0x00,0x00,0x10,0x11,0x16,0x10,0x10,0xF0,0x10,0x10,0x14,0x13,0x10,0x00,0x00,0x00, 0x81,0x81,0x41,0x41,0x21,0x11,0x0D,0x03,0x0D,0x11,0x21,0x41,0x41,0x81,0x81,0x00}
};

//当前的电梯运行状态,从上到下分别是 上 下 停

static uint8_t run_state[3][32] = {
		  {0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00},
		  {0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x02,0x02,0x42,0x82,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x01,0x06,0x00,0x00,0x00},
		  {0x80,0x60,0xF8,0x07,0x00,0x04,0x74,0x54,0x55,0x56,0x54,0x54,0x74,0x04,0x00,0x00,0x00,0x00,0xFF,0x00,0x03,0x01,0x05,0x45,0x85,0x7D,0x05,0x05,0x05,0x01,0x03,0x00}
};

//当前楼层的数字 从上到下分别是 1 2 3 4
static uint8_t cur_floor[4][16] = {
		   {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},
		   {0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},
		   {0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},
		   {0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00}
};

static void TEST_ctr_dcmotor_isr(void);
extern void intcVectorTable(void);

//清除相应显示,按下楼层
void Dispnot()
{
	uint8_t x_locate = (E.floor-1)*16+4; //按键消除的横坐标,分别是 4 20 36 52
	 ICETEK_CTR_LCD_put_bmp(x_locate,16,Clear[0], 8, 16);
	 ICETEK_CTR_LCD_update(x_locate,16,8,16);
}

//显示按下一楼
void Disp1()
{
	ICETEK_CTR_LCD_put_bmp(4, 16, cur_floor[0], 8, 16);
	 ICETEK_CTR_LCD_update(4,16,8,16);
}
//显示按下2楼
void Disp2()
{
	ICETEK_CTR_LCD_put_bmp(20, 16, cur_floor[1], 8, 16);
	 ICETEK_CTR_LCD_update(20,16,8,16);
}
//显示按下3楼
void Disp3()
{
	ICETEK_CTR_LCD_put_bmp(36, 16, cur_floor[2], 8, 16);
	 ICETEK_CTR_LCD_update(36,16,8,16);
}
//显示按下4楼
void Disp4()
{
	ICETEK_CTR_LCD_put_bmp(52, 16, cur_floor[3], 8, 16);
	 ICETEK_CTR_LCD_update(52,16,8,16);
}
//显示当前楼层
void DispFloor()
{
	ICETEK_CTR_LCD_put_bmp(96, 0, cur_floor[E.floor-1], 8, 16);
	ICETEK_CTR_LCD_update(96,0,8,16);
}

//显示门开
void DispOpen()
{
	ICETEK_CTR_LCD_put_bmp(0, 0, door_state[0], 16,16 );
	ICETEK_CTR_LCD_put_bmp(16, 0, door_state[1], 16, 16);
	ICETEK_CTR_LCD_update(0,0,16,16);
	ICETEK_CTR_LCD_update(16,0,16,16);
}

//显示门关
void DispClose()
{
	ICETEK_CTR_LCD_put_bmp(0, 0, door_state[0], 16,16 );
	ICETEK_CTR_LCD_put_bmp(16, 0,door_state[2], 16, 16);
	ICETEK_CTR_LCD_update(0,0,16,16);
	ICETEK_CTR_LCD_update(16,0,16,16);
}

//显示电梯上升
void DispUp()
{
	ICETEK_CTR_LCD_put_bmp(48, 0, run_state[0], 16, 16);
	ICETEK_CTR_LCD_update(48,0,16,16);
}

//显示电梯下降
void DispDown()
{
	ICETEK_CTR_LCD_put_bmp(48, 0, run_state[1], 16, 16);
	ICETEK_CTR_LCD_update(48,0,16,16);
}

//显示电梯停
void DispStop()
{
	ICETEK_CTR_LCD_put_bmp(48, 0, run_state[2], 16, 16);
	ICETEK_CTR_LCD_update(48,0,16,16);
}

//识别电梯门状态并显示
void DispDoor()
{
	switch(E.status)
	{
		case open:DispOpen();break;
		case close:DispClose();break;
	}
}

//开门动作
void Open()
{
	E.status=open;
	DispDoor();  //显示门状态
}

//关门动作
void Close()
{
	E.status=close;
	DispDoor(); //显示门状态
}

//检测电梯内部按钮
Dip()
{
	while(1)
	{
		switch(ICETEK_CTR_KEYPAD_getkey())
		{
			case KEYCODE_1:E.CallCar[1]=1;Disp1();break; //按下1楼
			case KEYCODE_2:E.CallCar[2]=1;Disp2();break;//按下2楼
			case KEYCODE_3:E.CallCar[3]=1;Disp3();break;//按下3楼
			case KEYCODE_4:E.CallCar[4]=1;Disp4();break;//按下4楼
			case KEYCODE_8:a=1;in=1;break;
			default:break;
		}
		if(a==1) //8键关门并退出
		{Close();USTIMER_delay(2000000);a=0;break;}
	}
}


//检测电梯外部按钮
void Key()
{

	switch(key_code)
	{
		case KEYCODE_1:E.CallUp[1]=1;break;  //一楼上请求
		case KEYCODE_2:E.CallDown[2]=1;break;//二楼下请求
		case KEYCODE_3:E.CallUp[2]=1;break;  //二楼上请求
		case KEYCODE_4:E.CallDown[3]=1;break;//三楼上请求
		case KEYCODE_5:E.CallUp[3]=1;break;  //三楼下请求
		case KEYCODE_6:E.CallDown[4]=1;break; //四楼下请i去
		case KEYCODE_7: Open();in=0;Dip();break;  //7键转换为检测内部按钮,开门
		default:break;
	}
}

//电梯初始化
void InitLift()
{
	int i;
	E.floor=1;
	E.stage=stop;
	E.status=close;
	for( i=0;i<=Maxfloor;i++)
	{
		E.CallUp[i]=0;E.CallDown[i]=0;E.CallCar[i]=0;
	}
	DispDoor();  //显示初始门状态
	DispFloor(); //显示初始楼层
}

//判断是否在当前楼层停留
int IsStop()
{
	if(E.CallCar[E.floor]) return 1;     //该楼层的楼层按钮被按下
//电梯上升且该楼层按下上升按钮但高楼层或者电梯下降时该楼层按下下降按钮
		if(E.stage==up&&E.CallUp[E.floor]||E.stage==down&&E.CallDown[E.floor])
			return 1;
//电梯上升时但高楼层没有呼叫时
	if(E.stage==up)
	{
		if(!UpCheck()&&E.CallDown[E.floor]==1)
			{E.stage=down;return 1;}
	}
//电梯下降时但低楼层没有呼叫时
	if(E.stage==down)
	{
		if(!DownCheck()&&E.CallUp[E.floor]==1)
			{E.stage=up;return 1;}
	}
	return 0;
}

//电梯停
void Stop()
{
	//ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_LOW);
	E.stage=stop; //状态变为停
	DispStop();  //显示停
	Close();     //门关
	DispDoor();  //显示门关
 //清除该楼层的请求
	E.CallCar[E.floor]=0;
	E.CallDown[E.floor]=0;
	E.CallUp[E.floor]=0;
}

//电梯上升一层
void GoUp()
{
	int i,j;
	//ICETEK_CTR_DCMOTOR_direct(DCMOTOR_DIRECTION_CLOCK);
	TEST_CTR_duty=50;
	ICETEK_CTR_DCMOTOR_enable(true);
	USTIMER_delay(2000000);

	E.floor++; //楼层加1
	Dispnot();  //清除该楼层的按下显示
}

//电梯下降一层
void GoDown()
{
	int i,j;
	//ICETEK_CTR_DCMOTOR_direct( DCMOTOR_DIRECTION_COUNTER_CLOCK);
	TEST_CTR_duty=50;
	 ICETEK_CTR_DCMOTOR_enable(true);
	USTIMER_delay(2000000);

	E.floor--;    //楼层减1
	Dispnot();    //清除该楼层的按下显示
}


//电梯上升
void Up()
{
	int i,j;
	ICETEK_CTR_DCMOTOR_direct(DCMOTOR_DIRECTION_CLOCK);
	DispUp(); //显示上升状态
	TEST_CTR_duty=20;  //起始速度为20
	ICETEK_CTR_DCMOTOR_enable(true);
	USTIMER_delay(2000000);

	while(E.floor<4)  //上升楼层不超过4
	{
		GoUp();  //上升了一层
		DispFloor();  //显示楼层
		if(IsStop())   //判断是否需要停留在当前楼层
		{
                        //若停留,缓慢停止
			TEST_CTR_duty=20;
			ICETEK_CTR_DCMOTOR_enable(true);
			USTIMER_delay(2000000);//延时

			ICETEK_CTR_DCMOTOR_enable(false);
			Stop(); //电梯停止动作
			USTIMER_delay(2000000);
			Open();//开门
			DispDoor();//显示楼层
			USTIMER_delay(2000000);//延时2s
			break;
		}
		else
		{
			TEST_CTR_duty=50;
			ICETEK_CTR_DCMOTOR_enable(true); //电机使能
			USTIMER_delay(2000000); //延时

		}
	}
	//ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_LOW);
	 ICETEK_CTR_DCMOTOR_enable(false); //停电机
	Stop();  //电梯停止动作
}

//电梯下降
void Down()
{
	int i,j;
	DispDown();//显示下降状态
	ICETEK_CTR_DCMOTOR_direct( !DCMOTOR_DIRECTION_CLOCK);//反转表示下降
	TEST_CTR_duty=20;//起速20
	ICETEK_CTR_DCMOTOR_enable(true);
	USTIMER_delay(2000000);

	while(E.floor>1)  //下降楼层不低于1楼
	{
		GoDown(); //下降一楼
		DispFloor(); //显示当前楼层
		if(IsStop()) //判断是否需要停留在当前楼层
		{
			TEST_CTR_duty=20;
			 ICETEK_CTR_DCMOTOR_enable(true);
						 USTIMER_delay(2000000);

			ICETEK_CTR_DCMOTOR_enable(false); //停电机
			Stop();  //电梯停
			USTIMER_delay(2000000);
			Open(); //门开
			DispDoor();//显示门开
			USTIMER_delay(2000000);//延时
			break;
		}
		else
		{
			TEST_CTR_duty=50;
			 ICETEK_CTR_DCMOTOR_enable(true);
			USTIMER_delay(2000000);

		}
	}
	//ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_LOW);
	   ICETEK_CTR_DCMOTOR_enable(false);//停电机
	Stop(); //电梯停,门关
}


//检查是否有高楼层请求
int UpCheck()
{
	int i;
	for( i=E.floor+1;i<=Maxfloor;i++)
		if(E.CallCar[i]||E.CallDown[i]||E.CallUp[i]) return 1;
	return 0;
}

//检查是否有低楼层请求
int DownCheck()
{
	int i;
	for(i=E.floor-1;i>=Minfloor;i--)
		if(E.CallCar[i]||E.CallDown[i]||E.CallUp[i]) return 1;
	return 0;
}

//返回电梯状态
enum EleStage UpOrDown()
{
	if(UpCheck())return E.stage=up;
	else if(DownCheck()) return  E.stage=down;
	else return E.stage=stop;
}

uint32_t TEST_ctr_dcmotor(void)
{
   uint32_t rtn;
   ICETEK_CTR_init();
   ICETEK_CTR_DCMOTOR_init();
   ICETEK_CTR_LCD_init();
   ICETEK_CTR_LCD_enable(true);
   rtn = ICETEK_CTR_KEYPAD_init();
   if (rtn != ERR_NO_ERROR)
   {
      printf("error initializing keypad: %u\r\n", rtn);
      return (rtn);
   }
   //ICETEK_CPLD_init();
   LED_init();
   DIP_init();
   EVMOMAPL138_int_enable((uint32_t)intcVectorTable);
   USTIMER_delay(1000);
   USTIMER_int_enable(VECTOR_ENTRY_04, TEST_CTR_int_period, (DSPINTC_func)TEST_ctr_dcmotor_isr);
   ICETEK_CTR_DCMOTOR_direct(DCMOTOR_DIRECTION_CLOCK);
   GPIO_int_enable(VECTOR_ENTRY_05, 4, 1, GPIO_INT_ON_BOTH_EDGE, TEST_ctr_keypad_isr);
   ICETEK_CTR_KEYPAD_enable(true);
 //  ICETEK_CTR_DCMOTOR_enable(true);
   //ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_LOW);
   InitLift(); //初始化电梯
   while(1)
   {
	   Key(); //按键扫描
	   switch(UpOrDown())  //检查电梯状态
	   {
	   	   case stop: Stop();break; //停
	   	   case up: Up();break;     //上升
	   	   case down:Down();break;  //下降
	   }
   ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_LOW); //停电机
   if(ICETEK_CTR_KEYPAD_getkey() == KEYCODE_9) //按下9退出循环
	   break;
   }
   ICETEK_CTR_DCMOTOR_enable(false);
   USTIMER_int_disable();
   EVMOMAPL138_int_disable();
   ICETEK_CTR_LCD_enable(false);
   ICETEK_CTR_close();
   return (ERR_NO_ERROR);
}

void TEST_ctr_dcmotor_isr(void)
{
	TEST_CTR_count++;

	if(TEST_CTR_count%100 == TEST_CTR_duty)
	{
		//TEST_CTR_toggle = 0;
		ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_LOW);
		return;
	}

	if(TEST_CTR_count%100 == 0)
	{
		//TEST_CTR_toggle = 1;
		ICETEK_CTR_DCMOTOR_drive(DCMOTOR_DRIVE_HIGHT);
		return;
	}
}


//-----------------------------------------------------------------------------
// Private Function Definitions
//-----------------------------------------------------------------------------

void TEST_ctr_keypad_isr(void)
{
	key_code = ICETEK_CTR_KEYPAD_getkey();
	if(in)
	{
		switch(key_code)
			{
			case KEYCODE_1:E.CallUp[1]=1;break;
			case KEYCODE_2:E.CallDown[2]=1;break;
			case KEYCODE_3:E.CallUp[2]=1;break;
			case KEYCODE_4:E.CallDown[3]=1;break;
			case KEYCODE_5:E.CallUp[3]=1;break;
			case KEYCODE_6:E.CallDown[4]=1;break;
			default:break;
		}
	}
}

相关的头文件和环境依赖自行看程序和自己的实现。这个课程设计的一大遗憾是没有用上类似链表或者队列的数据结构,因为我们C语言学习的时候没有学指针之类的(借口而已)。碍于当时的时间紧迫,用上链表之类的驱动和代码量难度都会加大,为了省事也就这样了。当然也没有实现教授所说的平滑的电梯上升和下降速度(毫无思路)。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值