今天参加蓝桥杯嵌入式第二场线下比赛,总的来说,难度和第一场差不多,下面将我的思路,和代码随着对应解析分享给大家。
客观题答案---供参考
1.ABCD
2.B
3.A
4.A
5.C
6.BC
7.ABD
8.ABCD
9.A
10.ABD
tips:比赛期间五个小时临场发挥,如果大家对某些模块做题思路有更好的,欢迎留言,相互讨论!
目录
1.赛题分析
先贴赛题
接下来分析功能概述
1) 通过 E2PROM 完成商品库存数量以及商品单价的存储。
题目要求中当商品单价或者库存数量发生变化时,保存到eeprom,大家需要注意在SHOP界面下购买了商品,也要保存到eeprom中。然后题目初始化要求中,第一次上电需要显示对应的单价和库存数量,这个我的解决办法在建立一个校验的变量,读取eeprom其他位置的数值,通过和我设定的值进行比对,不相等判定为第一次上电,将单价设置为题目要求,否则读取对应值。
2) 通过串口打印输出购买商品购买数量、 总金额等信息。
1.这一部分比较简单,通过重定向c库函数printf到串口,使用Printf函数打印信息即可,
2.根据上位机发送字符'?',我是先检验接收字符数量,不为1,跳出检测,第二步就是检验字符是否为'?',是就调用printf打印相关信息。
3) 依试题要求,通过按键, 实现界面切换与控制功能。
难点就是判断库存数量进行商品数量加减以及保存修改的数据,容易实现。
4) 依试题要求,通过 LCD、 LED 完成数据显示和指示功能。
省略
二、解决方法(附模块代码)
按键处理函数:
void Key_Proc(void)
{
Key_refresh();
if(key_falling==B1)//B1按键-界面切换按键
{
Index=(Index+1)%3;
}
else if(key_falling==B2)//B2按键-“商品 X”
{
if(Index==SHOP)
{
(X_goumaiNum==X_kucunNum)?(X_goumaiNum=0):(X_goumaiNum++);
}
else if(Index==PRICE)
{
X_Oleddanjia=X_danjia;
(X_danjia==20)?(X_danjia=10):(X_danjia++);
if( X_danjia!=X_Oleddanjia)//代表单价有变化
{
Write_eeprom(2,X_danjia);//保存
Delay_Ms(5);
}
}
else if(Index==REP)
{
X_OledkucunNum=X_kucunNum;
X_kucunNum++;
if( X_OledkucunNum!=X_kucunNum)//代表单价有变化
{
Write_eeprom(0,X_kucunNum);//保存
Delay_Ms(5);
}
}
}
else if(key_falling==B3)//B3按键-“商品 Y”
{
if(Index==SHOP)
{
(Y_goumaiNum==Y_kucunNum)?(Y_goumaiNum=0):(Y_goumaiNum++);
}
else if(Index==PRICE)
{
Y_Oleddanjia=Y_danjia;
(Y_danjia==20)?(Y_danjia=10):(Y_danjia++);
if( Y_danjia!=Y_Oleddanjia)//代表单价有变化
{
Write_eeprom(3,Y_danjia);//保存
Delay_Ms(5);
}
}
else if(Index==REP)
{
Y_OledkucunNum=Y_kucunNum;
Y_kucunNum++;
if( Y_OledkucunNum!=Y_kucunNum)//代表单价有变化
{
Write_eeprom(1,Y_kucunNum);//保存
Delay_Ms(5);
}
}
}
else if(key_falling==B4)//B4按键 -"确认"
{
if(Index==SHOP)
{
Queren_flag=1;
flag_5s=1;
Y_kucunNum=Y_kucunNum-Y_goumaiNum;//更新库存数量
X_kucunNum=X_kucunNum-X_goumaiNum;//更新库存数量
// 输出计费信息
printf("X:%d,Y:%d,Z:%d.%d\r\n",X_goumaiNum,Y_goumaiNum,\
((X_goumaiNum*X_danjia)+(Y_goumaiNum*Y_danjia))/10,\
((X_goumaiNum*X_danjia)+(Y_goumaiNum*Y_danjia))%10);
if(X_goumaiNum!=0)//代表数量有变化
{
Write_eeprom(0,X_kucunNum);//保存
Delay_Ms(5);
}
if(Y_goumaiNum!=0)//代表数量有变化
{
Write_eeprom(1,Y_kucunNum);//保存
Delay_Ms(5);
}
X_goumaiNum=0;//商品购买界面下xy清0
Y_goumaiNum=0;//商品购买界面下xy清0
}
}
}
是否第一次上电存储对应代码
/*
* @brief 系统参数初始化函数
* @param 无
* @retval 无
*/
void SystemPara_Init(void)
{
verify=Read_eeprom(4);
if(verify!=10)//随便设定一个数,总没有那么巧吧,哈哈哈,不等就认为第一次上电
{
Write_eeprom(0,10);//保存
Delay_Ms(5);
Write_eeprom(1,10);//保存
Delay_Ms(5);
Write_eeprom(2,10);//保存
Delay_Ms(5);
Write_eeprom(3,10);//保存
Delay_Ms(5);
Write_eeprom(4,10);//赋值为10,此段函数只执行一次
Delay_Ms(5);
}
X_kucunNum=Read_eeprom(0);
Y_kucunNum=Read_eeprom(1);
X_danjia =Read_eeprom(2);
Y_danjia =Read_eeprom(3);
Index=SHOP;
X_goumaiNum=0;
Y_goumaiNum=0;
}
串口解析代码
/**
* @brief 串口处理函数
* @attention 无
* @retval 无
*/
void Usart_Proc(void)
{
if(RxoverFlag==1)
{
RxoverFlag=0;
StringCheck();
memset(RxBuffer,0,sizeof(RxBuffer));
RxCounter=0;
}
}
/**
* @brief 字符串检查函数
* @attention 判断数据长度,格式是否正确
* @retval 无
*/
void StringCheck(void)
{
uint8_t i=1;
while(i)
{
if(RxCounter!=1)//长度不正确
{
break;
}
if(RxBuffer[0]=='?')
{
printf("X:%d.%d,Y:%d.%d\r\n",X_danjia/10,X_danjia%10,Y_danjia/10,Y_danjia%10);
}
break;
}
}
三、代码(完整代码,功能全部实现,附有注释)
lanqiaobei_qianrushi/main.c at main · AMingKL/lanqiaobei_qianrushi (github.com)
baidu链接:https://pan.baidu.com/s/1ZDl7TMPUWcOaTjrqwT8KSQ
提取码:amkl