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
-
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
-
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. -
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. -
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