蓝桥杯嵌入式STM32G431——第十二届第一场省赛停车计费系统真题及代码
生活随笔
收集整理的這篇文章主要介紹了
蓝桥杯嵌入式STM32G431——第十二届第一场省赛停车计费系统真题及代码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、第十二屆第一場省賽真題
2、解題思路整理
YYMMDDHHMMSS);車輛出停車場時的信息(車輛類型:車輛ID:出去時間年月日時分秒-YYMMDDHHMMSS)。
串口發送車輛出停車場時車輛信息、停車時間、停車費用(車輛類型:車輛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——第十二届第一场省赛停车计费系统真题及代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IAR移植FreeRTOS
- 下一篇: 项目汇报模板—再也不怕撕逼了