蓝桥杯嵌入式第八届省赛模拟升降控制器工程参考

我的理解

这套题,算是把状态机用的淋漓尽致需要时刻判断升降器,也就是电梯的运动方向,在电梯上升或者下行时不接受输入,只在开门和关门时接受输入,且需要不断地去计算电梯地运动方向(流水灯指示)以及需要不断地去计算下一站台是几号站台。

电梯状态

获得需要运行标志->关门(计时)->根据运动方向选择上行或下行->到站->开门->判断是否需要继续运行->重复直到没有需要到达地站台.

工程参考

链接:https://pan.baidu.com/s/13paH1t7fVlYu99uV3H6BhQ 
提取码:yzh1

主要代码



 
 

#include "work.h"
#include "rtc.h"
RTC_TimeTypeDef T;
RTC_DateTypeDef D; 



#define ReadB1  HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define ReadB2  HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define ReadB3  HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define ReadB4  HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)



u8 LEDINDEX[] = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 LEDDT[10]={0};
u8 ledflsuh_t =0;

u16 doort = 0;//开关门时间
u16 runtime = 0;//运行时间  上下每层楼为6s
u16 rtct = 0; //采集RTC时间

u16 keywait=0;
u8 ct = 0;

typedef struct KEY {
    
    
    u16 keytime;
    u8   key_state;
    bool sflag;
    bool lflag;
    bool state;
    
    
}KEY;

KEY keys[4]={0};

u8 floors[4]={0};
u8 current =0;
u8 sign = 0;//上升或下降状态或停止
u8 nextfloor = 99;


u8 floorstate = 0;//等待按键,1s后开始,关门,运行电机,开门,停止
#define UP   {HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);TIM16->CCR1=80;}
               
               
#define DOWN { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);TIM16->CCR1 =60;}

#define OPEN {HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);TIM17->CCR1=60;}
#define CLOSE {HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);TIM17->CCR1=50;}



//读取RTC时钟
void ReadRtc(void)
{
    if(rtct > 881)
    {
        rtct = 0;
        HAL_RTC_GetDate(&hrtc,&D,RTC_FORMAT_BIN);
        HAL_RTC_GetTime(&hrtc,&T,RTC_FORMAT_BIN);
        
        printf("%d %d %d\r\n",T.Hours,T.Minutes,T.Seconds);
      
    
    }
    
}

void led_scan(void){
    
    
    
    if(ledflsuh_t >20)
    {
        ledflsuh_t = 0;
        u8 res= 0x00;
        for (int i = 1 ; i<=8;i++) res|=LEDINDEX[LEDDT[i]];
        DisPlayLed(res);  
   
    }
    
    
}

void upOrdown(void)
{
    
 
    static char ci = 0;
   static  u16 ledst = 0;//上升下降led时间
   
         if(ledst++ == 500)
         {
             ledst=0;
             
               if(sign == 2) //上升 5-8
                {
                    
                    switch(ci)
                    {
  
                        case 1:
                            LEDDT[5]=5; LEDDT[6]=LEDDT[7]=LEDDT[8]=0;
                            ci++;
                            
                            break;
                        case 2:
                            LEDDT[6]=6; LEDDT[7]=LEDDT[5]=LEDDT[8]=0;
                            ci++;
                            break;
                        case 3:
                            LEDDT[7]=7; LEDDT[6]=LEDDT[5]=LEDDT[8]=0;
                            ci++;
                            break;
                        case 4:
                             
                            LEDDT[8]=8; LEDDT[6]=LEDDT[5]=LEDDT[7]=0;
                            ci++;
                            
                            break;
                        default:
                            ci=1;     
                    }
                      
                    
                }
            else if(sign == 1)  //下降
                {
                    
                    switch(ci){
                        
                    case 1:
                        LEDDT[5]=5;        
                        LEDDT[8]=LEDDT[6]=LEDDT[7]=0;  
                        ci--;
                        break;
                    case 2:
                         LEDDT[6]=6;        
                        LEDDT[5]=LEDDT[8]=LEDDT[7]=0;  ci--;
                        break;
                    case 3:
                        LEDDT[7]=7;        
                        LEDDT[5]=LEDDT[6]=LEDDT[8]=0; ci--;                  
                        break;
                    case 4:
                        LEDDT[8]=8;
                        LEDDT[5]=LEDDT[6]=LEDDT[7]=0;ci--;
                        break;
                    default :
                        ci =4;
                     
                }
                    
                                         
                }
                
                
                  {    //刷新LED灯
                        u8 res= 0x00;
                        for (int i = 1 ; i<=8;i++) res|=LEDINDEX[LEDDT[i]];
                         DisPlayLed(res);  
                 }
             
         }
         
        
        
   
    
    
}


void key_scan(void)
{
    
        keys[0].state =ReadB1;
        keys[2].state =ReadB3;
        keys[1].state =ReadB2;
        keys[3].state =ReadB4;
    for(int i = 0; i<4;i++)
    {
        switch(keys[i].key_state)
        {
            case 0:
                 if(!keys[i].state)keys[i].key_state=1;
                 
                break;
            case 1:
                if(!keys[i].state)
                {
                    keys[i].key_state=2;
                    keys[i].keytime=10;
                     
                }
                else keys[i].key_state=0;
            
                break;
            case 2:
                keys[i].sflag = 0 ;
                if(!keys[i].state){
                    
                 
                     
                    keys[i].keytime+=10;
                     //长按键判断  
                }
                else
                {
                    // if(keys[i].keytime > 500)keys[i].lflag=1;
                    
                     keys[i].keytime = 0;
                     keys[i].key_state = 0;  
                     keys[i].sflag=1;
                       
                }                    
                    
                
                break;
            
            
        }    
    }
    
    
}

void key_action(void)
{
    
    
      if(floorstate == 3) return ;  //电机运转期间按键无效
      if(keys[0].sflag ||  keys[1].sflag || keys[2].sflag || keys[3].sflag ){   
           keywait = 0;
          floorstate=1;
      }
   
     if(keys[0].sflag && current!=0)floors[0]=1,LEDDT[1]=1,keys[0].sflag=0;
     if(keys[1].sflag && current!=1)floors[1]=1,LEDDT[2]=2,keys[1].sflag=0;
     if(keys[2].sflag && current!=2)floors[2]=1,LEDDT[3]=3,keys[2].sflag=0;
     if(keys[3].sflag && current!=3)floors[3]=1,LEDDT[4]=4,keys[3].sflag=0;
      
}

int fputc( int ch,FILE * F)
{
     
    HAL_UART_Transmit(&huart1,(u8 *)&ch,1,0XFFFF);
    
    
    return ch;
      
}

void floorrunning(void)
{
    if(!floorstate)return;
    switch(floorstate)
    {
        
        case 1://等待按键1s后
             if(keywait++ ==1000) 
              {
                  floorstate = 2;
                  keywait  = 0;
              }
                break;
        case 2:  //关门
            if(doort++ == 0)CLOSE;
            if(doort ==4000)
            {
                doort = 0;
                floorstate =3;
                
            }
            break;
        case 3:
            
             if(runtime++ == 0){
                if(sign==1) DOWN
                else UP
              
                    
                
                 
             }
             if(runtime == 6000)
             {
                 runtime = 0; //到达下一层
               if(nextfloor != 99) {
                   u8 temp = current;
                           if(sign == 2){ //上升
                               if(nextfloor-current>1)temp++;
                               else temp=nextfloor, floorstate =4;       
                            }    
                           else if(sign == 1) { //下降
                               if(current-nextfloor >1)temp--;
                               else temp= nextfloor, floorstate =4;                 
                           }
                   current =temp,floors[temp]=0;
                    LEDDT[temp+1]=0;
                      
                    
               }                   
             }
            break;
        case 4:
            if(doort++ ==0)OPEN;
            if(doort == 4000){
                
                doort = 0;
               if(sign==0)floorstate=0;
                else floorstate =5;//继续寻找平台
                
            }            
            break;
        case 5:
             if(doort++ == 2000)
             {
                 doort = 0;
                 floorstate =2;//关门后继续寻找
                 
             }
            break;
        
     

    }        
    
    
}

 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 {
     
     if(htim->Instance  ==TIM4)  //10ms进入一次
     {
         
         
         key_scan();
         key_action();
         
     }
     else if(htim->Instance == TIM2) //1ms进入一次
     {
         ledflsuh_t++;
         ct++;
          rtct++;
         upOrdown();
         floorrunning();
         
     }
     
     
 }
 
 
 void DisPlayLed(u8 ds)
 {
     
       HAL_GPIO_WritePin(GPIOC,0xff<<8,GPIO_PIN_SET);
       HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
       HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
     
     
       HAL_GPIO_WritePin(GPIOC,ds<<8,GPIO_PIN_RESET);
       HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
       HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
     
     
 }
 
 
 void LcdDisPlay(void)
 {
     
           char temp[20] = {0};
         
           LCD_DisplayStringLine(Line1,(u8*)"   ----CURRENT----   ");
            
           sprintf(temp,"        %d        ",current+1);     
           LCD_DisplayStringLine(Line3,(u8*)temp);
           
           sprintf(temp,"      %d: %d: %d   ",T.Hours,T.Minutes,T.Seconds);
           LCD_DisplayStringLine(Line5,(u8*)temp);
 }
 
 
 
 //获得前进方向 并计算出下一层
 void Correction(void)
 {
     if(ct< 223)return;
     ct=0;
     
     u8 flag =0;
     u8 updt[4]={0};
     u8 downdt[4]={0};
     u8 m=0,n=0;
     for (u8 i =0;i<4;i++)
   {
       if(floors[i]){
          
           if(current > i)flag=1,downdt[n++]=i;
           else if(current < i){
               if(flag == 1) flag =7,updt[m++]=i;
               else flag =2,updt[m++]=i;
               
           }
       
       }
       
   }
            
     if(flag == 7){
         sign = 2;//先上后下
         nextfloor = updt[0];
      
     }
     else if(flag ==1){
         sign =1;  //下降
         nextfloor = downdt[n-1]; //找到最近
     }
     else if(flag == 2) {
         sign= 2; //上升
         nextfloor = updt[0];
     }
     else 
         sign =0,nextfloor = 99;
            
 }
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值