Blue Bridge Cup embedded real topic of the 7th provincial competition

Blue Bridge Cup embedded real topic of the 7th provincial competition

The end of the code is free!!!!!!

The end of the code is free!!!!!!

The end of the code is free!!!!!!

1. Title

"Analog liquid level detection and alarm system" calculates the liquid level height by collecting analog voltage signal, and performs alarm action according to the liquid level threshold set by the user. When the liquid level level level changes, it sends the liquid level information to PC through serial communication interface.

Design tasks and requirements

  1. Liquid level detection

    The output voltage signal of liquid level sensor is simulated by potentiometer R37. The equipment collects R37 output voltage at an interval of 1 second and compares it with the liquid level threshold set by the user. It is assumed that there is a positive proportional relationship between the liquid level height and R37 output voltage: H = VR37*K. when VR37=3.3V, the corresponding liquid level height is 100cm. The current liquid level height, sensor (R37) output status and liquid level level level are displayed through the liquid crystal. The liquid level detection display interface is shown in Figure 1

    The results obtained from AD acquisition shall be processed by software filtering algorithm, and the display results shall retain two significant digits after the decimal point

  2. Liquid level threshold setting

    The equipment can set three liquid level thresholds corresponding to four liquid level levels. The threshold is input by the user through the key. The equipment saves the threshold and judges the liquid level level level according to this threshold. It is assumed that the three liquid level thresholds entered by the user are 10cm, 20cm and 30cm. The corresponding relationship between the liquid level height and the liquid level level level is as follows:
    2.1 When the liquid level height is ≤ 10cm, the liquid level grade is 0;
    2.2 when 10cm < liquid level height ≤ 20cm, the liquid level grade is 1;
    2.3 when 20cm < liquid level height ≤ 30cm, the liquid level grade is 2;
    2.4 when the liquid level height is > 30cm, the liquid level grade is 3.
    The initial liquid level thresholds of the equipment are 30cm, 50cm and 70cm respectively. After the user modifies the threshold, the equipment shall save this parameter in E2PROM. When the equipment is powered on again, it can be obtained from E2PROM.

  3. Liquid level threshold setting

    B1 key: press the "setting" key to enter the threshold setting interface (as shown in Figure 2). Press B1 key again to exit the setting interface, save the user set results to E2PROM, and return to the liquid level detection interface shown in Figure 1.
    B2 key: switch and select 3 thresholds to be modified, and the selected threshold shall be highlighted.
    B3 key: press the "add" key. After pressing, the selected threshold increases by 5cm to 95cm.
    B4 key: press the "minus" key. After pressing, the selected threshold will be reduced by 5cm until it is reduced to 5cm.

  4. Serial port query and output function

    Use STM32 USART2 to complete the following serial port functions, and the baud rate is set to 9600.

4.1 query
Send the character 'C' to the equipment through the PC, and the equipment returns the current liquid level height and level;
Send the character'S' to the device through the PC, and the device returns to the three currently set thresholds.
For example, the return data format of liquid level height and level: "C: H55 + L2 \ R \ nalysis: answer the query of height and level. The liquid level height is 55cm and the liquid level level level is 2.
Example of threshold return data format: "S:TL30+TM50+TH70\r\n" analysis: answer the threshold query. The three thresholds stored in the device are 30cm, 50cm and 70cm respectively.
4.2 output
When the liquid level level changes, the equipment automatically sends the current liquid level level, liquid level height and liquid level change trend (up or down) to the PC.
Example of output data format:
"A:H55+L2+D\r\n"
Analysis: the liquid level change is sent automatically, the liquid level height is 55cm, the liquid level grade is 2, and the change trend decreases.
"A:H55+L2+U\r\n"
Analysis: the liquid level change is sent automatically, the liquid level height is 55cm, the liquid level grade is 2, and the change trend increases.

5. Status indication

LED indicator functions are defined as follows:
LD1: operation status indicator, on and off at an interval of 1 second;
LD2: liquid level level level change indicator. When the liquid level level changes, LD2 flashes 5 times at an interval of 0.2 seconds;
LD3: communication status indicator. When the equipment receives the query command, LD3 flashes for 5 times at an interval of 0.2 seconds

2. Topic analysis

The difficulty of this problem is not very prominent, but some places are very interesting, especially the one that automatically sends data when monitoring the change of liquid level level. At the beginning, I still had a small bug that hasn't been solved

In fact, most of them are not difficult. Here I'll talk about the method of sending data when the automatic monitoring level changes. You can understand it by reading my notes directly later,

The data control of the highlight part may be very troublesome for some people. Here I use a solution to the embedded real problem of the 10th Blue Bridge Cup. You can have a look

  • If we want to change the monitoring level, we need an Old_Level variable to save the last old data and a Liquid_Level to store the current level

  • Before the While(1) main function, we need to put a function to initialize the Old_Level. Otherwise, if we manually specify the default value for the Old_Level, assuming that the default value is 0, but the liquid level level is 1, the LD2 status indicator will flash five times as soon as we power on, which is what we don't want to see. Therefore, we need to initialize before entering the main cycle

  • During the later comparison, use the liquid level height variable to compare the upper and lower limits, and then change the liquid level. When the comparison is successful, assign a value to the liquid level first. Note that if we change the level of the liquid level for the first time after power on, then what is stored in the Old_Value is the initial level when we power on, and the Liquid_Level is assigned with old_va The size of Lue is different. By comparing their sizes, we can analyze the change trend and send serial port data

    Start with most of the control logic codes on the

3. Project structure

3.1 function structure and global variables

extern char USART_RXBUF[10];
extern uint8_t RXOVER;

int TimingDelay;
//Display part
char Height_Show[20];
char ADC_Show[20];
char Liquid_Level_Show[20];
char Threshold1_Show[20];
char Threshold2_Show[20];
char Threshold3_Show[20];
//As shown in the English translation
double Adc_Temp;
int Liquid_Height;
int Liquid_Level;
int Old_Level;
//Three thresholds
int Threshold1=30;
int Threshold2=50;
int Threshold3=70;
//Flag bit of highlighted part
int High_Light_flag = 1;
//K1 key mode
int mode=1;
char key;

//Lamp related control	
int Led1_Flag=1;
int Led2_Flag=0;
int Led3_Flag=0;
int Led3_Happen=0;
int Led2_Happen=0;

//Display interface function
void Liquid_Level_Display();
void Parameter_Setup_Display(int High_Light_flag);
//Set function
void Setting();
//K3,K4 key control function
void Key3_Control(int flag);
void Key4_Control(int flag);
//Serial port mode analysis
int analysis(char * data);
//Level level control
void Level_Control();
//Serial port general control
void Usart_Control();
//Led control
void Led_Control();
//Initialize level level
void Level_Init();
//Initialization threshold data (EEROM)
void Init_Data();
//Save threshold data (EEROM)
void Save_Data();

3.2 interface

Setting function

void Setting()
{
    //Calculate liquid level height
	Adc_Temp = Get_Adc();
	Liquid_Height=Adc_Temp*30.3;
	key = KEY_Scan();
	switch(key)
	{
		case '1':
            //Main interface and setting interface switching flag
			LCD_Clear(White);
            //This will be used in subsequent switch es
			mode = !mode;
			break;
		case '2':
			High_Light_flag++;
            //The practice of highlight part flag bit control was used in the 10th provincial competition of my blog
			if(High_Light_flag>3) { High_Light_flag = 1; }
			break;			
		case '3':
            //Directly pass in the previous highlight flag bit, so that the key can execute the correct logic of the highlight line
			Key3_Control(High_Light_flag);
			break;
		case '4':
			Key4_Control(High_Light_flag);
			break;
	}
    //Switching display of two interfaces
	switch(mode)
	{
		case 1:
			Liquid_Level_Display();
			break;		
		case 0:
            //In the same way, the highlight flag bit is introduced to match Key3 and Key4 with the corresponding display
			Parameter_Setup_Display(High_Light_flag);
			break;
	}
}

void Parameter_Setup_Display(int High_Light_flag) highlight interface function

I only want to write here. I can't think of how to simplify it

void Parameter_Setup_Display(int High_Light_flag)
{
	sprintf(Threshold1_Show,"Threshold1: %2d     ",Threshold1);
	sprintf(Threshold2_Show,"Threshold2: %2d     ",Threshold2);
	sprintf(Threshold3_Show,"Threshold3: %2d     ",Threshold3);
	if(High_Light_flag==1)
	{
		LCD_SetBackColor(White);
		LCD_DisplayStringLine(Line2,"   Parameter Setup");
		LCD_DisplayStringLine(Line5,Threshold2_Show);
		LCD_DisplayStringLine(Line6,Threshold3_Show);
		LCD_SetBackColor(Yellow);
		LCD_DisplayStringLine(Line4,Threshold1_Show);
	}
	else if(High_Light_flag==2)
	{
		LCD_SetBackColor(White);
		LCD_DisplayStringLine(Line2,"   Parameter Setup");
		LCD_DisplayStringLine(Line4,Threshold1_Show);
		LCD_DisplayStringLine(Line6,Threshold3_Show);
		LCD_SetBackColor(Yellow);
		LCD_DisplayStringLine(Line5,Threshold2_Show);
	}
	else if(High_Light_flag==3)
	{
		LCD_SetBackColor(White);
		LCD_DisplayStringLine(Line2,"   Parameter Setup");
		LCD_DisplayStringLine(Line5,Threshold2_Show);
		LCD_DisplayStringLine(Line4,Threshold1_Show);
		LCD_SetBackColor(Yellow);
		LCD_DisplayStringLine(Line6,Threshold3_Show);
	}

}

The rest is some data refresh functions. I don't think it's valuable here. To put it bluntly, it's Sprintf splicing and LCD display

3.3 K3 and K4 key control

It's very simple. Just take an example of K3, and K4 is the opposite

void Key3_Control(int flag)
{
    //It can be seen that we are fully cooperating with the highlight display interface
	if(flag==1)
	{
		if(Threshold1+5>95)
		{
            Threshold1=95;
            Save_Data();
			return;
		}
		Threshold1+=5;
		Save_Data();
	}
	else if(flag==2)
	{
		if(Threshold2+5>95)
		{
			Threshold2=95;
            Save_Data();
			return;
		}
		Threshold2+=5;
		Save_Data();
	}
	else if(flag==3)
	{
		if(Threshold3+5>95)
		{
			Threshold3=95;
            Save_Data();
			return;
		}
		Threshold3+=5;
		Save_Data();
	}
}

3.4 serial port control

Usart_ Serial port control

void Usart_Control()
{
	int mode;
	char data[20];

	if(RXOVER==1)
	{
		RXOVER = 0;
		//Analyze the data to determine which mode of data we need to return
        //In fact, the logic of this question is simple. You can write it all directly, but I'm used to dividing it into modules
		mode = analysis(USART_RXBUF);
		memset(USART_RXBUF,'\0',sizeof(USART_RXBUF));
		USART_ITConfig(USART2	,USART_IT_RXNE,ENABLE);
		switch(mode)
		{
			case 1:
				sprintf(data,"C:H%d+L%d\r\n",Liquid_Height,Liquid_Level);
				USART_SendString(data);
				break;
			case 2:
				sprintf(data,"S:TL%d+TM%d+TH%d\r\n",Threshold1,Threshold2,Threshold3);
				USART_SendString(data);
   			break;
			default:
			  break;
		}
	}
}

int analysis(char * data) data analysis function

int analysis(char * data)
{
	if(data[0]=='C')
	{
        //Received data Led3_ The position 1 of the happy flag triggers the Led3 part in the systick interrupt
		Led3_Happen=1;
		return 1;
	}
	else if(data[0]=='S')
	{
        //Received data Led3_ The position 1 of the happy flag triggers the Led3 part in the systick interrupt
		Led3_Happen=1;
		return 2;
	}
}

3.5 liquid level control

Level_ Level control

void Level_Control()
{

	char data[20];
	//0 grade
	if(Liquid_Height>0 && Liquid_Height < Threshold1)
	{
        //Assign a value to the current liquid level level variable first
		Liquid_Level=0;
        //Here, we only need to judge once. We'll give it to level 1 for judgment
		if(Old_Level>Liquid_Level)
		{
            //Status change, Led2_ The position 1 of the happy flag triggers the Led2 part of the systick interrupt
			Led2_Happen=1;
			sprintf(data,"H%d+L%d+D\r\n",Liquid_Height,Liquid_Level);
			USART_SendString(data);
		}
  		//After judgment, assign a value to the old level variable
		Old_Level=0;
	}
    //1 grade
	else if(Liquid_Height > Threshold1 && Liquid_Height < Threshold2)
	{
        //Similarly
		Liquid_Level=1;
        //If the old value is greater than the new value, it is a decline
		if(Old_Level>Liquid_Level)
		{
			Led2_Happen=1;
			sprintf(data,"H%d+L%d+D\r\n",Liquid_Height,Liquid_Level);
			USART_SendString(data);
		}
        //If the old value is smaller than the new value, it is rising
		if(Old_Level<Liquid_Level)
		{
			Led2_Happen=1;
			sprintf(data,"H%d+L%d+U\r\n",Liquid_Height,Liquid_Level);
			USART_SendString(data);
		}
        //Similarly
		Old_Level=1;
	}
    //Follow up similarly
	else if(Liquid_Height > Threshold2 && Liquid_Height < Threshold3)
	{
		Liquid_Level=2;
		if(Old_Level>Liquid_Level)
		{
			Led2_Happen=1;
			sprintf(data,"H%d+L%d+D\r\n",Liquid_Height,Liquid_Level);
			USART_SendString(data);
		}
		if(Old_Level<Liquid_Level)
		{
			Led2_Happen=1;
			sprintf(data,"H%d+L%d+U\r\n",Liquid_Height,Liquid_Level);
			USART_SendString(data);
		}
		Old_Level=2;
	}
	else if( Liquid_Height >= Threshold3)
	{
		Liquid_Level=3;
		if(Old_Level<Liquid_Level)
		{
			Led2_Happen=1;
			sprintf(data,"H%d+L%d+U\r\n",Liquid_Height,Liquid_Level);
			USART_SendString(data);
		}
		Old_Level=3;
	}
}

Here is the level initialization function void level mentioned earlier_ Init()

void Level_Init()
{
	int i;
	char data[20];
	//The data read by ADC was wrong when it was just powered on, so let him read it ten times first
	for(i=0 ;i<10;i++){  	Adc_Temp = Get_Adc();  }
	Liquid_Height=Adc_Temp*30.3;
	//Determine the state assignment of initialization
	if(Liquid_Height>0 && Liquid_Height < Threshold1)
	{
		Old_Level=0;
		Liquid_Level=0;
	}
	else if(Liquid_Height > Threshold1 && Liquid_Height < Threshold2)
	{
		Old_Level=1;
		Liquid_Level=1;

	}
	else if(Liquid_Height > Threshold2 && Liquid_Height < Threshold3)
	{
		Old_Level=2;
		Liquid_Level=2;
	}
	else if( Liquid_Height >= Threshold3)
	{
		Old_Level=3;
		Liquid_Level=3;
	}
}

3.6 Led control

Led on and off_ Control (change the flag bit mainly through systick interrupt)

void Led_Control()
{
	LED_Control(LED1,Led1_Flag);
	LED_Control(LED3,Led3_Flag);
	LED_Control(LED2,Led2_Flag);
}

interrupt

extern int Led1_Flag;
extern int Led2_Flag;
extern int Led3_Flag;

extern int Led3_Happen;
extern int Led2_Happen;
int Led1_Delay=0;
int Led2_Delay=0;
int Led3_Delay=0;
int Led3_Count=0;
int Led2_Count=0;
void SysTick_Handler(void)
{
	TimingDelay--;
    //It flashes once in 1s after normal operation
	if(++Led1_Delay==1000)
	{
		Led1_Delay=0;
		Led1_Flag=!Led1_Flag;
	}
    //The state has changed
	if(Led2_Happen)
	{
		if(++Led2_Delay==200)
		{
			Led2_Count++;
			Led2_Delay=0;
			Led2_Flag=!Led2_Flag;
		}
        //Because the lights are on and off alternately, the lights > 10, 1, 3, 5, 7 and 9 are on
		if(Led2_Count>10)
		{
			Led2_Happen=0;
			Led2_Count=0;
		}
	}
    //Data received
	if(Led3_Happen)
	{
		if(++Led3_Delay==200)
		{
			Led3_Count++;
			Led3_Delay=0;
			Led3_Flag=!Led3_Flag;
		}
		if(Led3_Count>10)
		{
			Led3_Happen=0;
			Led3_Count=0;
		}
	}
}

3.7 main function

//... omit most initialization
	//This is what I said before. Initialize the liquid level level first
	Level_Init();
	Init_Data();
	while(1)
	{
        //Sub module programming, so the main function is very concise
		Setting();
		Level_Control();
		Usart_Control();
		Led_Control();
	}

The basic codes are already here. On what is the real nanny level teaching, ha ha, ha ha, there are only some interface refresh, EEPROM data storage and reading, very, very basic codes. I don't think it's necessary to put it again.

I wish everyone's programming level is booming. Personally, I am quite satisfied with the structure of this time

Source code
Extraction code: 7gqa

Tags: Embedded system Single-Chip Microcomputer STM

Posted on Thu, 25 Nov 2021 18:24:40 -0500 by ThEMakeR