STM32实战项目—停车计费系统

这篇具有很好参考价值的文章主要介绍了STM32实战项目—停车计费系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


🎀 文章作者:二土电子

🌸 关注文末公众号获取其他资料和工程文件!

🐸 期待大家一起学习交流!


题目原型是第十二届蓝桥杯嵌入式大学组省赛题目

本博客的工程会上传到个人资源,需要的小伙伴可以自行下载,仅供参考。

一、任务要求

1.1 概述

设计一个停车计费系统,使用串口获取车辆进/出停车场信息,并且能够输出计费信息。另外,也可以通过串口完成费率设置,调整功能。

1.2 串口收发

使用 4个任意ASCII 字符组成的字符串标识车辆,作为车辆编号。

1.2.1 串口输出内容

  • 当有车辆进入停车场时,串口输出停车类型,车辆编号和进入时间,举例如下
    停车类型:CNBR
    车辆编号:A392
    进入时间:2023.6.29-11:33:00
  • 当有车辆驶出停车场时,串口输出停车类型,车辆编号,推出时间和总计费用,举例如下
    停车类型:CNBR
    车辆编号:A392
    退出时间:2023.6.29-11:50:00
    停车时长:1小时(不满1小时,按1小时计算)
    总计费用:2元

1.2.2 串口接收内容

  • 调整费率
    上位机输入“CNBR(空格)Rate(空格)U”时,对应停车类型的费率升高0.5元/小时。
    上位机输入“CNBR(空格)Rate(空格)D”时,对应停车类型的费率下降0.5元/小时。
    每次调整成功后返回“OK!停车类型:当前费率”。比如CNBR降低0.5,串口会返回“OK!CNBR:0.5元/小时”。
  • 车辆进出
    有车辆进/出时,按照“停车类型:车辆编号:IN/OUT”的格式输入进/出车辆信息和停车类型。

1.3 说明

  • CNBR 类停车费率位 3.50元/小时,VNBR 类型停车费率位2.00元/小时。
  • 停车时长:整数,单位为小时,不足1小时,按 1小时统计。
  • 停车费用:以元为单位,按小时计费,保留小数点后2 位有效数字。
  • 系统收到入停车场信息后,不需要回复;接收到出停车场信息后,解析、计算并通过串口回复计费信息。
  • 当接收到的字符串格式不正确或存在逻辑错误,系统通过串口输出“Error!”。
  • 每一条串口指令都带有换行和回车。

二、实现思路

2.1 指令判别

这里总结一下上面提到的指令

  • 车辆进入
    “停车类型:车辆编号:IN”,停车类型两种,分别是CNBR和VNBR。车辆编号是任意的4个字符,IN表示进入。该指令加上换行和回车,总长度为14
  • 车辆驶出
    车辆驶出与进入的区别在于,车辆驶出指令最后为“OUT”。加上换行和回车,总长度为15
  • 费率调整
    按照规定,费率调整指令格式为“CNBR(空格)Rate(空格)U/D”,算上空格,换行和回车,总长度为13

经过分析发现,各个指令的长度是不同的,因此在做指令判别时,接收到的指令长度可以作为第一步筛选条件。对于小于和大于这三个长度的接收内容,按照要求,统一返回“Error”。当然,并不是说接收到的长度符合要求,接收到的指令就是有效的指令,后续还会有判别。

2.1 车辆进入

车辆进入需要获取的信息有三个,分别是停车类型,车辆编号和进入时间。首先在接收到消息后根据长度判断是否是车辆进入的消息长度,而且在接收数组中有“IN”。如果不是,不按照车辆进入处理。获取停车类型和车辆编号的方法是一位一位地从接收数组中提取,存储到一个二维数组中。二维数组的每一行代表一辆车。这里在有车辆进入时,会记录进入时刻的总秒数,方便后续总计费用的计算。

2.2 车辆驶出

有车辆驶出时,首先需要匹配车牌号,找到具体是哪辆车驶出。再根据车牌号索引匹配停车类型和驶入总秒数。然后获取驶出时的总秒数,计算总计费用。在车辆驶出时,不必再存储相关信息。车辆驶出后需要对之前存储的车辆信息重新整理,防止信息被覆盖。

2.3 费率调整

首先解析接收到的指令,判断费率增减。如果已经为0.5元/小时,无法继续降低。每次调整后,按照规定格式输出信息。

三、程序设计

首先需要配置好RTC和串口等外设,具体配置方法可以看博主的STM32速成系列,这里就不再做详细介绍了。

3.1 串口接收消息处理

上面说了,接收到指令后根据接收内容的长度和固定为的内容来确定是否为正确指令,不正确返回“Error!”。这里直接贴出程序,程序注释很详细,逻辑也比较简单,就不再赘述了。

extern u8 gCarInFlag;   // 车辆进入标志位
extern u8 gCarOutFlag;   // 车辆驶出标志位
extern u8 gRateAdjFlag;   // 费率调整标志位
extern u8 gInCarCunt;   // 进入车辆数量

void Uart_Rece_Pares(void)   // 串口接收内容解析函数
{
	// 分析接收内容长度
	// 有车辆进入
	if (gReceCount == 14 && gReceFifo[10] == 'I' && gReceFifo[11] == 'N')
	{
		gCarInFlag = 1;   // 车辆进入标志位置1
	}
	// 有车辆驶出
	else if (gReceCount == 15 && gReceFifo[10] == 'O' && gReceFifo[11] == 'U' && gReceFifo[12] == 'T')
	{
		gCarOutFlag = 1;   // 车辆驶出标志位置1
	}
	// 费率调整
	else if (gReceCount == 13 && gReceFifo[5] == 'R' && gReceFifo[6] == 'a' && gReceFifo[7] == 't'
		       && gReceFifo[8] == 'e')
	{
		gRateAdjFlag = 1;   // 费率调整标志位置1
	}
	// 非法指令
	else
	{
		printf ("Error!\r\n");   // 打印错误信息
	}
}

3.2 车辆驶入处理函数

有车辆驶入时,需要获取停车类型,车辆编号和进入时间。根据格式要求,在接收到的数组中,前四位是停车类型,中间是车辆编号。车辆驶入时间直接从RTC获得即可。程序设计如下

u8 gCarNumber[8][4];   // 8行4列二维数组,存放车牌号
u16 gCarInDate[8][6];   // 存储车辆驶入的年月日时分秒
u32 gCarInSec[8];   // 存储车辆进入时的总秒数
u8 gCarType[8][4];   // 存储停车类型

extern u32 gReceCount;   // 接收计数变量
extern u8 gReceFifo[20];   // 接收数组
u32 gClearCount = 0;   // 清空接收数组计数变量

extern _calendar calendar;   // RTC结构体

// 车辆进入处理函数
void CarIn (void)
{
	u8 tempVar = 0;   // 临时循环变量
	
	// 有车辆进入
	if (gCarInFlag == 1)
	{
		gInCarCunt = gInCarCunt + 1;   // 进入车辆数量加1
		
		// 解析停车类型
		for (tempVar = 0;tempVar < 4;tempVar ++)
		{
			gCarType[gInCarCunt - 1][tempVar] = gReceFifo[tempVar];
		}
		
		// 提取车牌号
		for (tempVar = 5;tempVar < 9;tempVar ++)
		{
			gCarNumber[gInCarCunt - 1][tempVar - 5] = gReceFifo[tempVar];
		}
		
		RTC_Get_CurDate();   // 获取当前年月日时分秒
		gCarInSec[gInCarCunt - 1] = RTC_GetCounter();   // 存储总秒数
		
		// 存储车辆进入年月日时分秒
		gCarInDate[gInCarCunt - 1][0] = calendar.w_year;
		gCarInDate[gInCarCunt - 1][1] = calendar.w_month;
		gCarInDate[gInCarCunt - 1][2] = calendar.w_date;
		gCarInDate[gInCarCunt - 1][3] = calendar.hour;
		gCarInDate[gInCarCunt - 1][4] = calendar.min;
		gCarInDate[gInCarCunt - 1][5] = calendar.sec;
		
		// 按照格式输出车辆进入信息
		printf ("停车类型:%c%c%c%c\r\n",gCarType[gInCarCunt - 1][0],gCarType[gInCarCunt - 1][1],
		        gCarType[gInCarCunt - 1][2],gCarType[gInCarCunt - 1][3]);
		printf ("车辆编号:%c%c%c%c\r\n",gCarNumber[gInCarCunt - 1][0],gCarNumber[gInCarCunt - 1][1],
		        gCarNumber[gInCarCunt - 1][2],gCarNumber[gInCarCunt - 1][3]);
		printf ("进入时间:%d.%d.%d-%d:%d:%d\r\n",gCarInDate[gInCarCunt - 1][0],gCarInDate[gInCarCunt - 1][1],
		        gCarInDate[gInCarCunt - 1][2],gCarInDate[gInCarCunt - 1][3],gCarInDate[gInCarCunt - 1][4],
						gCarInDate[gInCarCunt - 1][5]);
						
		gCarInFlag = 0;   // 清除车辆进入标志位
		Clear_Rece();   // 清空接收数组
	}
}

这里顺便记录一下车辆进入时的总秒数,方便后续总计费用的计算。

串口测试一下效果

STM32实战项目—停车计费系统,STM32开发笔记—实战项目,stm32,嵌入式硬件,单片机

3.3 车辆驶出处理函数

// 车辆驶出处理函数
void CarOut (void)
{
	u8 tempVar = 0;   // 临时循环变量
	u8 tempVar1 = 0;   // 临时循环变量
	u8 outCarNum = 0;   // 存储是第几辆车驶出
	u32 time = 0;   // 存储停车总秒数
	u32 hourCunt = 0;   // 小时数
	
	// 有车辆驶出
	if (gCarOutFlag == 1)
	{
		// 匹配车牌号
		for (tempVar = 0;tempVar < 8;tempVar ++)
		{
			for (tempVar1 = 5;tempVar1 < 9;tempVar1 ++)
			{
				if (gReceFifo[tempVar1] == gCarNumber[tempVar][tempVar1 - 5])
				{
					outCarNum = tempVar;
				}
			}
		}
		
		RTC_Get_CurDate();   // 获取当前年月日时分秒
		
		// 存储车辆驶出年月日时分秒
		gCarOutDate[0] = calendar.w_year;
		gCarOutDate[1] = calendar.w_month;
		gCarOutDate[2] = calendar.w_date;
		gCarOutDate[3] = calendar.hour;
		gCarOutDate[4] = calendar.min;
		gCarOutDate[5] = calendar.sec;
		
		// 计算停车时间
		// 计算方法是用驶出时间总秒数减去进入时间总秒数
		gCarOutSec = RTC_GetCounter();   // 获取车辆驶出时总秒数
		time = gCarOutSec - gCarInSec[outCarNum];   // 计算停车时间
		
		// 如果不足一小时,按照一小时计算
		while (time >= 3600)
		{
			time = time - 3600;
			hourCunt = hourCunt + 1;
		}
		if (time != 0)
		{
			hourCunt = hourCunt + 1;
		}
		
		// 根据停车类型计算总计费用
		if (gCarType[outCarNum][0] == 'C')
		{
			gTotalCost = (float)hourCunt * gCnbrRate;
		}
		else
		{
			gTotalCost = (float)hourCunt * gVnbrRate;
		}
		
		// 按照格式输出车辆驶出信息
		printf ("停车类型:%c%c%c%c\r\n",gCarType[outCarNum][0],gCarType[outCarNum][1],
		        gCarType[outCarNum][2],gCarType[outCarNum][3]);
		printf ("车辆编号:%c%c%c%c\r\n",gCarNumber[outCarNum][0],gCarNumber[outCarNum][1],
		        gCarNumber[outCarNum][2],gCarNumber[outCarNum][3]);
		printf ("驶出时间:%d.%d.%d-%d:%d:%d\r\n",gCarOutDate[0],gCarOutDate[1],
		        gCarOutDate[2],gCarOutDate[3],gCarOutDate[4],gCarOutDate[5]);
		printf ("停车时长:%d小时\r\n",hourCunt);
		printf ("总计费用:%.2f\r\n",gTotalCost);
		
		// 重新整理车辆信息
		// 如果驶出的车辆是最后一辆,那么不需要再重新整理车辆信息
		// 如果不是最后一辆,将存储的最后一条车辆信息填充到驶出车辆位置
		if (outCarNum != gInCarCunt - 1)
		{
			// 重新整理车牌号
			for (tempVar = 0;tempVar < 4;tempVar ++)
			{
				gCarNumber[outCarNum][tempVar] = gCarNumber[gInCarCunt - 1][tempVar];
			}
			
			// 重新整理驶入时间
			for (tempVar = 0;tempVar < 6;tempVar ++)
			{
				gCarInDate[outCarNum][tempVar] = gCarInDate[gInCarCunt - 1][tempVar];
			}
			
			// 重新整理驶入时的总秒数
			gCarInSec[outCarNum] = gCarInSec[outCarNum];
		}
		
		gInCarCunt = gInCarCunt - 1;   // 车辆数量减1
			
		gCarOutFlag = 0;   // 清除车辆驶出标志位
		Clear_Rece();   // 清空接收数组
	}
}

个人认为其中有两个地方值得注意一下。一个是计算总计费用的方法。并没有直接用除法计算,减少了运算时间。另一个是在每次车辆驶出后,需要先重新整理之前存储的车辆信息,然后再将总车辆数减1。否则,当在有车辆进入时,会覆盖之前存储的最后一条车辆信息。串口测试结果如下

STM32实战项目—停车计费系统,STM32开发笔记—实战项目,stm32,嵌入式硬件,单片机

3.4 费率调整处理函数

// 费率调整处理函数
void RateAdjust (void)
{
	// 收到费率调整指令
	if (gRateAdjFlag == 1)
	{
		// 判断是CNBR还是VNBR
		if (gReceFifo[0] == 'C')
		{
			// 判断是上调还是下调
			if (gReceFifo[10] == 'U')
			{
				gCnbrRate = gCnbrRate + 0.5;
			}
			else if (gReceFifo[10] == 'D')
			{
				// 判断是否可减
				if (gCnbrRate > 0.5)
				{
					gCnbrRate = gCnbrRate - 0.5;
				}
			}
			printf ("OK!CNBR:%.1f元/小时\r\n",gCnbrRate);   // 输出当前费率
		}
		if (gReceFifo[0] == 'V')
		{
			// 判断是上调还是下调
			if (gReceFifo[10] == 'U')
			{
				gVnbrRate = gVnbrRate + 0.5;
			}
			else if (gReceFifo[10] == 'D')
			{
				// 判断是否可减
				if (gVnbrRate > 0.5)
				{
					gVnbrRate = gVnbrRate - 0.5;
				}
			}
			printf ("OK!VNBR:%.1f元/小时\r\n",gVnbrRate);   // 输出当前费率
		}
		
		gRateAdjFlag = 0;   // 清除费率调整标志位
		Clear_Rece();   // 清空接收数组
	}
}

串口测试结果如下

STM32实战项目—停车计费系统,STM32开发笔记—实战项目,stm32,嵌入式硬件,单片机文章来源地址https://www.toymoban.com/news/detail-517292.html

到了这里,关于STM32实战项目—停车计费系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 自建云服务计费系统

            自从Laxcus分布式操作系统正式开源两个月以来,可能是它一站式云计算平台属性和超大规模计算能力,给用户带来极大的便利,下载量一直持续增加,最近网站后台总是有用户在问,在Laxcus分布式操作系统的社区版本基础上,编写一个计费系统,应该如何实现,分

    2024年02月03日
    浏览(25)
  • FPGA出租车计费系统设计

            设计一个简易的出租车计费系统,实现计价功能,计费标准为按里程收费, 起步价为6.00 元,当里程小于3公里时,按起步价收费, 超过3公里后按1.2元 /公里收费。         实现车辆行驶的模拟:能模拟汽车的 启动,暂停,停止 等状态。         计费显示部分设计

    2024年02月04日
    浏览(62)
  • 蓝海卓越计费管理系统远程命令执行

    活着,就要时刻准备承受磨难! 蓝海卓越计费管理系统存在命令调试页面,导致攻击者可以远程命令执行 访问 debug.php页面 远程调试命令执行 漏洞证明 文笔生疏,措辞浅薄,望各位大佬不吝赐教,万分感谢。 免责声明:由于传播或利用此文所提供的信息、技术或方法而造成

    2024年02月15日
    浏览(42)
  • STM32实战项目—楼宇人员计数系统

    🎀 文章作者:二土电子 🌸 关注文末公众号获取其他资料和工程文件! 🐸 期待大家一起学习交流! 本文项目比较简单,目的是介绍一下红外对管的使用,程序设计也比较简单。因此,博主并没有将程序工程上传资源,如果有需要的话可以私信。 使用两个平行的红外对管,

    2024年02月12日
    浏览(34)
  • 【功能超全】基于OpenCV车牌识别停车场管理系统软件开发【含python源码+PyqtUI界面+功能详解】-车牌识别python 深度学习实战项目

    摘要: 车牌识别系统(Vehicle License Plate Recognition,VLPR) 是指能够检测到受监控路面的车辆并自动提取车辆牌照信息(含汉字字符、英文字母、阿拉伯数字及号牌颜色)进行处理的技术。车牌识别是现代智能交通系统中的重要组成部分之一,应用十分广泛。本文详细介绍了 车牌

    2024年02月09日
    浏览(66)
  • STM32MP157开发板Linux+Qt项目实战:智慧家庭

    stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux+单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2个Cortex-A7核和1个Cortex-M4 核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统。开发板搭配仿真

    2024年02月09日
    浏览(51)
  • FreeRTOS小项目实战------基于FreeRTOS和stm32的门禁系统

    目录 收获 系统总体框架 程序框架 具体程序实现 工程文件网盘链接 收获 学习 freertos的移植与裁剪 ,对任务间通信的认识更加深刻,加深了实时操作系统的理解,学习了as608指纹模块,rc522刷卡模块等模块的简单使用。 系统总体框架 该系统采用STM32F407ZGT6为主控芯片,在Fre

    2024年02月02日
    浏览(47)
  • 应用于停车场的24小时计费算法

    停车场管理中,最普遍最简单的计费规则当属24小时计费,也就是在按停车小时数计费. 收费规则设置界面如下 24小时计费规则并不复杂,方法输入车辆进出时间startTime、endTime 参考代码Java

    2024年02月15日
    浏览(36)
  • STM32实战项目-串口打印

    前言: 本小结主要实现串口打印功能,主要将上一结的状态机运行次数,通过串口在串口终端上打印出来,硬件电路上主要是TTL转USB驱动电路,软件上主要有状态机函数,串口发送函数等调试工具是串口助手。 目录 1.硬件电路 2.串口讲解   2.1定义 2.2协议  3.软件编程 3.1参

    2024年02月16日
    浏览(40)
  • STM32实战项目—WIFI远程开关灯

    🎀 文章作者:二土电子 🌸 关注文末公众号获取其他资料和工程文件! 🐸 期待大家一起学习交流! 前言 其实WIFI开关灯在几个月前就想做了,但是对于没有云平台调试经验的我,一开始有些摸不着头脑,所以就搁置了。十一假期与老同学聊天时了解到他也在做一个远程开

    2024年02月03日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包