【蓝桥杯嵌入式】第十五届蓝桥杯嵌入式省赛真题

原题展示 :

代码实现: 

数据定义: 

uint8_t display = 0;
uint8_t mode = 0;
int frea,freb,pera,perb,frea_m,freb_m;//频率0~1000	周期0~1000
float freA,freB,perA,perB;//频率 > 1000	周期 > 1000
int PD=1000,PH=5000,PX=0,NDA,NDB,NHA,NHB;
uint8_t select=0;
uint32_t count = 0;//计时
uint8_t count100ms_lcd,count100ms_flag,capture_flag;
float freqa_m,freqb_m;

LED相关:

void led_show(uint8_t led,uint8_t led_mode)
{	
	if(led_mode)
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led -1),GPIO_PIN_RESET);
	else
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led -1),GPIO_PIN_SET);
	
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

void led_offall()
{
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|
										GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
}

void led_fun(void)//LED灯显示
{
	if(display == 0)
		led_show(1,1);
	else
		led_show(1,0);
	
	if(frea > PH)
		led_show(2,1);
	else
		led_show(2,0);
	
	if(freb > PH)
		led_show(3,1);
	else
		led_show(3,0);
	
	if(NDA >= 3 || NDB >= 3)
		led_show(8,1);
	else
		led_show(8,0);
}

LCD相关:

char text[20];
void lcd_show()
{
	if(count100ms_lcd == 1)//100ms刷新LCD
	{
		switch(display)
		{
			case 0://数据界面
			{
				if(mode == 0)//频率显示模式
				{
					sprintf(text, "        DATA       ");
					LCD_DisplayStringLine(Line1,(uint8_t*)text);
					//第二行
					if(frea < 0)
						sprintf(text, "     A=NULL    ");
					else if(frea > 1000)
					{
						freA = (float)frea / 1000;
						sprintf(text, "     A=%.2fKHz   ",freA);
					}
					else
						sprintf(text, "     A=%dHz     ",frea);
					LCD_DisplayStringLine(Line3,(uint8_t*)text);
					//第三行
					if(freb < 0)
						sprintf(text, "     B=NULL  ");
					else if(freb > 1000)
					{
						freB = (float)freb / 1000;
						sprintf(text, "     B=%.2fKHz   ",freB);
					}
					else
						sprintf(text, "     B=%dHz      ",freb);
					LCD_DisplayStringLine(Line4,(uint8_t*)text);
				}
				else if(mode == 1)//周期显示模式
				{
					sprintf(text, "        DATA       ");
					LCD_DisplayStringLine(Line1,(uint8_t*)text);
					//第二行
					if(pera < 0)
						sprintf(text, "     A=NULL    ");
					else if(pera > 1000)
					{
						perA = (float)pera / 1000;
						sprintf(text, "     A=%.2fmS    ",perA);
					}
					else
						sprintf(text, "     A=%duS      ",pera);
					LCD_DisplayStringLine(Line3,(uint8_t*)text);
					//第三行
					if(perb < 0)
						sprintf(text, "     B=NULL    ");
					else if(perb > 1000)
					{
						perB = (float)perb / 1000;
						sprintf(text, "     B=%.2fmS    ",perB);
					}
					else
						sprintf(text, "     B=%duS      ",perb);
					LCD_DisplayStringLine(Line4,(uint8_t*)text);
				}
				sprintf(text, "                  ");
				LCD_DisplayStringLine(Line5,(uint8_t*)text);
				sprintf(text, "                  ");
				LCD_DisplayStringLine(Line6,(uint8_t*)text);
				break;
			}
			case 1://参数界面
			{
				sprintf(text, "        PARA       ");
				LCD_DisplayStringLine(Line1,(uint8_t*)text);
				sprintf(text, "     PD=%dHz    ",PD);
				LCD_DisplayStringLine(Line3,(uint8_t*)text);
				sprintf(text, "     PH=%dHz   ",PH);
				LCD_DisplayStringLine(Line4,(uint8_t*)text);
				sprintf(text, "     PX=%dHz    ",PX);
				LCD_DisplayStringLine(Line5,(uint8_t*)text);
				sprintf(text, "                  ");
				LCD_DisplayStringLine(Line6,(uint8_t*)text);
				break;
			}
			case 2://统计界面
			{
				sprintf(text, "        RECD       ");
				LCD_DisplayStringLine(Line1,(uint8_t*)text);
				sprintf(text, "     NDA=%d      ",NDA);
				LCD_DisplayStringLine(Line3,(uint8_t*)text);
				sprintf(text, "     NDB=%d     ",NDB);
				LCD_DisplayStringLine(Line4,(uint8_t*)text);
				sprintf(text, "     NHA=%d      ",NHA);
				LCD_DisplayStringLine(Line5,(uint8_t*)text);
				sprintf(text, "     NHB=%d      ",NHB);
				LCD_DisplayStringLine(Line6,(uint8_t*)text);
				break;
			}
		}
	}
}

按键相关:

uint8_t B1_state;
uint8_t B1_last_state;
uint8_t B2_state;
uint8_t B2_last_state;
uint8_t B3_state;
uint8_t B3_last_state;
uint8_t B4_state;
uint8_t B4_last_state;
void key_scan()
{
	B1_state = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
	B2_state = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
	B3_state = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
	B4_state = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
	if(B1_state == 0 && B1_last_state == 1)//B1按下  加
	{
		if(select == 0)//PD
		{
			PD += 100;
			if(PD > 1000)	PD = 100;
		}
		if(select == 1)//PH
		{
			PH += 100;
			if(PH > 10000)	PH = 1000;
		}
		if(select == 2)//PX
		{
			PX += 100;
			if(PX > 1000)	PX = -1000;
		}
	}
	if(B2_state == 0 && B2_last_state == 1)//B2按下  减
	{
		if(select == 0)//PD
		{
			PD -= 100;
			if(PD < 0)	PD = 1000;
		}
		if(select == 1)//PH
		{
			PH -= 100;
			if(PH < 1000)	PH = 10000;
		}
		if(select == 2)//PX
		{
			PX -= 100;
			if(PX < -1000)	PX = 1000;
		}
	}
	if(B3_state == 0 && B3_last_state == 1)//B3按下
	{
		if(display == 1)//参数界面  选择参数
		{
			select++;
			select %= 3;
		}
		else if(display == 0)//数据界面  模式切换
		{
			mode++;
			mode %= 2;
		}
		else if(display == 2)//记录界面
		{
			TIM4->CNT = 0;//按键长按计时
		}
	}
	else if(B3_state == 0 && B3_last_state == 0)//B3长按  清0
	{
		if(display == 2)
		{
			if(TIM4->CNT >= 10000)//1s 
			{
				NDA = 0;
				NDB = 0;
				NHA = 0;
				NHB = 0;
			}
		}
	}
	if(B4_state == 0 && B4_last_state == 1)//B4按下  界面切换
	{
		display++;
		display %= 3;
		if(display == 2)//记录界面
		{
			select = 0;
			mode = 0;
		}
			
	}
	B1_last_state = B1_state;
	B2_last_state = B2_state;
	B3_last_state = B3_state;
	B4_last_state = B4_state;
}

频率捕获:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//脉冲捕获中断
{
	if(htim->Instance == TIM2)
	{
		uint32_t capture_valuea;
		capture_valuea = TIM2->CCR1;
		TIM2->CNT = 0;
		frea_m = 80000000/(80*capture_valuea);//通道A频率
	}
	if(htim->Instance == TIM3)
	{
		uint32_t capture_valueb;
		capture_valueb = TIM3->CCR1;
		TIM3->CNT = 0;
		freb_m = 80000000/(80*capture_valueb);//通道B频率
	}
}

频率数据处理:

int max_a=0,min_a=20000,max_b=0,min_b=20000;
int frea_old=0,freb_old=0,PH_old=5000;
void freq_proc()//频率处理
{
	if(count100ms_flag)//每100ms进行更新频率数据
	{
		count100ms_flag=0;
		frea = frea_m+PX;//频率校准
		freb = freb_m+PX;
		pera = 1000000/(float)frea;//	1/fre = (s)  => 1000000/fre = (us)    周期初始单位为us
		perb = 1000000/(float)freb;
	}
	//频率超限
	if(frea_old != frea)//频率A改变
	{
		if(frea_old<PH && frea>PH)
		{
			NHA++;
		}
		frea_old = frea;
	}
	if(freb_old != freb)//频率B改变
	{
		if(freb_old<PH && freb>PH)
		{
			NHB++;
		}
		freb_old = freb;
	}
	if(PH_old!=PH)//参数PH改变
	{
		if(frea<PH_old && frea>PH)
		{
			NHA++;
		}
		if(freb<PH_old && freb>PH)
		{
			NHB++;
		}
		PH_old = PH;
	}
	//频率突变
	if(capture_flag) //3s计时
	{//static   3s内持续更新最大值,最小值
		if(frea>=0)
		{
			if(frea>max_a)
			{
				max_a=frea;
			}
			else if(frea<min_a)
			{
				min_a=frea;
			}
		}
		if(freb>=0)
		{
			if(freb>max_b)
			{
				max_b=freb;
			}
			else if(freb<min_b)
			{
				min_b=freb;
			}
		}		
	}
	else//统计完3s内的最大最小值 
	{
		capture_flag=1;
		if(max_a-min_a>PD && frea>=0)
		{
			NDA++;
		}
		if(max_b-min_b>PD && freb>=0)
		{
			NDB++;
		}
		//恢复初始化,以便在下一个3s 重新统计更新最大值,最小值
		max_a=0; 
		min_a=20000;
		max_b=0;
		min_b=20000;
	}
}

定时器:

uint32_t count3s,count100ms;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//100ms
{
	if(htim->Instance == TIM17)
	{
		count100ms++;
		if(count100ms>=10)//100ms
		{
			count100ms=0;
			count100ms_lcd=1;
			count100ms_flag=1;
		}
		
		if(capture_flag)
		{
			count3s++;
			if(count3s>=300)//5s
			{
				count3s=0;
				capture_flag=0;
			}
		}
	}
}

主函数: 

int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  MX_TIM17_Init();

	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	
	HAL_TIM_Base_Start(&htim4);
	HAL_TIM_Base_Start_IT(&htim17);
	HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
  while (1)
  {
	key_scan();
	lcd_show();
	freq_proc();
	led_fun();
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值