第十五届蓝桥杯嵌入式省赛
本篇文章用于记录我自写第十五届蓝桥杯嵌入式省赛真题的过程,记录我的一些错误以及成长!!!如有错误可指正,也欢迎大家和我交流!!!通过我的不断修改,最终在4T网站上取得满分!
目录
本篇文章用于记录我自写第十五届蓝桥杯嵌入式省赛真题的过程,记录我的一些错误以及成长!!! 如有错误可指正,也欢迎大家和我交流!!!
通过我的不断修改,最终在4T网站上取得满分!
省赛真题






错误点
1.LCD显示行数错误
我觉得这是一个特别低级的错误,但是一旦犯了又有点难以发现,不过咱们主打一个早发现早改正,至少不是在比赛之后才醒悟
LCD的显示函数:void LCD_DisplayStringLine(u8 Line, u8 *ptr);
Line:代表需要显示的行数,范围是Line0------Line9,一共十行
我使用时默认以为Line1是第一行,所以导致测评的时候显示全部都是错误的
2.LCD显示覆盖问题
起初我在LCD上显示频率是是这样写的
sprintf(buf," A=%.2lfKHz",temp_A_frq);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
咋一看没有任何问题,但是实际运行时就出现了以下问题


最后使用填空空格的方式进行修正
sprintf(buf," A=%.2lfKHz ",temp_A_frq);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
还有界面与界面之间的显示也会有影响,所以在每一次通过按键切屏时都需要进行清屏
使用LCD_Clear(Black);函数进行清屏
if(KeyCNT < 1000) //按键被按下小于1秒被记为短按
{
if(key_up == 1 && LCD_Page == 2)
{
LCD_Clear(Black);
if(PARAFlag == 0)
{
PD = PD + 100;
}
if(PARAFlag == 1)
{
PH = PH + 100;
}
if(PARAFlag == 2)
{
PX = PX + 100;
}
KeyCNT_Flag = 0;
}
3.NDA/B的计算问题
题目当中对于NDA/NDB的概述如下

也就是说我们需要记录三秒内A通道和B通道的最大值和最小值并求其差值与PD做比较
uint32_t Afrq_max = 0; //用于记录A通道当前的频率
uint32_t Afrq_min = 20000; //用于记录A通道上一次的频率
uint32_t Atemp_PD = 0; //用于记录A通道计算得到的最大值和最小值的差值
uint32_t Bfrq_max = 0; //用于记录B通道当前的频率
uint32_t Bfrq_min = 20000; //用于记录B通道上一次的频率
uint32_t Btemp_PD = 0; //用于记录B通道计算得到的最大值和最小值的差值
void NDA_B_PD(uint32_t Afrq, uint32_t Bfrq)
{
if(Afrq_min == 0)
{
Afrq_min = 20000;
}
if(Bfrq_min == 0)
{
Bfrq_min = 20000;
}
//A通道的最大值记录
if(Afrq > Afrq_max)
{
Afrq_max = Afrq;
}
//A通道的最小值记录
if(Afrq < Afrq_min)
{
Afrq_min = Afrq;
}
//B通道的最大值记录
if(Bfrq > Bfrq_max)
{
Bfrq_max = Bfrq;
}
//B通道的最小值记录
if(Bfrq < Bfrq_min)
{
Bfrq_min = Bfrq;
}
//判断3s标志
if(Cnt3s >= 3000)
{
Cnt3s = 0;
Cnt3sFlag = 1;
}
//计算差值并记录
if(Cnt3sFlag == 1)
{
Cnt3sFlag = 0;
Atemp_PD = Afrq_max - Afrq_min;
Btemp_PD = Bfrq_max - Bfrq_min;
Afrq_max = 0;
Afrq_min = 0;
Bfrq_max = 0;
Bfrq_min = 0;
if(Atemp_PD > PD)
{
NDA = NDA +1;
}
if(Btemp_PD > PD)
{
NDB = NDB +1;
}
}
}
这里有几个点需要注意:
1)为了能得到最小值我们定义的Afrq_min和Bfrq_min必须是测量范围的最大值
2)为了能得到最大值我们定义的Afrq_max和Bfrq_max必须是测量范围的最小值或者直接定义为0
3)计算完差值之后,Afrq_min,Bfrq_min,Afrq_max和Bfrq_max必须赋值为0,以防干扰到下一次计算
4)我这里使用了以下语句,是因为我发现上电之后有一个瞬间读到的频率值为0,这样最小值就会一直为0,无法进行记录,我这也是一种投机取巧的办法·,大家有更好的办法可以和我分享一下
if(Afrq_min == 0)
{
Afrq_min = 20000;
}
if(Bfrq_min == 0)
{
Bfrq_min = 20000;
}
4.NHA/B的计算问题
一开始我并没有理解NHA/B的计数方式,导致一直判断错误
NHA/B的要求是A通道或者B通道的频率值先小于PH,再大于PH才可以增加
所以我使用了一个标志位,用标志A通道或者B通道的频率值是否小于PH,当标志位等于0时未小于PH,当标志位等于1时已经小于,再进行后续对频率值是否大于PH值的判断并增值,最后将标志位赋值为0,进行下一轮判断
uint8_t FlagPHA = 0; //PHA计时标志
uint8_t FlagPHB = 0; //PHB计时标志
void NHA_B_PH(uint32_t Afrq, uint32_t Bfrq)
{
if(Afrq < PH)
{
FlagPHA = 1;
}
if(Bfrq < PH)
{
FlagPHB = 1;
}
if((FlagPHA == 1) && (Afrq > PH))
{
FlagPHA = 0;
NHA = NHA + 1;
}
if((FlagPHB == 1) && (Bfrq > PH))
{
NHB = NHB + 1;
FlagPHB = 0;
}
}
模块化代码
按键代码
void Key_Long_or_Short(void) //根据按键长按短按执行相应操作
{
key_val = Key_Scan();
key_down = key_val & (key_val ^ key_old);
key_up = ~key_val & (key_val ^ key_old);
key_old = key_val;
if(key_down)
{
KeyCNT_Flag = 1;
}
if(KeyCNT < 1000) //按键被按下小于1秒被记为短按
{
if(key_up == 1 && LCD_Page == 2)
{
LCD_Clear(Black);
if(PARAFlag == 0)
{
PD = PD + 100;
}
if(PARAFlag == 1)
{
PH = PH + 100;
}
if(PARAFlag == 2)
{
PX = PX + 100;
}
KeyCNT_Flag = 0;
}
if(key_up == 2 && LCD_Page == 2)
{
LCD_Clear(Black);
if(PARAFlag == 0)
{
PD = PD - 100;
}
if(PARAFlag == 1)
{
PH = PH - 100;
}
if(PARAFlag == 2)
{
PX = PX - 100;
}
KeyCNT_Flag = 0;
}
if(key_up == 3)
{
if(LCD_Page == 1) //数据界面
{
LCD_Clear(Black);
DataFlag = !DataFlag;
}
if(LCD_Page == 2) //参数界面
{
PARAFlag++;
if(PARAFlag >=3)
{
PARAFlag = 0;
}
}
if(LCD_Page == 3) //记录界面
{
}
KeyCNT_Flag = 0;
}
if(key_up == 4)
{
PARAFlag = 0;
DataFlag = 0;
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
LCD_Page++;
if(LCD_Page > 3)
{
LCD_Page = 1;
}
KeyCNT_Flag = 0;
}
}
else //按键被按下大于1秒被记为长按
{
if(key_up == 1)
{
KeyCNT_Flag = 0;
}
if(key_up == 2)
{
KeyCNT_Flag = 0;
}
if(key_up == 3)
{
if(LCD_Page == 3)
{
NDA = 0;
NDB = 0;
NHA = 0;
NHB = 0;
}
KeyCNT_Flag = 0;
}
if(key_up == 4)
{
KeyCNT_Flag = 0;
}
}
}
LCD显示代码
void LCD_PageToggle(void) //LCD切换界面函数
{
double temp_A_cycle, temp_B_cycle, temp_A_frq, temp_B_frq;
if(LCD_Page == 1)
{
if(DataFlag == 0) //频率界面
{
//注意:LCD显示当中的第一行在Line0
LCD_DisplayStringLine(Line1,Str1);
if(A_frq >= 1000)
{
temp_A_frq = Hz_kHz(A_frq);
sprintf(buf," A=%.2lfKHz ",temp_A_frq);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
}
else if(A_frq < 0)
{
LCD_DisplayStringLine(Line3,A_NULL);
}
else
{
sprintf(buf," A=%dHz ",A_frq);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
}
if(B_frq >= 1000)
{
temp_B_frq = Hz_kHz(B_frq);
sprintf(buf," B=%.2lfKHz ",temp_B_frq);
LCD_DisplayStringLine(Line4,(uint8_t*)buf);
}
else if(B_frq < 0)
{
LCD_DisplayStringLine(Line4,B_NULL);
}
else
{
sprintf(buf," B=%dHz ",B_frq);
LCD_DisplayStringLine(Line4,(uint8_t*)buf);
}
}
if(DataFlag == 1) //周期界面
{
LCD_DisplayStringLine(Line1,Str1);
if(A_cycle >= 1000)
{
temp_A_cycle = US_MS(A_cycle);
sprintf(buf," A=%.2lfmS ",temp_A_cycle);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
}
else if(A_cycle < 0)
{
LCD_DisplayStringLine(Line3,A_NULL);
}
else
{
sprintf(buf," A=%duS ",A_cycle);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
}
if(B_cycle >= 1000)
{
temp_B_cycle = US_MS(B_cycle);
sprintf(buf," B=%.2lfmS ",temp_B_cycle);
LCD_DisplayStringLine(Line4,(uint8_t*)buf);
}
else if(B_cycle < 0)
{
LCD_DisplayStringLine(Line4,B_NULL);
}
else
{
sprintf(buf," B=%duS ",B_cycle);
LCD_DisplayStringLine(Line4,(uint8_t*)buf);
}
}
}
if(LCD_Page == 2)
{
LCD_SetBackColor(Black);
LCD_DisplayStringLine(Line1,Str2);
if(PARAFlag == 0)
{
LCD_SetBackColor(Green);
}
else
{
LCD_SetBackColor(Black);
}
sprintf(buf," PD=%dHz ",PD);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
if(PARAFlag == 1)
{
LCD_SetBackColor(Green);
}
else
{
LCD_SetBackColor(Black);
}
sprintf(buf," PH=%dHz ",PH);
LCD_DisplayStringLine(Line4,(uint8_t*)buf);
if(PARAFlag == 2)
{
LCD_SetBackColor(Green);
}
else
{
LCD_SetBackColor(Black);
}
sprintf(buf," PX=%dHz ",PX);
LCD_DisplayStringLine(Line5,(uint8_t*)buf);
}
if(LCD_Page == 3)
{
LCD_DisplayStringLine(Line1,Str3);
sprintf(buf," NDA=%d ",NDA);
LCD_DisplayStringLine(Line3,(uint8_t*)buf);
sprintf(buf," NDB=%d ",NDB);
LCD_DisplayStringLine(Line4,(uint8_t*)buf);
sprintf(buf," NHA=%d ",NHA);
LCD_DisplayStringLine(Line5,(uint8_t*)buf);
sprintf(buf," NHB=%d ",NHB);
LCD_DisplayStringLine(Line6,(uint8_t*)buf);
}
}
单位转换代码
double US_MS(uint32_t US)
{
double MS;
uint8_t ge, shi, bai, qian, wan;
ge = US % 10;
shi = US / 10 % 10;
bai = US / 100 %10;
qian = US / 1000 % 10;
wan = US / 10000;
MS = wan * 10 + qian + bai * 0.1 + shi * 0.01 + ge * 0.001;
return MS;
}
double Hz_kHz(uint32_t HZ)
{
double kHZ;
uint8_t ge, shi, bai, qian, wan;
ge = HZ % 10;
shi = HZ / 10 % 10;
bai = HZ / 100 %10;
qian = HZ / 1000 % 10;
wan = HZ / 10000;
kHZ = wan * 10 + qian + bai * 0.1 + shi * 0.01 + ge * 0.001;
return kHZ;
}
LED代码
void Led_Disp(uint8_t LED) //用于点亮LED,低电平点亮
{
//先给PC8-PC15进行赋值,再给PD2(高电平),
//将PC8~PC15端口状态传送到左侧1Q~8Q;
//在给PD2低电平,左侧1Q~8Q端口状态锁定
//在使指定灯亮之前,让所有灯灭
HAL_GPIO_WritePin(GPIOC,0xFF<<8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
//选择需要点亮的LED进行点亮
HAL_GPIO_WritePin(GPIOC,LED<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void LED_Action(void)
{
uint8_t Flag1 = 01, Flag2 = 0, Flag3 = 0, Flag8 = 1;
if(LCD_Page == 1)
{
Flag1 = 1;
}
else
{
Flag1 = 0;
}
if(A_frq > PH)
{
Flag2 = 1;
}
else
{
Flag2 = 0;
}
if(B_frq > PH)
{
Flag3 = 1;
}
else
{
Flag3 = 0;
}
if((NDA >= 3) || (NDB >= 3))
{
Flag8 = 1;
}
else
{
Flag8 = 0;
}
LED_Flag = (Flag1 * LED1) | (Flag2 * LED2) | (Flag3 * LED3) | (Flag8 * LED8);
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐




所有评论(0)