目录

省赛真题

错误点

1.LCD显示行数错误

2.LCD显示覆盖问题

3.NDA/B的计算问题

4.NHA/B的计算问题

模块化代码

按键代码

LCD显示代码

单位转换代码

LED代码


 

本篇文章用于记录我自写第十五届蓝桥杯嵌入式省赛真题的过程,记录我的一些错误以及成长!!!  如有错误可指正,也欢迎大家和我交流!!!

通过我的不断修改,最终在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);
}

 

 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐