目录
1.赛题
2.分析
LED,按键,LCD显示较为简单,基本都有模版,可以参考:第十四届嵌入式方向省赛题解。重点分析串口功能:
1)接收数据的格式正确
2)接收数据的逻辑正确
3)接收数据的拆解:考虑到车辆入库,出库(判断出库的方法是在车库中可以找到该辆车),时间,价格计算等,需要将接收的数据拆解,用来登记或查询。
4)入库,出库判断,时间价格计算。——主要功能
5)需要用到的字符串函数有,strstr(),strcpy,strcmp(),sprintf();
strstr()——寻找字符串,并返回字符串起始地址
strcpy——复制字符串
stcmp——比较字符串,字符串相同返回0
sprintf——生成字符串
3.程序
先给出车库结构体数组
//为了节省空间,假设停车类型和车辆编号不重复,则不需要停车类型信息也可以完成功能
typedef struct{
u8 car_number[5]; //编号
u8 car_year;
u8 car_month;
u8 car_days;
u8 car_hour;
u8 car_minu; //分
u8 car_mins; //s
u8 empty; //empty = 0表示为空
}Car_message;
Car_message Car[8];
u8 i;
for(i = 0;i < ALL_Num;i++) //初始化阶段清空车库
memset(&Car[i],0,sizeof(Car_message));
3.1判断格式
u8 Judge_rule(u8 *Rx_Data)
{
char *p1,*p2;
if(strlen((char*)Rx_Data)!=24) return 0; //包含'/r/n'
p1 = strstr((char*)Rx_Data,"CNBR");
p2 = strstr((char*)Rx_Data,"VNBR");
if(p1== NULL && p2==NULL) return 0; //存在CNBR,VNBR其中一个
p1 = strstr((char*)Rx_Data,":"); //获取第一个冒号的地址
p2 = strstr(p1+1,":"); //获取第二个冒号的地址
if(p2-p1!=5) return 0; //p2-p1与5比较而不是与4比较,得到编号个数
return 1;
}
3.2判断逻辑
这里偷一下懒,主要是时间逻辑错误,如果考虑到闰年,闰月,year>365,month>12,day>31,hour>24等等,问题会很繁琐。因此只考虑出库时间<入库时间这一中错误。这一错误在进行时间计算时再进行判断。
3.3拆解字符串
这是非常关键的一步,将信息拆解后,对后续计算,信息登记等会有非常大的便利。可以减少工作量。
void Rx_Information(u8 *Rx_Data,u8* car_number,u8 *year,u8 *month,u8 *day,u8 *hour,u8 *minut,u8 *minus,u8 *car_type)
{
char *p1,*p2;
*year = (Rx_Data[10]-'0')*10+Rx_Data[11]-'0';
*month = (Rx_Data[12]-'0')*10+Rx_Data[13]-'0';
*day = (Rx_Data[14]-'0')*10+Rx_Data[15]-'0';
*hour = (Rx_Data[16]-'0')*10+Rx_Data[17]-'0';
*minut = (Rx_Data[18]-'0')*10+Rx_Data[19]-'0';
*minus = (Rx_Data[20]-'0')*10+Rx_Data[21]-'0';
p1 = strstr((char*)Rx_Data,":");
p2 = strstr(p1+1,":");
*p2 = '\0';
strcpy((char*)car_number,p1+1);
*p1 = '\0';
strcpy((char*)car_type,(char*)Rx_Data);
}
3.4入库,出库
void Judge_Out_In(u8 *Rx_Data)
{
u8 i,year,month,day,hour,minut,minus; //车辆信息
u8 car_number[5],car_type[5];
u8 string[20];
float fee;
int time;
Rx_Information(Rx_Data,car_number,&year,&month,&day,&hour,&minut,&minus,car_type);
for(i = 0;i<ALL_Num;i++) //出库
{
if(!strcmp((char*)car_number,(char*)Car[i].car_number)) //寻找车辆编号,找到则出库
{
time = (year-Car[i].car_year)*365*24*3600+(month-Car[i].car_month)*30*24*3600+(day-Car[i].car_days)*24*3600+(hour-Car[i].car_hour)*3600+(minut-Car[i].car_minu)*60+(minus-Car[i].car_mins);
if(time < 0) //时间出现逻辑错误
sprintf((char*)string,"Error\r\n");
else
{
time = (time+3599)/3600;
if(car_type[0] == 'C')
{
fee = time*cnbr_fee;
CNBR_Num--;
}
else
{
fee = time*vnbr_fee;
VNBR_Num--;
}
sprintf((char*)string,"%s:%s:%d:%.2f\r\n",car_type,car_number,time,fee);
memset(&Car[i],0,sizeof(Car_message)); //出库后,清除信息
}
HAL_UART_Transmit(&huart1,string,strlen((char*)string),0xFFFF);
return;
}
}
for(i = 0; i<ALL_Num;i++) //入库
{
if(Car[i].empty == 0) //寻找空位
{
strcpy((char*)Car[i].car_number,(char*)car_number);
Car[i].car_year = year;
Car[i].car_month = month;
Car[i].car_days = day;
Car[i].car_hour = hour;
Car[i].car_minu = minut;
Car[i].car_mins = minus;
Car[i].empty = 1;
if(car_type[0] == 'C')
CNBR_Num++;
else
VNBR_Num++;
break;
}
}
}
3.5串口主程序
void Rx_Pro()
{
if(Rx_flag == 1)
{
if(!Judge_rule(RxBuff)) //判断格式
{
HAL_UART_Transmit(&huart1,(u8*)"Error\r\n",strlen("Error\r\n"),0xFFFF);
}
else //入库出库处理
{
Judge_Out_In(RxBuff);
}
memset(&RxBuff,0,sizeof(RxBuff));
Rx_flag = 0;
Rx_cnt = 0;
}
}