蓝桥杯嵌入式第十二届第一场

前言

个人感觉这次的题目想拿高分和满分的拿分的还是有难度的,这届赛题我个人觉得难在车辆出入库之间,解决这两个主要问题,然后就是细节问题。接下来上赛题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解题之前,我觉得需要写一下串口部分的代码思路,方便后面的书写。
在这里插入图片描述
首先是车辆三要素,可以用结构体包含,想要车辆出入库,前提是串口发送数据合理,合理后判断车辆出入库,入库需要查询入几号库,出库也是,同时清空库内数据。大致就是以上步骤,其实思路清晰了,后续代码的编写也就是时间问题了,个人觉得这次拿满分很难,主要时间确实有点紧迫。接下来就上代码
全局变量和头文件

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "key.h"
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
__IO uint32_t keyTick,ledTick,uartTick; 
_Bool uart_flag,tim17_flag; //串口接收22字节标志位和PA7电平标志位
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
u8 lcd_display = 0;    //界面 0  1
u8 cnbr_num = 0,vnbr_num = 0;   //两种车辆类型的数目
u8 cnbr_rate = 35,vnbr_rate = 20;  //两种车辆每小时的停车费用

u8 led_ctrl;           //led控制
u8 uart_buf[2];        //串口发送缓存
u8 uart_rx[23];        //串口接收缓存
u8 rx_cnt;             //串口接收几个数

u8 year,month,day,hour,min,sec;        //首次接收串口数据并验证数据正确性
u8 year1,month1,day1,hour1,min1,sec1;  //数据正常赋值给这些变量 
u8 year3,month3,day3,hour3,min3,sec3;  //最后出车的时候计算停车费用,算总时间
u16 hour_all;                          //最后停车的总时间
__IO uint32_t money_vnbr,money_cnbr;   //两种车辆停车的总费用
u8 name1[4];                           //存车辆名字的数组
u8 car_indexes,car_out;                //第一个索引停哪个车位,第二个出库车位
typedef struct
{
  u8 type[5];       //车辆类型
  u8 name[5];       //车辆名字
  u8 year2;         //入库的时间
  u8 month2;
  u8 day2;
  u8 hour2;
  u8 min2;
  u8 sec2;
  u8 pos;           //当前车位的状态0有空位,1没有空位
} CAR;
CAR car_info[8];  //八个停车位

然后是各级任务

//1.lcd显示
void LCD_Process()
{
  u8 text[30];
  //主界面
  if(!lcd_display)
  {
  sprintf((char*)text,"       Data          ");
  LCD_DisplayStringLine(Line2,text);
    sprintf((char*)text,"   CNBR:%d          ",cnbr_num);
  LCD_DisplayStringLine(Line4,text);

  sprintf((char*)text,"   VNBR:%d          ",vnbr_num);
  LCD_DisplayStringLine(Line6,text);   

  sprintf((char*)text,"   IDLE:%d          ",(8-cnbr_num-vnbr_num));
  LCD_DisplayStringLine(Line8,text);   

  }
  //参数界面
  if(lcd_display==1)
  {
  sprintf((char*)text,"       Para          ");
  LCD_DisplayStringLine(Line2,text);
  sprintf((char*)text,"   CNBR:%0.2f          ",(cnbr_rate/10.0f));
  LCD_DisplayStringLine(Line4,text);
  sprintf((char*)text,"   VNBR:%0.2f          ",(vnbr_rate/10.0f));
  LCD_DisplayStringLine(Line6,text);   
  }
}
//2.按键功能
void KEY_Process()
{
   //10ms扫描一次
  if(uwTick - keyTick<10) return;
  
  keyTick = uwTick;
  Key_Read();
  //按键B1
  if(Trg & 0x01)
  {  
    LCD_Clear(Black);
    lcd_display =(lcd_display+1)%2;
  }
  //按键B2
   if(Trg & 0x02)
  {  
    //参数界面
     if(lcd_display ==1)
     {
       cnbr_rate+=5;
       vnbr_rate+=5;
     }
  } 
  //按键B3
     if(Trg & 0x04)
  {  
    //参数界面
     if(lcd_display ==1)
     { 
       cnbr_rate-=5;
       vnbr_rate-=5;
     }
  } 
  //按键B4
    if(Trg & 0x08)
  {  
    tim17_flag = !tim17_flag;
  }
  
}




//4.PWM占空比调节
void PWM_Process()
{
  if(tim17_flag)
  {
    TIM17->CCR1 = 100;
  }
  else
  TIM17->CCR1 = 0;     //0占空比即低电平
}

//5.led灯任务
void LED_Process()
{  
  if((8-cnbr_num-vnbr_num))
    led_ctrl |= 0x01;
  else
    led_ctrl &=  ~0x01;  
  
     if(tim17_flag)
    led_ctrl |= 0x02;
   else
    led_ctrl &=  ~ 0x02;
   
  LED_Control(led_ctrl);
}

串口任务单独写

//3.串口接收数据大小检查和定时清空接收
void RxIde_Process()
{
  if(uwTick- uartTick<50) return;
  uartTick = uwTick;
  //串口接收到数据但是没有22个
  if(rx_cnt>0 && (uart_flag ==0))
  {
    printf("error\r\n");
  }
  uart_flag = 0;     
  rx_cnt = 0;
  memset(uart_rx,'\0',sizeof(uart_rx));  //清空接收的数据
}
//检查数据合理性
_Bool check_String(u8 *str)
{
  u8 i;
  if((str[1]=='N') && (str[2]=='B') &&(str[3]=='R') && ((str[0]!='C')||(str[0]!='V'))&&(str[4]==':')&&(str[9]==':') )
  {

  for(i=10;i<=21;i++)
  {
   if(str[i]>'9' || str[i]<'0' )
   return 0;
  }
     year = (str[10] -'0')*10+(str[11] -'0');
     month = (str[12] -'0')*10+(str[13] -'0');
     day = (str[14] -'0')*10+(str[15] -'0');
     hour = (str[16] -'0')*10+(str[17] -'0');
     min = (str[18] -'0')*10+(str[19] -'0');
     sec = (str[20] -'0')*10+(str[21] -'0');
  
   if(year>99 || month >12 || day>31 ||hour >23||min>59||sec>59)
     return 0;
     
     year1 = year;
     month1 = month;
     day1 = day;
     hour1 = hour;
     min1 = min;
     sec1 = sec;
     return 1;
}
  return 0;
}

//判断是入车还是出车
u8 Judge(u8 *str)
{
  u8 i =0;
  for(i=0;i<8;i++)
  {
    if((str[0]==car_info[i].name[0])&&(str[1]==car_info[i].name[1])&&(str[2]==car_info[i].name[2])&&(str[3]==car_info[i].name[3]))
    {
    return (i+1);   //有名字相同的车辆,就返回相应的车库号,库号1-8,表示出库
    }
  }
  return 0;         //没有就返回零,表示入库
}
//判断进入第几个车库
u8 Indexes()
{
   u8 i =0;
  for(i=0;i<8;i++)
  {
     if(car_info[i].pos == 0)  //从低到高查每一个车库的状态
       return (i+1);
  }
  return 0;
}

//车辆入库,把数据写入结构体
void Write_enter()
{          
         car_info[car_indexes-1].type[0] = uart_rx[0];car_info[car_indexes-1].type[1] = uart_rx[1];car_info[car_indexes-1].type[2] = uart_rx[2];car_info[car_indexes-1].type[3] = uart_rx[3];
         car_info[car_indexes-1].name[0] = uart_rx[5];car_info[car_indexes-1].name[1] = uart_rx[6];car_info[car_indexes-1].name[2] = uart_rx[7];car_info[car_indexes-1].name[3] = uart_rx[8];
         car_info[car_indexes-1].year2 = year1;
         car_info[car_indexes-1].month2 = month1;
         car_info[car_indexes-1].day2 = day1;
         car_info[car_indexes-1].hour2= hour1;
         car_info[car_indexes-1].min2 = min1;
         car_info[car_indexes-1].sec2 = sec1;
         car_info[car_indexes-1].pos = 1;
}
//停车消耗的时间,不足一小时按一小时计算,不足一分按一分钟计算
void Write_out()
{
         year3= ((uart_rx[10]-'0')*10+(uart_rx[11]-'0'))-car_info[car_out-1].year2;
         month3 = ((uart_rx[12]-'0')*10+(uart_rx[13]-'0')) -car_info[car_out-1].month2;
         day3 = ((uart_rx[14]-'0')*10+(uart_rx[15]-'0'))-car_info[car_out-1].day2;
         hour3 = ((uart_rx[16]-'0')*10+(uart_rx[17]-'0'))-car_info[car_out-1].hour2;
         min3 = ((uart_rx[18]-'0')*10+(uart_rx[19]-'0'))-car_info[car_out-1].min2;
         sec3 = ((uart_rx[20]-'0')*10+(uart_rx[21]-'0'))-car_info[car_out-1].sec2;
          hour_all = (year3*365*25)+(month3*30*24)+(day3*24)+hour3;
         if(sec3>0)
         {
          min3++;
         }
         if(min3>0)
           hour_all++;
}
//串口接收回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
     uartTick = uwTick;
  
    uart_rx[rx_cnt++] = uart_buf[0];
  	HAL_UART_Receive_IT(&huart1,uart_buf,1);
    if(rx_cnt == 22) 
    {
     if(check_String(uart_rx)==0)
     {
      printf("error\r\n");
     }
     if(check_String(uart_rx)==1)
     {
       name1[0] = uart_rx[5];  //把串口接收的数据放入车辆名字中
       name1[1] = uart_rx[6];
       name1[2] = uart_rx[7];
       name1[3] = uart_rx[8];
       car_out = Judge(name1);
       if((Judge(name1)==0))  //判断入库
       {
         car_indexes = Indexes();  //判断第几号车库
         if(car_indexes!=0)        //有空闲车库
         {
         if(uart_rx[0] == 'C')     //判断那种类型车
         {
           cnbr_num++;
         }
         else 
         {
           vnbr_num++;
         }
         Write_enter();            //入库
         printf("car in\r\n");     //题目没有要求
       }
         else
           printf(" car is full\r\n"); //题目要求打印Error
         
       }
       
       else                           //出库
       {
         
            Write_out();             //计算停车的时间
          if(uart_rx[0] == 'C')
         {
           cnbr_num--;
           money_cnbr=hour_all*cnbr_rate;  //停车费用
           printf("%cNBR:%c%c%c%c:%d:%0.2f\r\n",car_info[car_out-1].type[0],car_info[car_out-1].name[0],car_info[car_out-1].name[1],
          car_info[car_out-1].name[1],car_info[car_out-1].name[3],hour_all,(money_cnbr/10.0f));
         }
         else 
         {
           vnbr_num--;
           money_vnbr=hour_all*vnbr_rate;   //停车费用
           printf("%cNBR:%c%c%c%c:%d:%0.2f\r\n",car_info[car_out-1].type[0],car_info[car_out-1].name[0],car_info[car_out-1].name[1],
           car_info[car_out-1].name[1],car_info[car_out-1].name[3],hour_all,(money_vnbr/10.0f));
         }
         memset(&car_info[car_out-1],0,sizeof(car_info[car_out-1]));   //清空数组内的数据

       }
     }
     rx_cnt = 0;
     uart_flag = 1;
    }
}

最后是主函数调用,要开启定时器通道和串口接收

  HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);  //开启定时器17pwm通道1
  TIM17->CCR1 = 0;                                
	HAL_UART_Receive_IT(&huart1,uart_buf,1);   //开启串口接收中断
	LCD_Init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	
	
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    LCD_Process();
    KEY_Process();
    RxIde_Process();
    PWM_Process();
    LED_Process();
  }

上述代码能实现最大部分功能,不过停车收费有bug,没有计算大小月各平年闰年,各位小伙伴有需要可以自行补充。

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值