一、前言:
这编文章意义不大,还有很多逻辑有待完善,比赛时还是建议优先实现功能,比如如何入库出库,而不是去花大量的时间去考虑接收字符串时间格式是否正确,比如像有没有超过24个小时,超过60分钟,或者是否都为数字字符这些,还有像字符串的长度是否正确,你如果要一一考虑的话需要太多的时间了,笔者已经是第二次做了,依旧花了快7个小时,而且评测时还不是一次就过的,还是需要看着错误修修改改才能满分。
二、题目展示:
三、具体实现:
1、头文件的相关定义与声明
#ifndef _code_h
#define _code_h
#include "stm32g4xx.h" // Device header
#include "stdio.h"
#include "string.h"
#include "stdint.h"
#include "main.h"
#include "gpio.h"
#include "lcd.h"
#include "tim.h"
#include "usart.h"
void lcd_proc(void);
void key_proc(void);
void led_proc(u8 led_x,u8 led_mode);
void usart_proc(void);
#endif
2、主函数的初始化
#include "code.h"
……
……
……
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
LCD_Init();
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
LCD_Clear(Black);
HAL_TIM_Base_Start(&htim2);
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
TIM17->CCR1=0;
extern u8 my_pData;
HAL_UART_Receive_IT(&huart1,&my_pData,1);
while (1)
{
lcd_proc();
key_proc();
usart_proc();
}
3、各个模块的实现
#include "code.h"
/*----------------------------lcd--------------------------------------*/
u8 ui;
char lcd_val[30];
u8 CNBR,VNBR,IDLE=8;
double CNBR_P=3.5,VNBR_P=2;
void lcd_proc(void)
{
if(ui==0)
{
sprintf(lcd_val," Data");
LCD_DisplayStringLine(Line1,(u8 *)lcd_val);
sprintf(lcd_val," CNBR:%d ",CNBR);
LCD_DisplayStringLine(Line3,(u8 *)lcd_val);
sprintf(lcd_val," VNBR:%d ",VNBR);
LCD_DisplayStringLine(Line5,(u8 *)lcd_val);
sprintf(lcd_val," IDLE:%d ",IDLE);
LCD_DisplayStringLine(Line7,(u8 *)lcd_val);
}
else
{
sprintf(lcd_val," Para");
LCD_DisplayStringLine(Line1,(u8 *)lcd_val);
sprintf(lcd_val," CNBR:%.2f ",CNBR_P);
LCD_DisplayStringLine(Line3,(u8 *)lcd_val);
sprintf(lcd_val," VNBR:%.2f ",VNBR_P);
LCD_DisplayStringLine(Line5,(u8 *)lcd_val);
}
led_proc(1,IDLE);
led_proc(2,TIM17->CCR1);
}
/*----------------------------key--------------------------------------*/
u8 key_val[4];
u8 key_old[4];
u8 key;
void key_proc(void)
{
for(u8 i=0;i<4;i++)
{
key_val[i]=HAL_GPIO_ReadPin(i<3?GPIOB:GPIOA,GPIO_PIN_0<<i%3);
}
for(u8 i=0;i<4;i++)
{
if(key_val[i]==0&&key_old[i]==1)
{
HAL_Delay(20);
if(key_val[i]==0&&key_old[i]==1)
{
key=i+1;
}
}
}
for(u8 i=0;i<4;i++)
{
key_old[i]=key_val[i];
}
switch(key)
{
case 1:
{
ui=!ui;
LCD_Clear(Black);
break;
}
case 2:
{
if(ui)
{
CNBR_P+=0.5;
VNBR_P+=0.5;
}
break;
}
case 3:
{
if(ui&&VNBR_P>0)
{
CNBR_P-=0.5;
VNBR_P-=0.5;
}
break;
}
case 4:
{
if(TIM17->CCR1==20)TIM17->CCR1=0;
else TIM17->CCR1=20;
break;
}
}
key=0;
}
/*----------------------------led--------------------------------------*/
void led_proc(u8 led_x,u8 led_mode)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
if(led_mode)
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led_x-1),GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led_x-1),GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
/*----------------------------usart--------------------------------------*/
u8 my_pData,count,rx_flag;
char rx_val[30];
char tx_val[30];
//VNBR:D583:20 0202 120000 == 22
struct Car_Data
{
char Type[5];
char Id[5];
char Time[13];
int Time_S;
}car[9];//8个车位,多出来的一位用来存放串口接收的临时数据
int Time_proc()
{
int time_S=0;
//年
time_S+=(car[8].Time[0]-'0')*10*360*24*3600;
time_S+=(car[8].Time[1]-'0')*360*24*3600;
//月
time_S+=(car[8].Time[2]-'0')*10*30*24*3600;
time_S+=(car[8].Time[3]-'0')*30*24*3600;
//日
time_S+=(car[8].Time[4]-'0')*10*24*3600;
time_S+=(car[8].Time[5]-'0')*24*3600;
//时
time_S+=(car[8].Time[6]-'0')*10*3600;
time_S+=(car[8].Time[7]-'0')*3600;
//分
time_S+=(car[8].Time[8]-'0')*10*60;
time_S+=(car[8].Time[9]-'0')*60;
//秒
time_S+=(car[8].Time[10]-'0')*10;
time_S+=(car[8].Time[11]-'0');
return time_S;
}
double Money(u8 time,u8 type)
{
if(!type)
return CNBR_P*time;
else
return VNBR_P*time;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rx_val[count]=my_pData;
TIM2->CNT=0;
count++;
rx_flag=1;
HAL_UART_Receive_IT(&huart1,&my_pData,1);
}
void usart_proc(void)
{
if(rx_flag==0)return;
if(TIM2->CNT<15)return;
sscanf(rx_val,"%4s:%4s:%12s",car[8].Type,car[8].Id,car[8].Time);
car[8].Time_S=Time_proc();
for(u8 i=0;i<8;i++)//判断是入库还是出库,即判断车俩是否已在车库
{
if(strcmp(car[8].Id,car[i].Id)==0)//已在车库则出库
{
int time=car[8].Time_S-car[i].Time_S,type=1;
if(time<=0)goto ERROR;
if(time%3600!=0)time+=3600;
if(strcmp(car[i].Type,"CNBR")==0)
{
CNBR--;
type=0;
}
else VNBR--;
IDLE++;
sprintf(tx_val,"%s:%s:%d:%.2f",car[i].Type,car[i].Id,time/3600,Money(time/3600,type));
HAL_UART_Transmit(&huart1,(u8*)tx_val,strlen(tx_val),50);
car[i].Type[0]='\0';
car[i].Id[0]='\0';
car[i].Time[0]='\0';
car[i].Time_S=0;
goto OK;
}
}
for(u8 i=0;i<8;i++)//寻找空位,入库操作
{
if(car[i].Type[0]==NULL)
{
car[i].Time_S=car[8].Time_S;
sscanf(rx_val,"%4s:%4s:%12c",car[i].Type,car[i].Id,car[i].Time);
if(strcmp(car[i].Type,"CNBR")==0)CNBR++;
else VNBR++;
IDLE--;
goto OK;
}
if(i==7)goto ERROR;
}
OK://操作成功处理
{
count=0;
rx_flag=0;
memset(rx_val,NULL,sizeof(rx_val));
return;
}
ERROR://错误处理
{
HAL_UART_Transmit(&huart1,(u8*)"Error",5,50);
count=0;
rx_flag=0;
memset(rx_val,NULL,sizeof(rx_val));
}
}
四、结语:
代码还需要很多的优化,尤其是时间的处理,虽然实现很快很简单,但也看起来傻傻的,参考意义不大。