【学习】蓝桥杯嵌入式:第七届预赛试题—液位检测告警系统

   日期:2021-03-15     浏览:114    评论:0    
核心提示:前言个人认为,比赛前做大量的练习,是非常必要的。然后如果想在嵌入式比赛中拿到好的成绩,关注我也很有必要,哈哈哈哈。下面上干货。一、题目重述功能描述二、系统设计分析思路:题目所给任务,进行逐级分析,分块实现。(下手角度因人而异)首先,我考虑的是先实现功能三,先实现按键控制功能切换。在按键切换功能完成的基础上,分别按照题目要求,进完善每个功能。我选择的是先从简单的入手。程序框架如下:void KEY_Cmd_Judge(void){ key_cmd_flag = KEY_Read(

前言
个人认为,比赛前做大量的练习,是非常必要的。我只放了一部分主要代码,思路还是挺清晰的。给大家创造的空间。如果想要源码,最下面也有途径。下面上干货。

一、题目重述


功能描述

二、系统设计分析

思路:题目所给任务,进行逐级分析,分块实现。(下手角度因人而异)

首先,我考虑的是先实现功能三,先实现按键控制功能切换。
在按键切换功能完成的基础上,分别按照题目要求,进完善每个功能。我选择的是先从简单的入手。

程序框架如下:

void KEY_Cmd_Judge(void)
{ 
	key_cmd_flag = KEY_Read();
	if(key_cmd_flag == 1)  
	{ 
		B1_Cmd_Processing();		//按键1://按键 B1 为设置键,按下后进入阈值设置显示界 面,再次按下时保存设置结果到 EEPROM,并返回液位检测显示界面。
	}
	else if(key_cmd_flag == 2)
	{ 
		B2_Cmd_Processing();		//按键2
	}
	else if(key_cmd_flag == 3)
	{ 
		B3_Cmd_Processing();	    //按键3
	}
	else if(key_cmd_flag == 4)
	{ 
		B4_Cmd_Processing();	    //按键4
	}
}

2、按键 B1

 实现切换阈值设置显示界面,和将设置阈值存入 EEPROM,并返回液位检测显示界面。
static void B1_Cmd_Processing(void)
{ 
		cmd1_flag++;
		//按键 B1 为设置键,按下后进入阈值设置显示界面,
		//再次按下时保存设置结果到 EEPROM,并返回液位检测显示界面
		if(cmd1_flag%2 == 1)
		{ 
			//阈值显示设置界面
			Threshold_Display();
		}
		if(cmd1_flag%2 == 0)
		{ 
			EEPROM_Write(); //写入数据
			LED_State(7);  //状态显示
			Liquid_Display();
		}
}

2、按键 B2

切换键,切换选择 3 个阈值,被选择的阈值突出显示。
static void B2_Cmd_Processing(void)
{ 
	//按键 B2 为切换键,切换选择 3 个阈值,被选择的阈值突出显示。
	//这个在设置阈值的时候,有所体现。
		cmd2_flag++;
		LCD_SetTextColor(Blue);
		
		Threshold_Display();
		if(cmd2_flag == 1)
		{ 
			LED_State(4);
			High1 = threshold;
		}
		else if(cmd2_flag == 2)
		{ 
			LED_State(5);
			High2 = threshold;
		}
		else if(cmd2_flag == 3)
		{ 
			LED_State(6);
			High3 = threshold;
		}
		else if(cmd2_flag == 4)
		{ 
			cmd2_flag = 0;
			LED_State(8);
		}
}

3、按键 B3

阈值加,每按一次,阈值增加 5cm,增加到 95cm 为止。
static void B3_Cmd_Processing(void)
{ 
		threshold += 5;
		if(threshold > 95)threshold = 95;//限定一定小于95
		
		if(cmd2_flag == 1)
		{ 
			High1 = threshold;
		}
		else if(cmd2_flag == 2)
		{ 
			High2 = threshold;
		}
		else if(cmd2_flag == 3)
		{ 
			High3 = threshold;
		}
		if(cmd1_flag%2 == 1) Threshold_Display();
}

4、按键 B4

 为加键,每按一次,阈值增减 5cm,增加到 5cm 为止。
static void B4_Cmd_Processing(void)
{ 
		threshold -= 5;
		if(threshold < 5)threshold = 5; //限定一定大于5
		
		if(cmd2_flag == 1)
		{ 
			High1 = threshold;
		}
		else if(cmd2_flag == 2)
		{ 
			High2 = threshold;
		}
		else if(cmd2_flag == 3)
		{ 
			High3 = threshold;
		}
		if(cmd1_flag%2 == 1) Threshold_Display();
}

5、子函数:一些框架内功能的实现

 LED状态显示函数
static void LED_State(uint8_t LED)
{ 
	switch(LED)
	{ 
		case 1:
		{ 
			LED_Control(LED1,1);
			LED_Control(LED2|LED3|LED4|LED5|LED6|LED7,0);
			break;
		}
		case 2:
		{ 
			LED_Control(LED2,1);
			LED_Control(LED1|LED3|LED4|LED5|LED6|LED7,0);
			break;
		}
		case 3:
		{ 
			LED_Control(LED3,1);
			LED_Control(LED2|LED1|LED4|LED5|LED6|LED7,0);
			break;
		}
		case 4:
		{ 
			LED_Control(LED4,1);
			LED_Control(LED2|LED1|LED3|LED5|LED6|LED7,0);
			break;
		}
		case 5:
		{ 
			LED_Control(LED5,1);
			LED_Control(LED2|LED1|LED3|LED4|LED6|LED7,0);
			break;
		}
		case 6:
		{ 
			LED_Control(LED6,1);
			LED_Control(LED2|LED1|LED3|LED5|LED4|LED7,0);
			break;
		}
		case 7:
		{ 
			LED_Control(LED7,1);
			LED_Control(LED2|LED1|LED3|LED5|LED6|LED4,0);
			break;
		}
		case 8:
		{ 
			LED_Control(LED2|LED1|LED3|LED5|LED6|LED4|LED7,0);
			break;
		}
		default:
		{ 
			break;
		}
	}
}
液面显示、阈值突出显示功能
void Liquid_Display(void)
{ 
	 //正常显示页面信息
		LCD_Clear(White);
		LCD_SetTextColor(Blue);
		
		VR_37 = (float)ADCConvertedValue*3.3/4096;
		High = Get_High(VR_37);
		Level = Get_Level(High);
	
		LCD_DisplayStringLine(Line1," Liquid Level ");
		sprintf((char*)Txt_Threshold," Height:%dcm ",High);
		LCD_DisplayStringLine(Line5,Txt_Threshold);
		sprintf((char*)Txt_Threshold," VR37: %1.2fv ",VR_37);
		LCD_DisplayStringLine(Line6,Txt_Threshold);
		sprintf((char*)Txt_Threshold," Level: %d ",Level);
		LCD_DisplayStringLine(Line7,Txt_Threshold);
}

void Threshold_Display(void)
{   
	//阈值重点显示
	LCD_Clear(White);
	if((cmd2_flag == 0)||(cmd2_flag == 4))
	{ 
		LCD_SetTextColor(Blue);
		LCD_DisplayStringLine(Line1," Threshold Setup ");
		sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
		LCD_DisplayStringLine(Line5,Txt_Threshold);
		sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
		LCD_DisplayStringLine(Line6,Txt_Threshold);
		sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
		LCD_DisplayStringLine(Line7,Txt_Threshold);
	}
	else if(cmd2_flag == 1)
	{ 
		LCD_SetTextColor(Blue);
		sprintf((char*)Txt_Threshold," threshold: %2dcm ",threshold);
		LCD_DisplayStringLine(Line9,Txt_Threshold);
		LCD_DisplayStringLine(Line1," Threshold Setup ");
		LCD_SetTextColor(Red);
		sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
		LCD_DisplayStringLine(Line5,Txt_Threshold);
		LCD_SetTextColor(Blue);
		sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
		LCD_DisplayStringLine(Line6,Txt_Threshold);
		sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
		LCD_DisplayStringLine(Line7,Txt_Threshold);
		
	}
	else if(cmd2_flag == 2)
	{ 
		LCD_SetTextColor(Blue);
		sprintf((char*)Txt_Threshold," threshold: %2dcm ",threshold);
		LCD_DisplayStringLine(Line9,Txt_Threshold);
		LCD_DisplayStringLine(Line1," Threshold Setup ");
		sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
		LCD_DisplayStringLine(Line5,Txt_Threshold);
		LCD_SetTextColor(Red);
		sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
		LCD_DisplayStringLine(Line6,Txt_Threshold);
		LCD_SetTextColor(Blue);
		sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
		LCD_DisplayStringLine(Line7,Txt_Threshold);
		
	}
	else if(cmd2_flag == 3)
	{ 
		LCD_SetTextColor(Blue);
		sprintf((char*)Txt_Threshold," threshold: %2dcm ",threshold);
		LCD_DisplayStringLine(Line9,Txt_Threshold);
		LCD_DisplayStringLine(Line1," Threshold Setup ");
		sprintf((char*)Txt_Threshold," Threshold1: %2dcm ",High1);
		LCD_DisplayStringLine(Line5,Txt_Threshold);
		sprintf((char*)Txt_Threshold," Threshold2: %2dcm ",High2);
		LCD_DisplayStringLine(Line6,Txt_Threshold);
		LCD_SetTextColor(Red);
		sprintf((char*)Txt_Threshold," Threshold3: %2dcm ",High3);
		LCD_DisplayStringLine(Line7,Txt_Threshold);
		
	}
}
液面高度转换,Level判断,EEPROM存储

float Get_High(float V)  //获取页面高度
{ 
	return (V/3.3)*100;
}

static uint8_t Get_Level(uint16_t H)  //获取页面高度
{ 
	uint8_t L_temp = 0;
	if(H<=High1)
	{ 
		L_temp = 1;
	}
	else if((H > High1) && (H <= High2))
	{ 
		L_temp =2;
	}
	else if((H > High2) && (H <= High3))
	{ 
		L_temp =3;
	}
	else if(H>High3)
	{ 
		L_temp = 4;
	}
	return L_temp;
}

void EEPROM_Read(void)
{ 
	//存储EEPROM数据 选前三个内存地址 存入 easy
	High1 = Byte_Read(0x00);
	High2 = Byte_Read(0x02);  //需要加延时么? 待测
	High3 = Byte_Read(0x04);
}
void EEPROM_Write(void)
{ 
	//存储EEPROM数据 选前三个内存地址 存入 easy
	Byte_Write(0x00,High1);
	Delay_Soft(0xffff);
	Byte_Write(0x02,High2);  //需要加延时时间 自行调试
	Delay_Soft(0xffff);
	Byte_Write(0x04,High3);
}

到此前三个任务已经完成

下面功能4:

串口查询与输出功能:中断实现
void USART2_IRQHandler(void)
{ 
	if(USART_GetITStatus(USART_PORT, USART_IT_RXNE) != RESET)
  { 
		Usart_temp = getchar();
		Usart_flag = 1;
		if(Usart_temp == 'C')
		{ 
			printf("C:\n High:%d Level:%d\r\n",High,Level);
		}
		if(Usart_temp == 'S')
		{ 
			printf("S:\n Threshold1:%d cm\n Threshold2:%d cm\n Threshold3:%d cm\n\r\n\n",High1,High2,High3);
		}
  }
	
	USART_ClearITPendingBit(USART_PORT,USART_IT_RXNE);
}

功能5

状态显示
void SysTick_Handler(void)
{ 
	
	Time_Handler_Display++;
	Time_Handler_LED2++;
	Time_Handler_LED3++;
	if(Time_Handler_Display == Liquid_Display_Time)
	{ 
		Time_Handler_Display = 0;
		if(cmd1_flag%2 == 0)
		{ 
			LED_Toggle(1);
			Liquid_Display();
		}	
	}
	
	if(Time_Handler_LED2 == LED2_Toggle_Time)  //不用每次都判断 0.2s判断一次就够了
	{ 
		Time_Handler_LED2 = 0;
		if(Level != Level_temp)
		{ 
			LED_Toggle(2);
			Level_temp_i++;
			Level_Change();
		}
	}
	
	if(Time_Handler_LED3 == LED3_Toggle_Time)  //不用每次都判断 0.2s判断一次就够了
	{ 
		Time_Handler_LED3 = 0;
		if(Usart_flag == 1)
		{ 
			LED_Toggle(3);
			Usart_i++;
			if(Usart_i == 10)  
			{ 
				Usart_flag = 0;
				Usart_i = 0;
			}
		}
	}
	
	if(TimeDelay_Ms != 0)
	{ 
		TimeDelay_Ms--;
	}
}

void USART2_IRQHandler(void)
{ 
	if(USART_GetITStatus(USART_PORT, USART_IT_RXNE) != RESET)
  { 
		Usart_temp = getchar();
		Usart_flag = 1;
		if(Usart_temp == 'C')
		{ 
			printf("C_cmd:\n High:%d Level:%d\r\n",High,Level);
		}
		if(Usart_temp == 'S')
		{ 
			printf("S_cmd:\n Threshold1:%d cm\n Threshold2:%d cm\n Threshold3:%d cm\n\r\n\n",High1,High2,High3);
		}
  }
	
	USART_ClearITPendingBit(USART_PORT,USART_IT_RXNE);
}

main.c

int main(void)
{ 
	ALL_Init();
	while(1)
	{ 
		KEY_Cmd_Judge();	
	}          
}

三、测试


led也是按照预期闪烁

四、总结:

主要用到的模块:ADC、EEPROM、USART、GPIO、Systick、LCD、KEY.

先整体搭建程序框架、逐步完善。关于LCD的显示倒没什么,主要是中间有一些细节,什么时候显示什么界面,需要底层判断,然后判断flag,然后就是ADC和串口的配置,需要熟练掌握。EEPROM注意在写入的时候,加延时,否则会出错。

工程源码:

私信即可
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服