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

📄 logic.c

📁 利用单片机实现的控制电梯系统
💻 C
字号:
#include <reg52.h>
#include	"PIN.H"			// 修改该文件以适应硬件环境/单片机型号等
#include	"CH452CMD.H"	// CH452常量定义
#include    "definition.h"
#define uchar unsigned char
#define uint unsigned int
#define step_motor_frequence 65536-1000
#define timer_10ms 65536-10000
#define up 1
#define down 0
extern void CH452_Write (unsigned short cmd);
extern uchar CH452_Read( void );
extern void keyboard_detact(uchar value);
uchar up_list[5];
uchar down_list[5];
bit read_flag;
bit direction_display_flag;
bit highest_floor_flag;
bit lowest_floor_flag;
uchar storey;
uint counter_5s;
uchar over_load_flag;
uchar up_list_flag=0;
uchar down_list_flag=0;
uchar inside_request=0;
uchar outside_request=0;
bit current_direction;
sbit L297_clock=P1^0;
sbit L297_reset=P1^1;
sbit L297_mode=P1^2;
sbit L297_direction=P1^3;
sbit L297_on=P1^4;
void interrupt_logic(void);
void input_up_list(uchar request);
void input_down_list(uchar request);
/************************初始化程序******************/
void init_port(void)
{
 P0=0x00;
 P2=P2&0x07;
}

void init_serialport(void)
{
 SCON=0x98;
 PCON=0x80;
 ES=1;
 IP=0x10;
}

void init_stepper_motor(void)
{
 L297_on=1;
 L297_reset=1;
 L297_mode=1;
 L297_direction=up;
 current_direction=up;
}

void init_timer(void)
{
 TMOD=0x11;
 TH0=step_motor_frequence/256;
 TL0=step_motor_frequence%256;
 ET0=1;
 TH1=timer_10ms/256;
 TL1=timer_10ms%256;
 ET1=1;
 TR0=1;
}
 
void init_exint0(void)
{
 EA=1;
 EX0=1;
 IT0=1;
}

void init_CH451L(void)
{
 CH452_Write(CH452_RESET);
 CH452_Write(CH452_BCD | 0x20);    // 选择BCD译码方式,扫描极限为2个数码管
 CH452_Write(CH452_SYSON2);     // 开启显示
 CH452_Write(CH452_DIG0 | 0);
}

void delay_ms(uint t)//延时子程序,延时 1MS*t S
{
	uchar a;
	while(--t != 0)
	{
		for(a = 0; a < 125; a++);
	}
}

void delay_s(uchar x)
{
 uchar i;
 for(i=0;i<x;i++)
 delay_ms(1000);
}
/*****************************超重判断程序************************/
void over_load_judge(void)
{
 if(1==over_load_flag)
 {
  TR0 = 0;
  delay_s(3);
 }
 else if(2==over_load_flag)
 {
  TR0=1;
  over_load_flag=0;
 } 
}
/*****************************电梯逻辑程序************************/
void transmit_run(void)
{
  SBUF=0x0f;
  while(0==TI);
  TI=0;
}

void transmit_stop(void)
{
  SBUF=0xf0;
  while(0==TI);
  TI=0;
}

void start_lift(void)
{
 uchar temp;
 do
 {
  if(1==read_flag)
  {
   temp=CH452_Read();
   keyboard_detact(temp);
   read_flag=0;
  }
 }
 while(storey!=1);
 TR0=0;                          //电梯停转
 CH452_Write(CH452_DIG0 | storey);
 CH452_Write(CH452_DIG1 | 0x10);
 delay_s(2);
 direction_display_flag=0;
}

void keyboard_program(void)
{
 uchar keyboard_value;
 if(1==read_flag)
 {
  keyboard_value=CH452_Read();
  keyboard_detact(keyboard_value);
  interrupt_logic();
  read_flag=0;
 }
}

void direction_display(void)
{
 if(up==current_direction)
 CH452_Write(CH452_DIG1 | 0x07);
 else
 CH452_Write(CH452_DIG1 | CH452_BCD_CH_L);
 CH452_Write(CH452_DIG0 | storey);
}

void turn_off_lights(uchar level)
{
 switch(level)
 {
  case 1:
  {
   inside_led1=0;
   outside_up_led1=0;
   break;
  }
  case 2:
  {
   inside_led2=0;
   if(up==current_direction)
   {
    outside_up_led2=0;
	if(2>=up_list[0])
	outside_down_led2=0;
   }
   else
   {
    outside_down_led2=0;
	if(2<=down_list[0])
	outside_up_led2=0;
   }
   break;			 
  }
  case 3:
  {
   inside_led3=0;
   if(up==current_direction)
   {
    outside_up_led3=0;
	if(3>=up_list[0])
	outside_down_led3=0;
   }
   else
   {
    outside_down_led3=0;
	if(3<=down_list[0])
	outside_up_led3=0;
   }
   break;
  }
  case 4:
  {
   inside_led4=0;
   if(up==current_direction)
   {
    outside_up_led4=0;
	if(4>=up_list[0])
	outside_down_led4=0;
   }
   else
   {
    outside_down_led4=0;
	if(4<=down_list[0])
	outside_up_led4=0;
   }
   break;
  }
  case 5:
  {
   inside_led5=0;
   outside_down_led5=0;
   break;
  }
  default:break;
 }
}

void lift_run(void)
{
 uchar i;
 if((0==down_list_flag)&&(0==up_list_flag))
 {
  TR0=0;
  CH452_Write(CH452_DIG1 | 0x10);
 }
 else if(up==current_direction)
 {
  if(0!=up_list_flag)
  {
   L297_direction=up;
   if(storey==up_list[0]) //到达楼层后电梯停转
   {
    TR0=0;//电梯停转
	transmit_stop();
    for(i=0;i<4;i++)
    {
     up_list[i]=up_list[i+1];//在队列中去除应最先响应的楼层
    }
    up_list[4]=0;
	turn_off_lights(storey);
    up_list_flag--;
    CH452_Write(CH452_DIG1 | 0x10);
    TR1=1;
    counter_5s=500;
    while(counter_5s)
	{
     keyboard_program();
	}
    TR1=0;
   }
   else//若没有到达楼层,则判断是否电梯停转,若停转则启动,没有停转就跳过
   {
    if(0==TR0)
    {
	 TR0=1;
	 transmit_run();
	 direction_display();
	}
   }
  }
  else if((0==up_list_flag)&&(0!=down_list_flag))//若上升队列为空而下降队列不为空,则判断下降队列,
  {
   current_direction=down;
  }
 }
 else if(down==current_direction)
 {
  if(0!=down_list_flag)
  {
   L297_direction=down;
   if(storey==down_list[0])
   {
    TR0=0;
	transmit_stop();
    for(i=0;i<4;i++)
    {
     down_list[i]=down_list[i+1];
    }
    down_list[4]=0;
    turn_off_lights(storey);
    down_list_flag--;
    CH452_Write(CH452_DIG1 | 0x10);
    TR1=1;
    counter_5s=500;
    while(counter_5s)
    {
     keyboard_program();
	}
    TR1=0;
   }
   else
   {
    if(0==TR0)
	{
     TR0=1;
	 transmit_run();
	 direction_display();
	}    
   }
  }
  else if((0==down_list_flag)&&(0!=up_list_flag))
  {
   current_direction=up;
  }
 }
}

void input_up_list(uchar request)
{
 uchar i=0,temp=0,k;
 if(0==up_list_flag)//若上升队列为空则直接插入
 up_list[0]=request;
 else if(5>up_list_flag)//若上升队列没有满
 {
  if(request>up_list[up_list_flag-1])//若请求楼层最大则插在上升队列末尾
  up_list[up_list_flag]=request;
  else								 //若请求楼层不是最大则进行判断
  { 
   while(0!=up_list[i])
   {
    if(request>up_list[i])			  //当请求楼层大于此楼层时则往后判断
	{
	 i++;
	}
	else if(request<up_list[i])		  //当请求楼层小于此楼侧时则插在此楼层前面
	{
	  for(k=4;k>i;k--)
	 { 
	  up_list[k]=up_list[k-1];
	 }
	 up_list[i]=request;
	 break;
	}
	else 							   //当请求楼层等于此楼层时则不改变此队列
	{
	 temp=1;
	 break;
	}
   }
  }
 }
 if(1!=temp)
 up_list_flag++;
}

void input_down_list(uchar request)
{
 uchar i=0,temp=0,k;
 if(0==down_list_flag)//若下降队列为空则直接插入
 down_list[0]=request;
 else if(5>down_list_flag)//若下降队列没有满
 {
  if(request<down_list[down_list_flag-1])//若请求楼层最小则插在下降队列末尾
  down_list[down_list_flag]=request;
  else									 //若请求楼层不是最小则进行判断
  {
   while(0!=down_list[i])
   {
    if(request<down_list[i])			 //当请求楼层小于此楼层时则往后判断
	{
	 i++;
	}
	else if(request>down_list[i])		//当请求楼层大于此楼侧时则插在此楼层前面
	{
	  for(k=4;k>i;k--)
	 { 
	  down_list[k]=down_list[k-1];
	 }
	 down_list[i]=request;
	 break;
	}
	else 
	{
	 temp=1;
	 break;
	}
   }
  }
 }
 if(1!=temp)
 down_list_flag++;
}

void interrupt_logic(void)
{
 if((0==down_list_flag)&&(0==up_list_flag))	//判断电梯是否在运行中
 {
  if(0!=inside_request)//内部按键控制
  {
   if(storey<inside_request)
   {
    current_direction=up;
    input_up_list(inside_request);
   }
   else if(storey>inside_request)
   {
    current_direction=down;
    input_down_list(inside_request);    
   }
   inside_request=0;
  }
  else if(0!=outside_request)//外部按键控制
  {
   if(storey<(outside_request&0x0f))
   {
    if(0x10<outside_request)//此时为下降请求时
	{
	 highest_floor_flag=1;//此时表明最高上升请求为一下降请求
	 outside_request&=0x0f;
	}
    input_up_list(outside_request);	 
    current_direction=up;
   }
   else if(storey>(outside_request&0x0f))
   {
    if(0x10>outside_request)//此时为上升请求时
	lowest_floor_flag=1;//此时表明最低下降请求为一上升请求
	else
	outside_request&=0x0f;
    input_down_list(outside_request);
    current_direction=down;
   }   
   outside_request=0;
  }
 }
 else                            //若电梯正在运行
 {
  if(0!=inside_request)//如果是内部按钮控制
  {
   if(up==current_direction)
   {
	if(storey<inside_request)//表明此时请求楼层在当前楼层上面
	{
	 if(inside_request<=up_list[0])//如果此请求小于等于最高请求楼层则直接插入上升队列
	 input_up_list(inside_request);
	 else if(1==highest_floor_flag)//若此请求大于最高请求楼曾则需判断最高请求楼层为向上还是向下请求
     {
	  input_down_list(up_list[0]);//则将最大请求楼层插入向下队列
	  up_list[0]=inside_request;//将最大请求楼层变为此次请求的楼层
	  highest_floor_flag=0;//表示最高请求楼层是上升请求
	 }
	 else//若为最高请求楼层向上请求则直接插入向上请求队列
     input_up_list(inside_request);
	}
	else//表明此请求楼层在当前楼层下面,注:因为就是在运动中因此不用考虑在当前楼层的问题
    {
	 input_down_list(inside_request);//当次上升请求小于当前楼层时则直接插入向下队列
	}
   }
   else
   {
	if(storey>inside_request)//表明此时请求楼层在当前楼层下面
    {
	 if(inside_request>=down_list[0])//如果此请求大于等于最低请求楼层则直接插入下降队列
	 input_down_list(inside_request);
	 else if(1==lowest_floor_flag)//若此请求小于最低请求楼曾则需判断最低请求楼层为向上还是向下请求
	 {
	  input_up_list(down_list[0]);//则将最小请求楼层插入向上队列
	  down_list[0]=inside_request;//将最小请求楼层变为此次请求的楼层
	  lowest_floor_flag=0;//表示最小请求楼层是下降请求
	 }
	 else//若为最低请求楼层向下请求则直接插入向下请求队列
     input_down_list(inside_request);
	}
	else//表明此请求楼层在当前楼层上面
	{
	 input_up_list(inside_request);//当次下降请求大于当前楼层时则直接插入向上队列
	}    
   }
   inside_request=0;
  }
  else if(0!=outside_request)//如果是外部按钮控制
  { 
   if(up==current_direction)//若电梯正在往上运行则响应向上的请求
   {
    if(0x10>outside_request)//表明请求为上升请求时
	{
	 if(storey<outside_request)//表明此时请求楼层在当前楼层上面
	 {
	  if(outside_request<=up_list[0])//如果此上升请求小于等于最高请求楼层则直接插入上升队列
	  input_up_list(outside_request);
	  else if(1==highest_floor_flag)//若此上升请求大于最高请求楼曾则需判断最高请求楼层为向上还是向下请求
	  {
	   input_down_list(up_list[0]);//则将最大请求楼层插入向下队列
	   up_list[0]=outside_request;//将最大请求楼层变为此次请求的楼层
	   highest_floor_flag=0;//表示最高请求楼层是上升请求
	  }
	  else//若为最高请求楼层向上请求则直接插入向上请求队列
      input_up_list(outside_request); 
	 }
	 else//表明此请求楼层在当前楼层下面,注:因为就是在运动中因此不用考虑在当前楼层的问题
	 {
	  input_down_list(outside_request);//当次上升请求小于当前楼层时则直接插入向下队列
	 }
	}
	else//表明请求若为下降请求时
	{
	 outside_request&=0x0f;
	 if(outside_request<=up_list[0])//若此下降请求小于等于最高请求楼层时直接插入下降队列
	 {
	  input_down_list(outside_request);
	 }
	 else//若此下降请求大于最高请求楼层时则插入上升队列并表明最高请求楼层的方向
	 {
	  input_up_list(outside_request);
	  highest_floor_flag=1;       //表示最高请求楼层是下降请求
	 }
	}
   }
   else                    //若电梯正在往下运行则相应向下的请求
   {
    if(0x10<outside_request)//表明请求为下降请求时
    {
	 outside_request&=0x0f;
	 if(storey>outside_request)//表明此时请求楼层在当前楼层下面
	 {
	  if(outside_request>=down_list[0])//如果此下降请求大于等于最低请求楼层则直接插入下降队列
	  input_down_list(outside_request);
	  else if(1==lowest_floor_flag)//若此下降请求小于最低请求楼曾则需判断最低请求楼层为向上还是向下请求
	  {
	   input_up_list(down_list[0]);//则将最小请求楼层插入向上队列
	   down_list[0]=outside_request;//将最小请求楼层变为此次请求的楼层
	   lowest_floor_flag=0;//表示最小请求楼层是下降请求
	  }
	  else//若为最低请求楼层向下请求则直接插入向下请求队列
      input_down_list(outside_request);
	 }
	 else//表明此请求楼层在当前楼层上面
	 {
	  input_up_list(outside_request);//当次下降请求大于当前楼层时则直接插入向上队列
	 }
    }
	else//表明请求若为上升请求时
	{
	 if(outside_request>=down_list[0])//若此上升请求大于等于最低请求楼层时直接插入上升队列
	 {
	  input_up_list(outside_request);
	 }
	 else//若此上升请求小于最低请求楼层时则插入下降队列并表明最低请求楼层的方向
	 {
	  input_down_list(outside_request);
	  lowest_floor_flag=1;       //表示最高请求楼层是下降请求
	 }
	}
   }
   outside_request=0;
  }
 }
}
/*********************************主程序*********************/
void main(void)
{
 init_port();
 init_serialport();
 init_timer();
 init_exint0();
 init_CH451L();
 init_stepper_motor();
 start_lift();
 while(1)
 {
  keyboard_program();
  if(1==direction_display_flag)
  {
   direction_display();
   direction_display_flag=0;
  }
  lift_run();
  over_load_judge(); 
 }
}

/*****************************中断程序及其判断*************/
void exint0(void) interrupt 0 using 1
{
 read_flag=1;
 direction_display_flag=1; 
}

void timer0_interrupt(void) interrupt 1 using 2
{
 L297_clock=!L297_clock;
 TH0=step_motor_frequence/256;
 TL0=step_motor_frequence%256;
}

void timer1_interrupt(void) interrupt 3 using 3
{
 counter_5s--;
 TH1=timer_10ms/256;
 TL1=timer_10ms%256;
}

void serial_receive(void) interrupt 4 using 3
{
 uchar weight_signal;
 weight_signal=SBUF;
 if(0x0A==weight_signal)//表示接收到异常重物信号
 {
  over_load_flag=1;  
 }
 else if(0xA0==weight_signal)//接收到正常重物信号
 {
  over_load_flag=2;
 }
 RI=0;
}

⌨️ 快捷键说明

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