2016年嵌入式第七届省赛真题解析

 

串口发送数据会修改显示数组的值:原因暂未找到!!!

一、题目

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57yW56iL5bCP54aK,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57yW56iL5bCP54aK,size_20,color_FFFFFF,t_70,g_se,x_16 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57yW56iL5bCP54aK,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57yW56iL5bCP54aK,size_20,color_FFFFFF,t_70,g_se,x_16

二、分析 

 题目要求做一个液位检测告警系统,这里将将题目分为四大部分显示界面,设置界面,串口收发,LED灯指示

1.界面

 由于题目用到了按键切换不同的界面,所以先做界面与按键切换这一部分。

 

 ​watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57yW56iL5bCP54aK,size_20,color_FFFFFF,t_70,g_se,x_16

界面的控制用变量lcd_ctrl控制:若变量等于0x00则表示显示界面;若变量为0x1_,则为设置界面,并且0x10设置阈值1,0x11设置阈值2,0x12设置阈值3


if(unKey_Down == 1)  // 界面切换
	{	
		if(lcd_ctrl == 0x00)
		{
			LCD_Clear(White);
			lcd_ctrl = 0x10;
		}
		else
		{
			LCD_Clear(White);lcd_ctrl = 0x00;
            LCD_Clear(White);lcd_ctrl = 0x00;
			iic_24c02_write(high_level_ctrl, 0, 3); //写
			high_level_ctrl[0] = high_level_disp[0];  //将显示值(进行加减)赋给控制值
			high_level_ctrl[1] = high_level_disp[1];
			high_level_ctrl[2] = high_level_disp[2];
			
		}	
	}
	if(unKey_Down == 2 && lcd_ctrl>>4 ==0x1)  // 选择,默认第一行:0x10
	{	
		if(lcd_ctrl>= 0x12) lcd_ctrl = 0x10;
		else lcd_ctrl++;
	}

软件滤波:采用中值滤波,即在在采集ADC数据时,总共采取10次,结果求起平均值即可。

//中值滤波
	for(count=0;count<=9;count++)
	{
		v37_sum += getADC2();
	}
	v37 = v37_sum* 3.3 / 4096 /10;
	v37_sum =0; //清0为下一次准备
	high = 100/3.3*v37;

注意:在for循环里面,只将收集到的初次数据相加处理即可,数据转换(乘除)放在循环外面处理,不然每一次都做数据转换浪费内存与计算,这样每一只要进行一次转换即可

 

 在设置阈值进行加减时,要注意各个阈值之间的大小问题,并且设置时文字要高亮显示,使用设置字体颜色函数LCD_SetTextColor(),该函数只对后面的显示文字有效

 

 

//lcd显示函数
void Lcd_Proc(void)
{
	if((uwTick -  uwTick_Lcd_Set_Point)<50)	return;//减速函数
		uwTick_Lcd_Set_Point = uwTick;
	
	if(lcd_ctrl == 0x00)
	{
		LCD_SetTextColor(Blue);
		sprintf((char *)Lcd_Disp_String, "    Liquid Level    ");
		LCD_DisplayStringLine(Line2, Lcd_Disp_String);	
		
		
		sprintf((char *)Lcd_Disp_String, "    Height: %d",(uint8_t)high);
		LCD_DisplayStringLine(Line4, Lcd_Disp_String);	
		
		sprintf((char *)Lcd_Disp_String, "    ADC: %.2f",v37);
		LCD_DisplayStringLine(Line6, Lcd_Disp_String);
		
		sprintf((char *)Lcd_Disp_String, "    Level: %d",level);
		LCD_DisplayStringLine(Line8, Lcd_Disp_String);	

	}
	else
	{
		LCD_SetTextColor(Blue);
		sprintf((char *)Lcd_Disp_String, "  Parameter Setup    ");
		LCD_DisplayStringLine(Line2, Lcd_Disp_String);
			
		
		if(lcd_ctrl == 0x10){LCD_SetTextColor(Green);} //颜色选择,仅对后面的有效
		else{LCD_SetTextColor(Blue); }
		sprintf((char *)Lcd_Disp_String, "  Threshold 1: %2dcm",high_level_disp[0]);
		LCD_DisplayStringLine(Line4, Lcd_Disp_String);
		
		if(lcd_ctrl == 0x11){LCD_SetTextColor(Green);}
		else LCD_SetTextColor(Blue);
		sprintf((char *)Lcd_Disp_String, "  Threshold 2: %2dcm",high_level_disp[1]);
		LCD_DisplayStringLine(Line6, Lcd_Disp_String);
			
		if(lcd_ctrl == 0x12){LCD_SetTextColor(Green);} 
		else LCD_SetTextColor(Blue);
		sprintf((char *)Lcd_Disp_String, "  Threshold 3: %2dcm",high_level_disp[2]);
		LCD_DisplayStringLine(Line8, Lcd_Disp_String);
			
	}
	
}

// 按键设置
if(unKey_Down == 3)  // 加 ,有大小
	{	
		if(lcd_ctrl == 0x10)
		{
			if(high_level_disp[0]>=95) high_level_disp[0] = 95;
			else if(high_level_disp[0]<high_level_disp[1]-5)high_level_disp[0] += 5;
		}
		if(lcd_ctrl == 0x11)
		{
			if(high_level_disp[1]>=95) high_level_disp[1] = 95;
			else if(high_level_disp[1] <high_level_disp[2]-5 && high_level_disp[1] >high_level_disp[0] )
				high_level_disp[1] += 5;
		}
		if(lcd_ctrl == 0x12)
		{
			if(high_level_disp[2]>=95) high_level_disp[2] = 95;
			else if(high_level_disp[2]>high_level_disp[1])high_level_disp[2] += 5;
		}
	}
	
	if(unKey_Down == 4)  // 减
	{	
		if(lcd_ctrl == 0x10)
		{
			if(high_level_disp[0]<=5) high_level_disp[0] = 5;
			else if(high_level_disp[0]<=high_level_disp[1]-5)high_level_disp[0] -= 5;
		}
		if(lcd_ctrl == 0x11)
		{
			if(high_level_disp[1]<=5) high_level_disp[1] = 5;
			else if(high_level_disp[1] <high_level_disp[2] && high_level_disp[1] -5>high_level_disp[0] ) high_level_disp[1] -= 5;
		}
		if(lcd_ctrl == 0x12)
		{
			if(high_level_disp[2]<=5) high_level_disp[2] = 5;
			else if(high_level_disp[2]>high_level_disp[1]+5)high_level_disp[2] -= 5;
		}
	}

这里将阈值用两个数组来存储,一个用来显示(加减),一个用来控制(真正起作用)。文字高亮显示:在显示前判断一下是否选择这一行,若是设置新的文字颜色;若不是设置文本颜色。有可能会影响显示界面或者第一行,若影响到了直接在它前面加一句颜色的设置函数即可。

 

2.串口收发

//串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(rx_buffer == 'C')
	{
		led3 =1;
		sprintf((char *)tx_buffer, "C:H%3d+L%d\r\n",(int)high,level);
		HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);	
	
	}
	if(rx_buffer == 'S')
	{
		led3 =1;
		//sprintf((char *)tx_buffer, "S:TL%2d+TM%2d+TH%2d\r\n",(uint_8)high_level_ctrl[0],(uint_8)high_level_ctrl[1],(uint_8)high_level_ctrl[2]);
		sprintf((char *)tx_buffer, "S:TL%2d+TM%2d+TH%2d\r\n",high_level_ctrl[0],high_level_ctrl[1],high_level_ctrl[2]);
		HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)(&rx_buffer), 1);

}


if(high <= high_level_ctrl[0]) level = 0;
	else if(high>high_level_ctrl[0] && high<=high_level_ctrl[1]) level = 1;
	else if(high>high_level_ctrl[1] && high<=high_level_ctrl[2]) level = 2;
	else level = 3;
	
	cur_level = level;
	if(cur_level > old_level)
	{
		led2 = 1;
		sprintf(tx_buffer, "A:H%3d+L%1d+U\r\n",(unsigned int)high,(unsigned int)level);
	  	HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);	
	}
	else if(cur_level < old_level)
	{
		led2 =1;
		sprintf(tx_buffer, "A:H%3d+L%1d+D\r\n",(unsigned int)high,(unsigned int)level);
	  	HAL_UART_Transmit(&huart1,(unsigned char *)tx_buffer, strlen(tx_buffer), 50);	
	}
	old_level = cur_level;

在收到字符,就向串口发送相应的信息,直接在接收中断里面完成即可。判断当前数据是否发送变化: 用三个变量cur_level, old_level, level ;然后比较old与cur即可

3.LED

LED1以1s的周期闪烁,LED2,3在相应的条件下闪烁5次

这里定时精度不是要求的很高,所以直接使用了滴答定时器的uwTick计时。

灯闪烁:即相应的为不断的翻转即可

第0位翻转:ucLed ^= 0x01  

第一位翻转:ucLed ^= 0x20

第二位翻转:ucLed  ^= 0x40

某一位翻转:ucLed ^= (1<< x)  将第x位翻转(0-7)

某一位清0: ucLed  &= ~(1<<3) 第3位清0(0-7)

某一位置1: ucLed  | = (1<< 3)       

 让led2闪烁5次,即翻转10次

void Led_Proc(void)
{
	if((uwTick -  uwTick_Led_Set_Point)<=200)	return;//减速函数
		uwTick_Led_Set_Point = uwTick;	

    if(led2 ==1)
	{
		if(led2_num--) // 10次 0.2进来判断10
		{
			ucLed ^= 0x02;
		}
		if(led2_num == 0)
		{
			led2_num =10;
			led2 = 0;
			ucLed &= ~(1<<1); //清零
		}
		
	}
	LED_Disp(ucLed);
}

注意:当闪烁5次以后,要将相应的标志恢复位原来前的现场!!!!

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值