#蓝桥杯嵌入式#第七届预赛:液位检测告警系统

#蓝桥杯嵌入式#第七届预赛:液位检测告警系统_第1张图片
#蓝桥杯嵌入式#第七届预赛:液位检测告警系统_第2张图片

初始化文件可以参考之前的

  • 首先是最基础的ADC转换,得到ADC的值的函数之前基础模块配置那以及写过
u16 get_ADC()
{
     
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
	return ADC_GetconversionValue(ADC1);
}
  • 那么便能得到液位高度H和电压VR37
float value, VR37;
u8 h;
value = 1.0 * get_ADC() / 4096;
VR37 = 3.3 * value;
h = 100 * value;
  • 其中等级需要根据阈值确定,阈值需要IIC读写,因此:
u8 Threshod[3]={
     10,20,30}
//写函数
void EEPROMRefresh()
{
     
	EPROM_Write(0x00, Threshold[0]);
	Delay_Ms(5);
	EPROM_Write(0x01, Threshold[1]);
	Delay_Ms(5);
	EPROM_Write(0x02, Threshold[2]);
	Delay_Ms(5);
	EPROM_Write(0x03, 0xAB);
}

//读
if(EPROM_Read(0x03) == 0xAB)
{
     
	Delay_Ms(2);
	Threshold[0] = EPROM_Read(0x00);
	Delay_Ms(2);
	Threshold[1] = EPROM_Read(0x01);
	Delay_Ms(2);
	Threshold[2] = EPROM_Read(0x02);
}
  • 读取到阈值以后就可以进行等级计算了,注意,由于后面需要等级变化,所以我们这里要设置一个变量记录最新的等级
u8 level, last_lecel;
u8 flag = 1;
if(h <= Threshold[0]) level = 0;
else if(h > Threshold[0] && h <= Threshold[1]) level = 1;
else if(h > Threshold[1] && h <= Threshold[2]) level = 2;
else if(h > Threshold[2]) level = 3;
if(flag)
{
     
	last_level = level;
	flag = 0;
}
  • 接下来是第一问和第二问的LCD显示,通过按键切换,我们这里设置一个变量Mode进行切换即可,注意,按键2有高亮显示的功能
void ShowThreshold(u8 type, u8 line)
{
     
	u8 index;
	if(line == Line2)
		index = 0;
	else if(line == Line3)
		index = 1;
	else if(line == Line4)
		index = 2;
	
	sprintf((char*)str, "Threshold %d: %d", index + 1, Threshold[index]);
	if(type)
	{
     
		LCD_SetTextColor(Green);
		LCD_DisplayStringLine(line, str);
		LCD_SetTextColor(Black);
	}
	else
		LCD_DisplayStringLine(line, str);
}

u8 LCD_Mode = 0;
u8 str[20];
if(!LCD_Mode)
{
     
	LCD_DisplayStringLine(Line1, (unsigned char*)"Liguid Level");
	sprintf((char*)str, "Height:%dcm", h);
	LCD_DisplayStringLine(Line2, str);
	sprintf((char*)str, "VR37:%.2lfV", VR37);
	LCD_DisplayStringLine(Line3, str);
	sprintf((char*)str, "Level:%d", level);
	LCD_DisplayStringLine(Line4, str);
}
else
{
     
	LCD_DisplayStringLine(Line1, (unsigned char*)"Threshold Setup");
	ShowThreshold(line == 0? 1 : 0, Line2);
	ShowThreshold(line == 1? 1 : 0, Line3);
	ShowThreshold(line == 2? 1 : 0, Line4);
}
  • 接下来是按键功能
  • 之前写过的按键循环扫描:
#define BTN1 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
#define BTN2 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)
#define BTN3 GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)
#define BTN4 GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2)
u8 Key_Scan()
{
     
	static u8 key = 1;
	if(key && (!BTN||!BTN2||!BTN3||!BTN4))
	{
     
		Delay_Ms(10);
		key = 0;
		if(!BTN1)
			return 1;
		if(!BTN2)
			return 2;
		if(!BTN3)
			return 3;
		if(!BTN4)
			return 4;
	}
	else if(BNT1&&BTN2&&BTN3&&BTN4)
		key = 1;
	return 0;
}
  • 按键功能实现
u8 line;
switch(Key_Scan())
{
     
	case 1:
		if(LCD_Mode)
		{
     
			LCD_ClearLine(Line1);
			LCD_ClearLine(Line2);
			LCD_ClearLine(line3);
			LCD_ClearLine(line4);
			LCD_Mode = 0;
			EEPROMRefresh();
			line = 0;
		}
		else
		{
     
			LCD_ClearLine(Line1);
			LCD_ClearLine(Line2);
			LCD_ClearLine(line3);
			LCD_ClearLine(line4);
			LCD_Mode = 1;
		}
		break;
	case 2:
		if(LCD_Mode)
		{
     
			line = line + 1;
			line %= 3;
		}
		break;
	case 3:
		if(Threshold[line] <= 95 && LCD_Mode)
			Threshold[line] += 5;
		break;
	case 4:
		if(Threshold[line] >= 5 && LCD_Mode)
			Threshold[line] -= 5;
		break;
}
  • 然后是串口的功能实现
  • 在串口的中断处理函数中
void sendString(u8 *str)
{
     
	while(*str)
	{
     
		USART_SendData(USART2, *str++);
		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
	}
}

u8 led3 = 0;
u8 tmp, sting[20];
extern u8 Threshold[3], h, level;
void USARTy_IRQHandler(void)
{
     
	if(USART_GetITStatus(USART2, USART_IT_RXNE) !+ RESET)
	{
     
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
		tmp = USART_ReceiveData(USART2);
		if(tmp == 'C')
		{
     
			if(led3 == 0)
				led3 = 1;
			sprintf((char*)string, 'C:H%d+L%d\r\n', h, level);
			SendString(string);
		}
		else if(tmp == 'S')
		{
     
			if(led3 == 0)
				led3 = 1;
			sprintf((char*)string, 'S:TL%d+TM%d+TH%d\r\n', Threshold[0], Threshold[1], Threshold[2]);
			SendString(string);
		}
	}
}
  • 在主函数中,当检测到等级变化,同样需要串口通信
u8 change[2]={
     'D','U'};
u8 led2 = 0;
if(level != last_level)
{
     
	if(led2 == 0)
		led2 = 1;
	sprintf((char*)str, "A:H%d+L%d+%c", h, last_level, change[level>last_level]);
	SendString(str);
	level = last_level;
}
  • 最后是指示灯的控制了,由于每个灯有规定的闪烁时间,因为,我们在TIM的中断处理函数中加上对LED的处理

注:这里时钟周期要设为19999,分频为72-1;即0.2s

extern u8 led2;
extern u8 led3;
u8 cnt = 0;
u8 led1_sta = 1, led2_sta = 1, led3_sta = 1;
void TIM2_IRQHandler(void)
{
     
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
	{
     
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
		cnt++;
		cnt %= 50;
		if(cnt % 10 == 0)
		{
     
			if(led3)
			{
     
				LED_Control(LED3, led3_sta);
				led3_sta = !led3_sta;
				if(led3++ == 10)
					led3 = 0;
			}
			if(led2)
			{
     
				LED_Control(LED2, led2_sta);
				led2_sta = !led2_sta;
				if(led2++ == 10)
					led2 = 0;
			}
		}
		if(cnt == 0)
		{
     
			LED_Control(LED1, led1_sta);
			led1_sta = !led1_sta;
		}
	}
}

你可能感兴趣的:(嵌入式(蓝桥杯))