1、第十二届第一场省赛真题





2、解题思路整理

  1. 本届赛题相较于往届赛题在串口部分有较为复杂的逻辑,想要解决还是需要下一番功夫的。首先除了串口模块,LED、LCD、按键、PA7输出频率固定、占空比固定的PWM这些模块都是基本的套路比较简单,先把这些逐个完成。
  2. 串口模块:串口接收车辆进入停车场的信息(车辆类型:车辆ID:进入时间年月日时分秒-
    YYMMDDHHMMSS);车辆出停车场时的信息(车辆类型:车辆ID:出去时间年月日时分秒-YYMMDDHHMMSS)。
    串口发送车辆出停车场时车辆信息、停车时间、停车费用(车辆类型:车辆ID:停车时间(小时-未满一小时按一小时计算):停车费用)。
  3. 初步判断串口接收在RX_BUF中的数据是否满足正确格式,例如:接收到的字符串长度为22、对应固定位置不改变的字符(CNBR、VNBR、:)正确、时间为0~9的数字。不满足格式则串口输出error。
  4. 如果初步判断字符符合正确格式,则开始对车辆信息进行处理。
  5. 当串口接收到一辆符合要求的车辆信息,通过车辆ID判断停车场中是否存在该车。
    如果存在则该车为出停车场;串口输出车辆信息、停车时间、停车费用。(停车时间、停车费用应当大于0,否则串口输出error);清空对应车位的车辆信息、将车位非空标志置0表示该车位空闲。由于一年中有12个月,每个月的天数不同,故可将月份转化为天数计算用来处理不同月份天数跨度下对应的停车时间。
    如果不存在则该车为入停车场,找空闲车位,将该车的车辆信息、进入时间存入对应车位的车辆信息、将车位非空标志置1表示该车位有车(当无空闲车位时,再有车辆进入则输出error)。

3、主函数部分代码

#include "main.h"
#include "rcc.h"
#include "led_key.h"
#include "lcd.h"
#include "tim.h"
#include "uart.h"//***子函数扫描速度控制变量区
__IO uint32_t uwTick_LED_Speed_Ctrl;
__IO uint32_t uwTick_KEY_Speed_Ctrl;
__IO uint32_t uwTick_LCD_Speed_Ctrl;
__IO uint32_t uwTick_UART_Speed_Ctrl;//***全局变量区
uint8_t ucLED;
uint8_t key_value,key_up,key_down;
static uint8_t key_old;uint8_t LCD_String_Disp[21];uint8_t RX_Buffer;
uint8_t RX_BUF[200];
uint8_t RX_Count;_Bool Interface_Ctrl = 0; //0-车位显示界面 1-费率设置界面
uint8_t CNBR_cost = 35; //上电默认3.50 此处对数据/10得所需要的费率
uint8_t VNBR_cost = 20; //上电默认2.00
_Bool B4_Ctrl = 0; //0-PA7处于低电平 1-PA7输出2KHz,20%占空比的PWM信号
uint8_t CNBR_count = 0;
uint8_t VNBR_count = 0;
uint8_t IDLE_count = 8; //上电默认空闲车位8个
float stop_car_cost; //停车费用
uint8_t year_365[12]={31,28,31,30,31,30,31,31,30,31,30,31};
uint8_t year_366[12]={31,29,31,30,31,30,31,31,30,31,30,31}; //闰年366天
uint16_t month_trans_day_temp; //各月份之间的天数//***子函数声明区***//
void SystemClock_Config(void);
void LED_Proc(void);
void KEY_Proc(void);
void LCD_Proc(void);
void UART_Proc(void);
_Bool CheckCmd(uint8_t *RX_str);
void sub_str(uint8_t *d_str,uint8_t *s_str,uint8_t locate,uint8_t length);
uint8_t find_locate(void);
uint8_t id_isExist(uint8_t *id_str);
uint16_t month_trans_day(uint8_t d_m,uint8_t s_m,uint8_t *month_a);//***定义结构体用于存储车辆的信息
typedef struct car_information
{uint8_t type_in[5]; //注意数组的大小加上结束符‘/0’uint8_t id_in[5]; uint8_t year;uint8_t month;uint8_t day;uint8_t hour;uint8_t min;uint8_t sec;_Bool notEmpty;}car_information_storage;car_information_storage car_num[9]; //分别对应8辆车的信息 定义9个空间防止数组越界 如果只有8个位置 当第九辆车进入会克卡死//***主函数区***//
int main(void)
{HAL_Init();SystemClock_Config();LED_KEY_Init();LCD_Init();LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);USART1_UART_Init();HAL_UART_Receive_IT(&huart1, (uint8_t *)(&RX_Buffer) ,1);TIM17_Init();while (1){LED_Proc();KEY_Proc();LCD_Proc();UART_Proc();}}//***LED控制子函数
void LED_Proc(void)
{if((uwTick - uwTick_LED_Speed_Ctrl)<200) return;uwTick_LED_Speed_Ctrl = uwTick;    //每200ms执行一次if(IDLE_count)ucLED |= 0x01;elseucLED &= 0x02;LED_Disp(ucLED);
}//**按键控制子函数
void KEY_Proc(void)
{if((uwTick - uwTick_KEY_Speed_Ctrl)<100) return;uwTick_KEY_Speed_Ctrl = uwTick;    //每100ms执行一次key_value = KEY_Scan();key_down = key_value & (key_value ^ key_old);key_up = ~key_value & (key_value ^ key_old);key_old = key_value;switch(key_down){case 1: //B1实现车位显示界面与费率设置界面的切换Interface_Ctrl ^= 1; //取异或 实现0-1来回切换
//          if(Interface_Ctrl == 0)
//              Interface_Ctrl = 1; //费率设置界面
//          else
//              Interface_Ctrl = 0; //车位显示界面LCD_Clear(Black); //清屏break;case 2: //B2-按下CNBR VNBR费率增加0.5if(Interface_Ctrl == 1) //在费率设置界面有效{CNBR_cost += 5;VNBR_cost += 5;}break;case 3: //B2-按下CNBR VNBR费率减少0.5if(Interface_Ctrl == 1) //在费率设置界面有效{if(VNBR_cost == 0){CNBR_cost = 15;VNBR_cost = 0;}else{CNBR_cost -= 5;VNBR_cost -= 5;}}break;case 4:B4_Ctrl ^= 1; //取异或 实现0-1来回切换break;}}//***LCD控制子函数
void LCD_Proc(void)
{if((uwTick - uwTick_LCD_Speed_Ctrl)<100) return;uwTick_LCD_Speed_Ctrl = uwTick;    //每100ms执行一次if(!B4_Ctrl) //PA7处于低电平{HAL_TIM_PWM_Stop(&htim17 , TIM_CHANNEL_1); __HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1, 0);//强制配置成低电平HAL_TIM_PWM_Start(&htim17 , TIM_CHANNEL_1);    ucLED &= 0x01;         }else //PA7输出2KHz,20%占空比的PWM信号{HAL_TIM_PWM_Stop(&htim17 , TIM_CHANNEL_1); //设置占空比为20%__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1, 100);//强制配置成PWMHAL_TIM_PWM_Start(&htim17 , TIM_CHANNEL_1);ucLED |= 0x02;}if(!Interface_Ctrl) //车位显示界面{memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "       Data");LCD_DisplayStringLine(Line1 , LCD_String_Disp);     memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "   CNBR:%1d",CNBR_count);LCD_DisplayStringLine(Line3 , LCD_String_Disp);       memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "   VNBR:%1d",VNBR_count);LCD_DisplayStringLine(Line5 , LCD_String_Disp);   memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "   IDLE:%1d",IDLE_count);LCD_DisplayStringLine(Line7 , LCD_String_Disp);       }else //费率设置界面{memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "       Para");LCD_DisplayStringLine(Line1 , LCD_String_Disp);       memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "   CNBR:%4.2f" , (float)CNBR_cost/10);LCD_DisplayStringLine(Line3 , LCD_String_Disp);      memset(LCD_String_Disp , 0 ,sizeof(LCD_String_Disp));sprintf((char*)LCD_String_Disp , "   VNBR:%4.2f" , (float)VNBR_cost/10);LCD_DisplayStringLine(Line5 , LCD_String_Disp);  }}//***串口控制子函数
void UART_Proc(void)
{if((uwTick - uwTick_UART_Speed_Ctrl)<100) return;uwTick_UART_Speed_Ctrl = uwTick;  //每100ms执行一次    //***在LCD上显示CheckCmd是否有效
//  memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
//  sprintf((char*)LCD_String_Disp, "%1d",CheckCmd(RX_BUF));
//  LCD_DisplayStringLine(Line8, LCD_String_Disp);  if(CheckCmd(RX_BUF)) //满足长度 类型 时间格式正确{uint8_t car_type[5]; //车的类型uint8_t car_id[5]; //车的IDuint8_t stop_locate = 0xff; //停车位置 默认无车辆uint8_t spare_locate; //空位uint8_t year_temp,month_temp,day_temp,hour_temp,min_temp,sec_temp;float time_count; //总秒数//***车辆出入停车场的对应的年月日时分秒字符->整型的转换year_temp = (RX_BUF[10]-0x30)*10+(RX_BUF[11]-0x30);month_temp = (RX_BUF[12]-0x30)*10+(RX_BUF[13]-0x30);day_temp = (RX_BUF[14]-0x30)*10+(RX_BUF[15]-0x30);hour_temp = (RX_BUF[16]-0x30)*10+(RX_BUF[17]-0x30);min_temp = (RX_BUF[18]-0x30)*10+(RX_BUF[19]-0x30);sec_temp = (RX_BUF[20]-0x30)*10+(RX_BUF[21]-0x30);//**判断时间格式是否正确if((month_temp>12)||(day_temp>30)||(hour_temp>23)||(min_temp>59)||(sec_temp>59)){printf("error\n"); //串口输出error}else //串口接收到一辆车的信息且全部正确后执行{//          printf("accpect\r\n");//将该车的类型与ID存入定义的数组中sub_str(car_type , RX_BUF , 0 ,4);sub_str(car_id , RX_BUF , 5 ,4);
//          printf("%s\n",car_id);            stop_locate = id_isExist(car_id); //判断对应的停车信息的有无 返回停车位置
//          printf("%d\n",stop_locate);if(stop_locate!=0xff) //停车位置不为0xff 有停车信息 该车辆已经进入停车场{//***对时间进行处理***////一年中12个月每个月的天数不一样 只需将对月份的时间处理转化为对天数的处理if(year_temp % 4 == 0) //闰年{month_trans_day_temp = month_trans_day(month_temp,car_num[stop_locate].month,year_366); //闰年2月份有29天}else{month_trans_day_temp = month_trans_day(month_temp,car_num[stop_locate].month,year_365);}time_count = (float)((year_temp-car_num[stop_locate].year)*365*24*3600)+(month_trans_day_temp*24*3600)+((day_temp-car_num[stop_locate].day)*24*3600)+((hour_temp-car_num[stop_locate].hour)*3600+(min_temp-car_num[stop_locate].min)*60+(sec_temp-car_num[stop_locate].sec)); //停车时间的总秒数time_count = (time_count + 3599)/3600; //转换为小时 未满1小时按一小时计费if(time_count < 0) //时间错误输出error{printf("error\n"); //串口输出error}else {if(car_type[0] == 'C'){CNBR_count--; //CNBR类型车辆-1stop_car_cost = (uint16_t)time_count*((float)CNBR_cost/10);}else if(car_type[0] == 'V'){VNBR_count--; //VNBR类型车辆-1stop_car_cost = (uint16_t)time_count*((float)VNBR_cost/10);}IDLE_count++; //空闲车位+1printf("%s:%s:%d:%.2f\n",car_type,car_id,(uint16_t)time_count,stop_car_cost); //串口输出车辆出停车场时的车辆信息、停车时间、停车费用}memset(&car_num[stop_locate] , 0 ,sizeof(car_num[stop_locate])); //表示车辆离开 该位置为车辆信息清空}else if(stop_locate == 0xff)//停车场中无该车辆{spare_locate = find_locate();  //判断是否有空闲车位
//              printf("%d\n",spare_locate);if(spare_locate!=0xff) //停车场有空位 将车辆信息存入对应的空位{sub_str(car_num[spare_locate].type_in , car_type , 0 ,4);
//                  printf("%s\n",car_num[spare_locate].type_in);sub_str(car_num[spare_locate].id_in , car_id , 0 ,4);
//                  printf("%s\n",car_num[spare_locate].id_in);                   car_num[spare_locate].year = year_temp;car_num[spare_locate].month = month_temp;car_num[spare_locate].day = day_temp;car_num[spare_locate].hour = hour_temp;car_num[spare_locate].min = min_temp;car_num[spare_locate].sec = sec_temp;car_num[spare_locate].notEmpty = 1; //置1 对应位置有车不为空if(car_type[0] == 'C'){CNBR_count++; //CNBR类型车辆+1}else if(car_type[0] == 'V'){VNBR_count++; //VNBR类型车辆+1}IDLE_count--; //空闲车位-1}else //停车场无空位串口输出error{printf("error\n");}}}}//完成一次串口数据接收RX_Count = 0; //串口接收字符个数清空memset((char*)RX_BUF , 0 ,sizeof(RX_BUF)); //中断接收数组清空 为下一次接收做1准备
}_Bool CheckCmd(uint8_t *RX_str)    //判断接收中断数据的有效性 长度是否满足 类型是否满足 时间为数字是否满足
{uint8_t i;if(RX_Count != 22)  //如果串口接收到的数据不是22个字符则不满足{return 0; }//***判断类型是否满足 对应位的固定符号是否满足if((RX_BUF[0]=='C'||RX_BUF[0]=='V')&&(RX_BUF[1]=='N')&&(RX_BUF[2]=='B')&&(RX_BUF[3]=='R')&&(RX_BUF[4]==':')&&(RX_BUF[9]==':')){    for(i=10;i<22;i++){//***判断第十位往后的是否为数字if((RX_BUF[i]>‘9’) {printf("error\n"); //串口输出errorreturn 0;}}}else //不满足类型或符号返回0{printf("error\n"); //串口输出errorreturn 0;}//格式全部满足返回1return 1;
}//***将目标字符串的值替换为源字符串中的值
void sub_str(uint8_t *d_str,uint8_t *s_str,uint8_t locate,uint8_t length)
{uint8_t i;for(i=0;i<length;i++){d_str[i] = s_str[locate+i];}d_str[length] = '\0'; //字符串的末尾需加入结束符 用于判别车辆id时使用的字符串比较函数}//***判断车辆id是否已进入停车场
uint8_t id_isExist(uint8_t *id_str) //如果已经存在于停车场则返回停车位置 否则返回0xff
{uint8_t i = 0;for(i=0;i<8;i++) {if((strcmp((const char*)id_str,(const char*)car_num[i].id_in))== 0){return i;}}return 0xff;
}//***找空闲的车位
uint8_t find_locate(void) //如果有空位返回空位位置 否则返回0xff
{uint8_t i;for(i=0;i<8;i++) {if(!car_num[i].notEmpty) //有空位返回对应空位{return i;}}return 0xff;
}//***时间处理子函数月份转换为天数
uint16_t month_trans_day(uint8_t d_m,uint8_t s_m,uint8_t *month_a)
{uint8_t i;uint16_t day_sum = 0;for(i=s_m-1;i<d_m-1;i++){day_sum = day_sum + month_a[i]; //将对应年数组中每个月对应天数累加}return day_sum;}//***串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{RX_BUF[RX_Count] = RX_Buffer;RX_Count++;HAL_UART_Receive_IT(&huart1, (uint8_t *)(&RX_Buffer) ,1);}//***printf重定向为串口输出
int fputc(int ch, FILE * f)
{char c = ch;HAL_UART_Transmit(&huart1 , (uint8_t *)&c , 1 ,50);return ch;
}//***测试数据 CNBR:3.50 VNBR:2.00//*VNBR:D583:220403121217 进
//*VNBR:D583:220503121217 出 30天 720小时 1440.00//*VNBR:D583:220303121217 进
//*VNBR:D583:220403121217 出 31天 744小时 1488.00//*VNBR:D583:220203121217 进
//*VNBR:D583:220303121217 出 28天 672小时 1344.00//*VNBR:D583:220228121216 进
//*VNBR:D583:220301121216 出 24小时 48.00元//*VNBR:D583:220303121216 进
//*VNBR:D583:220303121316 出 1小时 2.00元//*VNBR:D584:220303121216
//*VNBR:D584:220303131256 2小时 4.00元//*VNBR:D585:220303121216
//*VNBR:D585:220303141446 3小时 6.00元//*CNBR:D586:220303121313
//*CNBR:D586:220303131416 2小时 7.00元//*CNBR:D587:220303121513
//*CNBR:D587:220303141813 3小时 10.50元//*CNBR:D588:220303121216
//*CNBR:D588:220304121216 1天 25*3.50=84.00元//*CNBR:D589:220303121216
//*CNBR:D589:220303121219 1小时 3.50元//*CNBR:D590:220303121216
//*CNBR:D590:220303211446 10小时 35.00元

蓝桥杯嵌入式STM32G431——第十二届第一场省赛停车计费系统真题及代码相关推荐

  1. 蓝桥杯单片机第十二届第一场省赛--张三填坑

    Less interests.More interest. 蓝桥杯单片机第十二届第一场省赛--张三填坑 坑0 坑1 坑2 坑3 坑4 坑5 坑6 坑7 坑8 仅记录试题中可能存在的坑. 源码和PDF题 ...

  2. 【蓝桥杯嵌入式】第十二届蓝桥杯嵌入式省赛客观题及详细题解

    题1 解析: 波特率,指每秒钟传输码元符号的个数,对符号传输速率的一种度量,单位为1baud/s. 由于串口只有高低电平之分,即1码元等于1bit,即波特单位1baud和1bit等效,因此,此时的波特 ...

  3. 【蓝桥杯嵌入式】第十二届蓝桥杯嵌入式省赛程序设计试题以及详细题解

    原题展示     通读本试题后,可以知本试题所涉及到的模块有LCD显示.LED指示.按键切换.串口收发.定时器的PWM输出五个部分,试题的总体变化不大.在试题要求的所有功能中,串口这部分是侧重点,它既 ...

  4. 【STM32G4】备战蓝桥杯嵌入式---实战---第十二届嵌入式模拟赛

    文章目录 前言 一.题目 功能简述 二.模块初始化以及功能分析 1.模块的初始化 2.模块功能分析 三.函数实现 1.void Display(void); 2.uint8_t KEY_Scan(ui ...

  5. 蓝桥杯2021年第十二届省赛-杨辉三角形

    蓝桥杯2021年第十二届省赛真题-杨辉三角形 - C语言网 (dotcpp.com)https://www.dotcpp.com/oj/problem2610.html 参考: 2021第十二届蓝桥杯 ...

  6. 突击蓝桥杯嵌入式(七)——第十三届省赛第一场真题

    突击蓝桥杯嵌入式(七)--第十三届省赛第一场真题 一.题目概览 二.思路梳理 我们直接在LCD例程的基础上,改需增加的外设如下: LED灯(配置锁存器PD2),串口(波特率9600,带中断),按键4个 ...

  7. 2020年第11届蓝桥杯省赛Python组(真题+解析+代码):数字三角形

    大家好,我是爱分享的小蓝,欢迎交流指正~  1 真题 输入 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 输出 27 2 解析 难度系数:⭐⭐ 考察题型:动态规划 涉及知识点:模块 ...

  8. 第十二届蓝桥杯大赛软件类省赛第一场 Java 大学 B 组题目蓝桥杯JavaB组大赛软件类省赛第十二届第一场

    第十二届蓝桥杯大赛软件类省赛第一场 Java 大学 B 组题目 在线看题 题目PDF下载链接 百度云 链接:https://pan.baidu.com/s/1LSZvUV5dFwNtSbOshORU1 ...

  9. 蓝桥杯|2021第十二届蓝桥杯第二次模拟赛真题与解答[Java]

    记录2021年第十二届蓝桥杯第二次模拟赛真题与解题,部分答案来自网络.个人记录,菜得很. 目录 填空题 一 二 三 四 五 编程题 六 七 八 九 十 填空题 一 问题描述 请问在 1 到 2020 ...

  10. 蓝桥杯嵌入式STM32G431——第九届省赛真题电子定时器

    第九届省赛真题电子定时器 第九届省赛真题 主函数代码(不包含各模块初始化代码) 按键模块与LCD模块的逻辑图(仅供参考) 第九届省赛真题 主函数代码(不包含各模块初始化代码) #include &qu ...

最新文章

  1. iOS开发—block介绍
  2. JAVA的面向对象编程总结(第一部分)~
  3. 数据指标有哪些?什么是好的数据指标?
  4. [云炬Mysql数据库笔记] 第2章 数据库设计
  5. 网页结构的简介和Xpath语法的入门教程
  6. bzoj 1625: [Usaco2007 Dec]宝石手镯(01背包)
  7. 组态软件android版,昆仑通态组态软件
  8. 向量与直线,梯度与法向量,切向量
  9. H5与SCC3的新特性
  10. color 常用色值
  11. How to learn Japanese ?
  12. 【报告分享】2020年K12在线教育行业广告策略用户调研报告(附下载)
  13. 大家好,才是真的好「博客出书的故事②」
  14. 【语义分割】2021-PVT2 CVMJ
  15. Python爬取拉勾网数据分析职位
  16. C语言的函数到底是什么
  17. 基于arduino的ESP32 学习笔记(一) 基于ESP32的智能花盆
  18. VS错误代码列表之美
  19. 解决Perl TK 中文输入,操作问题
  20. 覃卫平java,广西外国语学院与柳州市柳江区实验高中、柳城县中学签订优质生源基地协议并圆满完成挂牌仪式...

热门文章

  1. 极域电子教室超级管理员密码
  2. 解决《Python源码剖析》扫描版PDF字体模糊问题
  3. Python代码编辑器jupyter的安装
  4. Lstm(循环神经网络)
  5. 电脑录音软件如何录制YY语音
  6. OJ在线编程常见输入输出JavaScript练习
  7. 软件工程 软件设计说明书模板
  8. QFIL的烧录、读写
  9. Java模拟银行转账(操作事务)
  10. 白云机场停车费一天要多少钱,广州白云机场t2航站楼最近停车场