蓝桥杯嵌入式2011省赛模拟题 停车计费

一.赛题

本文的目的在于 记录下该次培训自己的经历以及习得的东西,顺便开源分享在网上,欢迎大家的阅读以及指点,该系列代码开源在git仓库中,如果出现找不到或者编译错误,无法下载的问题,欢迎评论区或者私信

在这里插入图片描述
在这里插入图片描述

二.思路分析

2.1 整体逻辑

  • 利用一个车位结构体,将其变成结构体数组模拟停车场。
  • 停车流程
    • 按键1按下时,使能停车信号(只有该信号为1时才能停车)。
    • 通过串口发送IDx给程序。程序解析这里的x,并检查x号停车位符不符合入库的要求(不符合的原因可能是,没有停车位了或者这个车位有车)
    • 成功停车后,记录下该位置的时分秒 将该位设置为已被占用
  • 出车流程
    • 按键2按下,使能出库信号(同上)
    • 同停车流程第二步
    • 成功停车后,计算该位置的钱 ( (当前小时-当前车辆的停车小时+1)* 费率 ),位置设置为未被占用
  • 费率以及灯设置
    • 串口接收到后,直接解析数据改变费率
    • 停车位不为0时,LED1亮,为0时LED2亮
    • 当没有停车位的时候key1又按下了,那么闪烁一下LED3
  • LCD显示设置
    • 当id不为0时,正常显示相应数据,id为0时,id显示x 时分秒默认为000

2.2 相关变量

  1. 时间部分 hour,sec,min不多说了
  2. parking_size停车场的10个车位 采用全局变量记录,这里没必要用线性表,麻烦了。
  3. 单个车位利用一个Parking_Space结构体表达,内置时分秒变量,以及该车位是否被使用的标志位,然后将其设置成10位的结构体数组即可。
  4. id变量,用来对应停车场结构体数组里的每一个具体车位。
  5. 入库使能信号和出库使能信号,在按键按下后生效,解析完数据后失能。
  6. rate费率,fee停车金额这些的也没什么特别的

示例

//车位结构体
struct Parking_Space{
	int hour;
	int min;
	int sec;
	int is_used;
};
//停车场
struct Parking_Space parking[10];
//剩余车位数
int parking_size = 10
//对应停车场里的车位
int id = 0;

2.3 相关函数

函数名就和他们的作用一样,处理各自对应的需求逻辑

void KEY_Control(void);		//按键控制
void LCD_Control(void);		//展示界面控制
void Led_Control(void);		//LED逻辑控制
void TIME_Control(void);	//时分秒的基础计时
void UART_Control(void);	//串口逻辑控制

void In_Disp(void);			//入车显示
void Out_Disp(void);		//出车显示
void USART_Rate_Control(void);//串口费率模式控制
void USART_Car_Control(void); //串口出入库控制

//停车场出入库控制 1入库 2出库 返回值为1表示成功
int Car_Control(int mode,int index_id);

三.源码部分解读

3.1 按键控制

这里大家可能会有点不理解为什么要有key_flag,和id置0的操作,没事,按键代码完后续马上解释。

void KEY_Control(){
    //按键1按下 有车位时
	if(KEY_Scan()==1 && parking_size != 0)
	{
        //按键按下时,串口还没输入ID 所以这里提取置0,界面就会展示还没输ID时的情况
		id = 0;
		LCD_Clear(White);
		key_flag = 1;	//对应界面标志位
		in_enable = 1;	//入库使能
		Uart_SendString("Appoint a in Id\r\n"); //串口发送提示
	}
    //按键1按下 无车位时
	if(KEY_Scan()==1 && parking_size == 0)
	{
		LED_Control(LED3,1);	
		HAL_Delay(500);
		LED_Control(LED3,0);
	}
    //按键2按下
	if(KEY_Scan()==2)
	{
		id = 0;
		LCD_Clear(White);
		key_flag=2;
		out_enable = 1;		//这些基本同上
		Uart_SendString("Appoint a out Id\r\n");
	}
}

3.2 显示部分

为何要有id置0和key_flag的切换?大家看这边就知道了。

//入库显示
void In_Disp(){
	LCD_DisplayStringLine(Line2," ID Code    Time");
	if(id!=0){
		sprintf(disp,"   %d      %02d:%02d:%02d",id,parking[id-1].hour,parking[id-1].min,parking[id-1].sec);
	}else{
		sprintf(disp,"   %s      %02d:%02d:%02d","x",0,0,0); //id为0时的展示界面
	}
	LCD_DisplayStringLine(Line4,(u8 *)disp);
	sprintf(disp,"           Rates:%d",rate);
	LCD_DisplayStringLine(Line8,(u8 *)disp);
}
//出库显示
void Out_Disp(){
	LCD_DisplayStringLine(Line2," ID Code    Fee");
	if(id!=0){
		sprintf(disp,"   %d        %2d",id,fee);
	} else {
		sprintf(disp,"   %s        %2d","x",0);
	}
	
	LCD_DisplayStringLine(Line4,(u8 *)disp);
	sprintf(disp,"           Rates:%d",rate);
	LCD_DisplayStringLine(Line8,(u8 *)disp);
}
//根据标志位展示界面
void LCD_Control(){
	if(key_flag==0){
		sprintf(disp,"           Rates:%d",rate);
		LCD_DisplayStringLine(Line8,(u8 *)disp);
	}
	if(key_flag==1){
		In_Disp();
	}
	if(key_flag==2){
		Out_Disp();
	}
}

3.3串口部分

前面的两个使能信号 很好的在串口控制出入库的地方发挥了作用。以及需要讲解一下这里为什么需要一个临时变量temp_id,而不是直接给id赋值

因为我们的id会直接影响lcd的显示,意味着这里的解析数据,如果直接给到id的话,屏幕就会更改。

可是这真的是我们想要的情况吗?不是的,因为这里解析出的数据不一定是正确数据。举个例子,1,3号库相继停入车辆,此时界面显示的是id为3的时候。

那如果这时我们又收到了1号库的停车请求,解析数据直接给id的话,那么显示界面就会显示id为1的车库了。可是这时我们的停车是失败的。

那么问题就出现了,停车失败,可是显示却按错误的id显示了

所以解决办法就是拿一个临时变量temp_id接收串口解析的数据,如果我们正确停车,该变量赋值给id,正常显示。如果停车失败,id维持原样

void USART_Car_Control(){
		int temp_id;
		if((UART1_Rx_Buf[3] - '0')== 0 && UART1_Rx_Buf[2] - '0'==1)
		{
				temp_id = 10;
		}
		else if(UART1_Rx_Buf[2] - '0' > 0 && UART1_Rx_Buf[3] - '0' <=9)
		{
				temp_id = UART1_Rx_Buf[2] - '0';
		}
		else{
				temp_id = 0;
		}
		if(key_flag==1)	
		{
			if(!in_enable)//如果还不是入库模式
			{
				Uart_SendString("In_Key not press\r\n");
				return;
			}
			in_enable = 0;				//失能入库
			if(Car_Control(1,temp_id))//调用出入库控制函数
			{
				id = temp_id;//停车成功 改变当前显示的ID
				sprintf(disp,"Park Success:ID%d\n",id);
				Uart_SendString(disp);
			}
			else
			{
				sprintf(disp,"Park Fail:ID%d\n",temp_id);
				Uart_SendString(disp);
			}
		}
		if(key_flag==2)	//基本同上
		{
			if(!out_enable)
			{
				Uart_SendString("Out_Key not press\r\n");
				return;
			}
			out_enable = 0;
			if(Car_Control(0,temp_id))
			{
				id = temp_id;
				sprintf(disp,"Go Out Success:ID%d\n",id);
				Uart_SendString(disp);
			}
			else
			{
				sprintf(disp,"Go Out Fail:ID%d\n",temp_id);
				Uart_SendString(disp);
			}
		}		
}

串口总控制部分 没有太多好说的。

void UART_Control(){
	if(UART1_Rx_flg==1)
	{
		if(UART1_Rx_Buf[0]=='I' && UART1_Rx_Buf[1]=='D') //ID解析出入库部分
		{
			USART_Car_Control();	//调用出入库串口控制
		}
		else if(UART1_Rx_Buf[0]=='F' && UART1_Rx_Buf[1]=='x')
		{
			USART_Rate_Control(); //调用费率串口控制
		}
		else
		{
			Uart_SendString("Error Command\n");//命令错误
		}
        //清空缓冲区和串口标志
		for(int i = 0;i<UART1_Rx_cnt;i++){
			UART1_Rx_Buf[i] = '\0';
		}
   		UART1_Rx_cnt = 0;
    	UART1_Rx_flg = 0;
	}
}

3.4 出入库部分

看注释即可 存入位置是index_id-1是因为,ID1对应的存入的是数组的0号位,以此类推

int Car_Control(int mode,int index_id){
	if(index_id < 1 || index_id > 10){
		return 0;
	}
	if(mode)//入库模式
	{
		if(parking_size==0){//如果没有车位
			return 0;
		}
		if(parking[index_id-1].is_used){//如果该车位已被使用
			return 0;
		}
		parking[index_id-1].hour = hour;
		parking[index_id-1].min  = min ;
		parking[index_id-1].sec  = sec ;
		parking[index_id-1].is_used  = 1;//设置车位被使用
		parking_size--;	//车位剩余数--
		return 1;
	}
	if(mode==0)//出库模式 基本同上
	{
		if(parking_size==10){
			return 0;
		}
		if(!parking[index_id-1].is_used){
			return 0;
		}
		fee = (1 + hour - parking[index_id-1].hour)*rate;//费用计算
		parking[index_id-1].is_used=0;
		parking_size++;
		return 1;
	}
	return 0;
}

剩下的部分较为简单,不做细讲,大家可以直接阅读源码,都在Gitee仓库上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这里煤球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值