蓝桥杯嵌入式第十二届程序设计题

news2025/3/31 3:27:57

一、题目概览

设计一个小型停车计费系统

二、分模块实现

1、LCD

void disp_proc()
{
	if(view==0)
	{
		char text[30];
		sprintf(text,"       Data");
		LCD_DisplayStringLine(Line2,(uint8_t *)text);
		
		sprintf(text,"   CNBR:%d           ",Cnum);
		LCD_DisplayStringLine(Line4,(uint8_t *)text);    
		sprintf(text,"   VNBR:%d           ",Vnum);
		LCD_DisplayStringLine(Line6,(uint8_t *)text);
		sprintf(text,"   IDLE:%d           ",idle-Cnum-Vnum);
		LCD_DisplayStringLine(Line8,(uint8_t *)text);
	}
	if(view==1)
	{
		char text[30];
		sprintf(text,"       Para");
		LCD_DisplayStringLine(Line2,(uint8_t *)text);
		
		sprintf(text,"   CNBR:%.2lf        ",Crate);
		LCD_DisplayStringLine(Line4,(uint8_t *)text);
		sprintf(text,"   VNBR:%.2lf        ",Vrate);
		LCD_DisplayStringLine(Line6,(uint8_t *)text);
	}
}

2、按键

Crate和Vrate分别是CNBR类型和VNBR类型停车的费率,按按键B3的减少我没有设置下限(仔细看了题目没要求),而且设置下限为零的话重新开始加的话两个费率就相等了。

void key_proc()
{
	if(key[0].single_flag==1)//B1
	{
		view=!view;
		LCD_Clear(Black);
		key[0].single_flag=0;
	}
	if(key[1].single_flag==1)//B2
	{
		if(view==1)
		{
			Crate+=0.5;
			Vrate+=0.5;
		}
		key[1].single_flag=0;
	}
	if(key[2].single_flag==1)//B3
	{
		if(view==1)
		{
			Crate-=0.5;
			Vrate-=0.5;
		}
		key[2].single_flag=0;
	}
	if(key[3].single_flag==1)//B4
	{
		state=!state;
		if(state==1)
		{
			HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
			__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,(20/100)*(80000000/80/2000));
			LED_state|=0x02;LED_Disp(LED_state);
		}
		else
		{
			HAL_TIM_PWM_Stop(&htim17,TIM_CHANNEL_1);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET);
			LED_state&=0xFD;LED_Disp(LED_state);
		}
		key[3].single_flag=0;
	}
}

3、PA7脉冲输出

 

4、串口通信(重点)

串口通信的基础代码我学习的是B站这个uart串口通信(完结)_哔哩哔哩_bilibili

 这个题目最关键的部分就是串口接收数据的处理,即对时间的解析算出停车时间

自定义的变量:

extern struct keys key[];
extern uint frq;
extern float duty;
bool view=0;
bool cnbr_flag=0;
bool vnbr_flag=0;

extern char rxdata[];
extern uint8_t rxdat;
extern int rx_point;//接收位指针

struct CarInfo
{
	char car_type[5];
	char car_num[5];
	char car_time[15];
}CNBRnum[10],VNBRnum[10];
int Cnum=0;
int Vnum=0;
int idle=8;
double Crate=3.50;
double Vrate=2.00;

uchar pa7_duty[2]={0,20};
uchar state=0;	//PA7端口输出状态
uchar LED_state=0x01;

// 定义结构体用于保存解析的时间  
typedef struct {  
    uint8_t year;  
    uint8_t month;  
    uint8_t day;  
    uint8_t hour;  
    uint8_t minute;  
} DateTime; 

void key_proc(void);
void disp_proc(void);
void uart_rx_proc(void);
void parse_time(char *time_str,DateTime *dt);
void calculate_time_difference(DateTime *start, DateTime *end, int *hours, int *minutes);

自定义的两个处理时间的函数: 

// 解析时间字符串
void parse_time(char *time_str,DateTime *dt)
{
	dt->year=2000+(time_str[0]-'0')*10+(time_str[1]-'0');
	dt->month=(time_str[2]-'0')*10+(time_str[3]-'0');
	dt->day=(time_str[4]-'0')*10+(time_str[5]-'0');
	dt->hour=(time_str[6]-'0')*10+(time_str[7]-'0');
	dt->minute=(time_str[8]-'0')*10+(time_str[9]-'0');
}
// 计算两个时间之间的差值  
void calculate_time_difference(DateTime *start, DateTime *end, int *hours, int *minutes) {  
    // 简化的差值计算,假设输入是有效的  
    int total_start_minutes = start->year * 525600 + start->month * 43800 + start->day * 1440 + start->hour * 60 + start->minute; // 1年=525600分钟  
    int total_end_minutes = end->year * 525600 + end->month * 43800 + end->day * 1440 + end->hour * 60 + end->minute;  

    int diff_minutes = total_end_minutes - total_start_minutes;  
    *hours = diff_minutes / 60;  
    *minutes = diff_minutes % 60;  
}  

串口接收数据的处理函数: 

void uart_rx_proc()
{
	if(rx_point>0)
	{
		if(rx_point==22)//接收的字符串定长为22
		{
			if(rxdata[0]=='C')//开头字母判断停车类型
			{
				sscanf(rxdata,"%4s:%4s:%12s",CNBRnum[Cnum].car_type,CNBRnum[Cnum].car_num,CNBRnum[Cnum].car_time);
				for(int i=0;i<Cnum;i++)
				{
					if(strcmp(CNBRnum[i].car_num,CNBRnum[Cnum].car_num)==0)//能匹配到一样的车辆编号说明这是出停车场的信息,反之是入停车库
						{
							DateTime start_time,end_time;
							parse_time(CNBRnum[i].car_time,&start_time);	//解析时间字符串,拆分成时、分、秒
							parse_time(CNBRnum[Cnum].car_time,&end_time);
							
							int hours,minutes;
							calculate_time_difference(&start_time,&end_time,&hours,&minutes);	//计算时间差
							if(minutes>0)hours+=1;
							double cost=Crate*hours;
							//串口输出计费信息
							char temp[30];
							sprintf(temp,"CNBR:%4s:%d:%.2lf\r\n",CNBRnum[i].car_num,hours,cost);
							HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);							
							Cnum-=1;
							
							for(int j=i;j<Cnum;j++) //前移
							{
								strncpy(CNBRnum[j].car_num,CNBRnum[j+1].car_num,strlen(CNBRnum[j].car_num));
								strncpy(CNBRnum[j].car_time,CNBRnum[j+1].car_time,strlen(CNBRnum[j].car_time));
								strncpy(CNBRnum[j].car_type,CNBRnum[j+1].car_type,strlen(CNBRnum[j].car_type));							
							}
							
							cnbr_flag = 1;
							break;
						}
				}
				if(cnbr_flag == 0)	//入车库
				{
					Cnum++;
				}
				cnbr_flag = 0;
			}
			if(rxdata[0]=='V')
			{
				sscanf(rxdata,"%4s:%4s:%12s",VNBRnum[Vnum].car_type,VNBRnum[Vnum].car_num,VNBRnum[Vnum].car_time);
				for(int i=0;i<Vnum;i++)
				{
					if(strcmp(VNBRnum[i].car_num,VNBRnum[Vnum].car_num)==0)
						{
							DateTime start_time,end_time;
							parse_time(VNBRnum[i].car_time,&start_time);
							parse_time(VNBRnum[Vnum].car_time,&end_time);
							
							int hours,minutes;
							calculate_time_difference(&start_time,&end_time,&hours,&minutes);
							if(minutes>0)hours+=1;
							double cost=Vrate*hours;
							
							char temp[30];
							sprintf(temp,"VNBR:%4s:%d:%.2lf\r\n",VNBRnum[i].car_num,hours,cost);
							HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);	
							Vnum-=1;
							
							for(int j=i;j<Vnum;j++) //前移
							{
								strncpy(VNBRnum[j].car_num,VNBRnum[j+1].car_num,strlen(VNBRnum[j].car_num));
								strncpy(VNBRnum[j].car_time,VNBRnum[j+1].car_time,strlen(VNBRnum[j].car_time));
								strncpy(VNBRnum[j].car_type,VNBRnum[j+1].car_type,strlen(VNBRnum[j].car_type));							
							}
							
							vnbr_flag = 1;
							break;
						}
				}
				if(vnbr_flag == 0)//入库
				{
					Vnum++;
				}
				vnbr_flag = 0;	
			}
			idle = 8-Cnum-Vnum;
			if(idle>0){LED_state|=0x01;LED_Disp(LED_state);}
			else{LED_state&=0xFE;LED_Disp(LED_state);}
		}
		else
		{
			char temp[20];
			sprintf(temp,"Error\n");
			HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);
		}
		rx_point=0;memset(rxdata,0,30);
	}
}

5、LED指示灯

LED1:(我写在了串口接收数据处理的函数里)

 

LED2: (写在了控制按键B3里面)

6、main

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  MX_TIM17_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();
	LED_Disp(0x00);
	
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	
	HAL_TIM_Base_Start_IT(&htim2);
	
	HAL_UART_Receive_IT(&huart1,&rxdat,1);
	
  /* USER CODE END 2 */
                                                                    
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(state == 0)
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET);
		LED_Disp(LED_state);
		
		if(rx_point!=0)            //防止接收不完整问题
		{
			int temp=rx_point;
			HAL_Delay(1);
			if(temp==rx_point) uart_rx_proc();
		}
		
		key_proc();
		disp_proc();
  }
  /* USER CODE END 3 */
}

三、总结

我使用的是数组的方式存储车辆信息,有车出停车场的情况我的思路是后面的车位‘往前移’,补空位,感觉这个方法有点笨笨的(T_T),so如果有其他思路请评论!!(*^_^*)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python多态、静态方法和类方法

目录 一、多态 二、静态方法 三、类方法 一、多态 多态&#xff08;polymorphism&#xff09;是面向对象编程中的一个重要概念&#xff0c;指的是同样的方法调用可以在不同的对象上产生不同的行为。在Python中&#xff0c;多态是通过方法的重写&#xff08;override&#x…

DTMF从2833到inband的方案

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 之前的文章中介绍过通过dialplan拨号计划配置的方法&#xff0c;实现2833到inband的转换&#xff0c;但是实际生产环境中的场景会更复杂&#xff0c;无法预先在dialplan中设置好相关参数和函数。 环境 CentOS 7.9 fr…

在Vue 3 + TypeScript + Vite 项目中安装和使用 SCSS

在Vue 3 TypeScript Vite 项目中安装和使用 SCSS 1、安装 SCSS 的相关依赖 npm install sass --save-dev2、配置 Vite 对于 Vue 3&#xff0c;Vite 已经内置了对 SCSS 的支持&#xff0c;通常不需要额外的配置。但是&#xff0c;如果需要自定义配置&#xff0c;可以在路径…

Uni-app入门到精通:tabBar节点实现多页面的切换

tabBar节点用于实现多页面的切换。对于一个多tabBar应用&#xff0c;可以通过tabBar节点配置项指定一级导航栏&#xff0c;以及tabBar切换时显示的对应页面。在pages.json中提供tabBar节点配置&#xff0c;不仅是为了方便快速开发导航&#xff0c;更重要的是提示App平台和小程序…

运筹说 第134期 | 矩阵对策的解法

上一期我们了解了矩阵对策的基本理论&#xff0c;包含矩阵对策的纯策略、矩阵对策的混合策略和矩阵对策的基本定理。 接下来小编将为大家介绍矩阵对策的解法&#xff0c;包括图解法、方程组法和线性规划法三种经典方法。 01 图解法 本节首先介绍矩阵对策的图解法&#xff0c;…

3. 轴指令(omron 机器自动化控制器)——>MC_CamOut

机器自动化控制器——第三章 轴指令 15 MC_CamOut变量▶输入变量▶输出变量▶输入输出变量 功能说明▶时序图▶指令的中止▶重启运动指令▶多重启动运动指令▶异常 MC_CamOut 结束通过输入参数指定的轴的凸轮动作 指令名称FB/FUN图形表现ST表现MC_CamOut解除凸轮动作FBMC_Cam…

TF32 与 FP32 的区别

TF32&#xff08;Tensor Float 32&#xff09;与FP32&#xff08;单精度浮点数&#xff09;是两种用于深度学习和高性能计算的浮点格式&#xff0c;其核心区别体现在精度、性能优化和应用场景上。以下是两者的详细对比分析&#xff1a; 一、位宽与结构差异 FP32的位宽结构 FP32…

【大模型】视觉语言模型:Qwen2.5-VL的使用

官方github地址&#xff1a;https://github.com/QwenLM/Qwen2.5-VL 目录 Qwen家族的最新成员&#xff1a;Qwen2.5-VL 主要增强功能 模型架构更新 快速开始 使用Transformers聊天 Docker Qwen家族的最新成员&#xff1a;Qwen2.5-VL 主要增强功能 强大的文档解析功能&am…

测试用例与需求脱节的修复方案

测试用例与需求脱节的问题可通过明确需求定义、加强需求追踪、建立有效沟通机制进行修复。其中&#xff0c;加强需求追踪尤为关键&#xff0c;能确保测试用例与实际需求的精确匹配&#xff0c;避免资源浪费和测试效果不佳。据行业研究&#xff0c;约70%的软件缺陷源于需求管理不…

【Unity】 鼠标拖动物体移动速度跟不上鼠标,会掉落

错误示范&#xff1a; 一开始把移动的代码写到update里去了&#xff0c;发现物体老是掉(总之移动非常不流畅&#xff0c;体验感很差&#xff09; void Update(){Ray ray Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out RaycastHit hit, M…

VLAN 高级特性

VLAN Access 类型端口&#xff1a;只能属于 1 个 VLAN&#xff0c;发出数据时只能根据 PVID 剥离一个 VLAN Tag 入方向&#xff1a;针对没有 tag 的数据包打上 PVID 的 tag出方向&#xff1a;将 tag 为本接口 PVID 的数据包去掉 tag&#xff0c;发出数据。&#xff08;只有在与…

学习中学习的小tips(主要是学习苍穹外卖的一些学习)

目录 架构的细分 使用实体类来接收配置文件中的值 webMvcConfig类&#xff1a; jwt令牌 管理端的拦截器&#xff1a; JwtProperties&#xff1a; JwtTokenAdminInterceptor &#xff1a; 对密码加密操作 Redis&#xff1a; 分页查询 整体思想 为什么动态 SQL 推荐传实体…

【极速版 -- 大模型入门到进阶】LORA:大模型轻量级微调

文章目录 &#x1f30a; 有没有低成本的方法微调大模型&#xff1f;&#x1f30a; LoRA 的核心思想&#x1f30a; LoRA 的初始化和 r r r 的值设定&#x1f30a; LoRA 实战&#xff1a;LoraConfig参数详解 论文指路&#xff1a;LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE M…

线程同步——读写锁

Linux——线程同步 读写锁 目录 一、基本概念 1.1 读写锁的基本概念 1.2 读写锁的优点 1.3 读写锁的实现 1.4 代码实现 一、基本概念 线程同步中的读写锁&#xff08;Read-Write Lock&#xff09;&#xff0c;也常被称为共享-独占锁&#xff08;Shared-Exclusive Lock&a…

邪性!Anaconda安装避坑细节Windows11

#工作记录 最近不断重置系统和重装Anaconda&#xff0c;配置的要累死&#xff0c;经几十次意料之外的配置状况打击之后&#xff0c;最后发现是要在在Anaconda安装时&#xff0c;一定要选“仅为我安装”这个选项&#xff0c;而不要选“为所有用户安装”这个选项。 选“仅为我安…

【大模型】激活函数之SwiGLU详解

文章目录 1. Swish基本定义主要特点代码实现 2. GLU (Gated Linear Unit)基本定义主要特点代码实现 3. SwiGLU基本定义主要特点代码实现 参考资料 SWiGLU是大模型常用的激活函数&#xff0c;是2020年谷歌提出的激活函数&#xff0c;它结合了Swish和GLU两者的特点。SwiGLU激活函…

AOA与TOA混合定位,MATLAB例程,三维空间下的运动轨迹,滤波使用EKF,附下载链接

本文介绍一个MATLAB代码&#xff0c;实现基于 到达角&#xff08;AOA&#xff09; 和 到达时间&#xff08;TOA&#xff09; 的混合定位算法&#xff0c;结合 扩展卡尔曼滤波&#xff08;EKF&#xff09; 对三维运动目标的轨迹进行滤波优化。代码通过模拟动态目标与基站网络&am…

【211】线上教学系统

--基于SSM线上教学平添 主要实现的功能有&#xff1a; 管理员 : 首页、个人中心、学员管理、资料类型管理、学习资料管理、交流论坛、我的收藏管理、试卷管理、留言板管理、试题管理、系统管理、考试管理。 学员 : 首页、个人中心、我的收藏管理、留言板管理、考试管理。 前台…

从混乱思绪到清晰表达:记录想法如何改变你的学习人生

关键要点 • 记录想法似乎是发现自己想法并将其组织成可传播形式的最佳理由&#xff0c;研究表明写作和教学能增强学习和理解。 • 证据倾向于支持写作有助于澄清思想&#xff0c;而教学通过“教授效应”深化知识。 • 教学和分享被认为是最有效的学习方法&#xff0c;这与记录…

电机控制常见面试问题(二十)

文章目录 一.整流电路绕组接法二.电机为什么需要转速器三.电机转矩产生原理四.电机控制中载波频率大小的确定五.开关周期 Tpwm 一.整流电路绕组接法 为了引出直流的输出&#xff0c;一定要在整流变压器的二次侧引出零线&#xff0c;所以二次侧绕组必须接成星形 一次绕组必须要…