蓝桥杯嵌入式第十届省赛解析

196 阅读5分钟

@TOC


前言

本篇文章将为大家讲解第十届省赛题目,总的来说题目的难点就是EEPROM的数据存储,因为这里涉及到了小数的部分,其他的其实都是不难的。

一、题目解析

本届题目主要考察了LCD显示,LED控制,模拟电压输入,按键输入E2PROM数据存储,这些都是非常常规的操作起来并不难,值得一讲的就是数据存储和LCD高亮显示。 在这里插入图片描述

二、LCD高亮显示

在赛题的这一部分需要我们高亮显示一行数据,这里是很多同学没有接触过的现在就给大家讲解一下如何高亮显示吧。 在这里插入图片描述 代码: 我想要高亮显示的是Max_Volt_buf,操作如下: 首先先将背景色设置为想要高亮的颜色,然后再去显示想要显示的字符串,最后将颜色重置为白色那么这样就达到了高亮显示的效果了。

LCD_SetBackColor(Green);		
LCD_DisplayStringLine(Line2, (u8*)Max_Volt_buf);
LCD_SetBackColor(White);

三、E2PROM如何存储小数部分

E2PROM存储的类型是unsigned char类型的存储的范围是0-255,所以直接使用他存储小数是不可能的。有很多同学就会卡在这里,这里教大家一个好的方法。 既然E2PROM只能够存储u8类型的那么我们就将小数变成整数来存储进去,读取的时候再将整数换算为小数 在这里插入图片描述 这里我们需要存储的是Max Volt和Min Volt这两个小数。 代码: 存储: 首先先定义两个整数类型的write_Max_Volt 和write_Min_Volt ,使用他们来保存从小数转换为整数的Max Volt和Min Volt。 这里直接让Max_Volt *10强制变为整数存储进去。因为电压的范围是0-3.3V所以这里我们并不需要担心范围的问题,可以直接进行乘法操作。 注意点: 为什么这里需要加一个0.01呢因为Max_Volt 是一个小数他乘10后不一定可以得到正确的数值,所以这里需要加一个0.01进行补偿,当然了也不一定是加0.01这个数值大家可以通过调试测试出来

int write_Max_Volt = 0;
int write_Min_Volt = 0;

write_Max_Volt = (Max_Volt + 0.01) * 10;
EEPROM_Write(0x02, (u8)write_Max_Volt);

write_Min_Volt = (Min_Volt + 0.01) * 10;
EEPROM_Write(0x03, (u8)write_Min_Volt);

读取: 和上面一样我们需要先定义read_Max_Volt 和read_Min_Volt 两个变量来保存读取出来的整数值。 读取出来的数值为整数我们需要对他进行转换。

这个代码的目的是将一个整数转换为一个浮点数,整数的高位作为浮点数的整数部分,低位作为浮点数的小数部分,例如: 如果read_Max_Volt的值为30,则按照下面代码的转换规则,可以得到Max_Volt的值为3.0。 这个转换应该是很简单的,不熟练的同学再回去看看C语言知识。

int read_Max_Volt = 0;
int read_Min_Volt = 0;

read_Max_Volt = EEPROM_Read(0x02);
HAL_Delay(5);
read_Min_Volt = EEPROM_Read(0x03);
HAL_Delay(5);

Max_Volt = (float)(read_Max_Volt / 10) + (float)(read_Max_Volt % 10) / 10.0f;
Min_Volt = (float)(read_Min_Volt / 10) + (float)(read_Min_Volt % 10) / 10.0f;

四、参数合理性判断

这一部分需要大家注意,上限值电压参数肯定是不难比下限电压参数 在这里插入图片描述 这里先定义两个old变量用来保存Max_Volt和Min_Volt,当从参数设置界面退出时判断参数是否正确,如果不正确那么就将old_Max_Volt和old_Min_Volt赋值给Max_Volt和Min_Volt 恢复原来正确的值。

float old_Max_Volt = 0;
float old_Min_Volt = 0;

if(key_val == 1)
{
	UI = !UI;
	if(UI)
	{
		old_Max_Volt = Max_Volt;
		old_Min_Volt = Min_Volt;
	}
	else
	{
		if(Max_Volt < Min_Volt)
		{
			Max_Volt = old_Max_Volt;
			Min_Volt = old_Min_Volt;			
		}
	}		
	LCD_Clear(White);
}

五、完整代码

全部代码展示:

  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "key.h"
#include "i2c.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*R38电压变量(因为板子的R37坏掉了所以只有R38了)*/
int volt_value = 0;
float volt_R38 = 0;
/*电压上限下限变量*/
char volt_buf[16] = {0};
float Max_Volt = 2.4;
float Min_Volt = 1.2;
/*定义这两个变量是为了当Max和Min参数错误的时候恢复原变量的(例如Max < Min)时就会使用到这两个变量*/
float old_Max_Volt = 0;
float old_Min_Volt = 0;
char Max_Volt_buf[16] = {0};
char Min_Volt_buf[16] = {0};
/*界面切换变量*/
int UI = 0;
int select = 0;
/*上下限LED控制变量*/
int upled = 1;
int lowled = 2;
char upled_buf[16] = {0};
char lowled_buf[16] = {0};

/*操作E2PROM变量*/
int write_Max_Volt = 0;
int write_Min_Volt = 0;

int read_Max_Volt = 0;
int read_Min_Volt = 0;

// 按键执行程序
__IO uint32_t keyTick = 0;
u16 key_val = 0;
void Key_Scan(void)
{
	if(uwTick - keyTick < 10) return ; 
	keyTick = uwTick; 
	
	Key_Read();
	if(Trg & 0x01)	//B1
	{
		key_val = 1; 
	}
	if(Trg & 0x02)	//B2
	{
		key_val = 2;
	}
	if(Trg & 0x04)	//B3
	{
		key_val = 3;
	}
	if(Trg & 0x08)	//B4
	{
		key_val = 4;
	}
}

__IO uint32_t ledTick = 0;
void LED(void)
{
	static int status = 0;
	if(uwTick - ledTick < 200) return ; 
	ledTick = uwTick;
	status = !status; 	
	if(volt_R38 > Max_Volt)
	{
		Led_Set_Status(upled, status);
		if(UI == 0)
		{
			LCD_DisplayStringLine(Line5, (u8*)"    Status: Upper");
		}		
	}
	else if(volt_R38 < Min_Volt)
	{
		Led_Set_Status(lowled, status);
		if(UI == 0)
		{
			LCD_DisplayStringLine(Line5, (u8*)"    Status: Lower");
		}
	}
	else if(volt_R38 >= Min_Volt && volt_R38 <= Max_Volt)
	{
		if(UI == 0)
		{
			LCD_DisplayStringLine(Line5, (u8*)"    Status: Nomal");			
		}		
		HAL_GPIO_WritePin(GPIOC,0xff00,GPIO_PIN_SET);//关闭全部LED
		
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//打开锁存器
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关闭锁存器
	}
}

void key_dispose(void)
{
	if(key_val == 1)
	{
		UI = !UI;
		if(UI)
		{
			old_Max_Volt = Max_Volt;
			old_Min_Volt = Min_Volt;
		}
		else
		{
			if(Max_Volt < Min_Volt)
			{
				Max_Volt = old_Max_Volt;
				Min_Volt = old_Min_Volt;			
			}
		}		
		LCD_Clear(White);
	}
	if(key_val == 2)
	{
		if(UI)
		{
			select++;
			select = select % 4;
		}
	}	
	if(key_val == 3)
	{
		if(UI)
		{
			if(select == 0)
			{
				if(Max_Volt < 3.29)
				{
					Max_Volt += 0.3;
				}
				write_Max_Volt = (Max_Volt + 0.01) * 10;
				EEPROM_Write(0x02, (u8)write_Max_Volt);
			}
			else if(select == 1)
			{
				if(Min_Volt < 3.29)
				{
					Min_Volt += 0.3;
				}
				write_Min_Volt = (Min_Volt + 0.01) * 10;
				EEPROM_Write(0x03, (u8)write_Min_Volt);
			}
			else if(select == 2)
			{
				if(upled < 8)
				{
					upled++;
				}				
			}
			else if(select == 3)
			{
				if(lowled < 8)
				{
					lowled++;
				}					
			}
		}
		EEPROM_Write(0x00, (u8)upled);
		HAL_Delay(2);
		EEPROM_Write(0x01, (u8)lowled);
	}
	if(key_val == 4)
	{
		if(UI)
		{
			if(select == 0)
			{
				if(Max_Volt > 0.1)
				{
					Max_Volt -= 0.3;
				}
				write_Max_Volt = (Max_Volt + 0.01) * 10;
				EEPROM_Write(0x02, (u8)write_Max_Volt);				
			}
			else if(select == 1)
			{
				if(Min_Volt > 0.1)
				{
					Min_Volt -= 0.3;
				}
				write_Min_Volt = (Min_Volt + 0.01) * 10;
				EEPROM_Write(0x03, (u8)write_Min_Volt);				
			}
			else if(select == 2)
			{
				if(upled > 1)
				{
					upled--;
				}
			}
			else if(select == 3)
			{
				if(lowled > 1)
				{
					lowled--;
				}
			}			
		}
		EEPROM_Write(0x00, (u8)upled);
		HAL_Delay(2);
		EEPROM_Write(0x01, (u8)lowled);		
	}
	key_val = 0;
}

/*数据界面*/
void Data_Show(void)
{
	LCD_DisplayStringLine(Line1, (u8*)"        Main");
	sprintf(volt_buf, "    Volt: %3.2fV", volt_R38);
	LCD_DisplayStringLine(Line4, (u8*)volt_buf);
}

/*参数设置界面*/
void Para_Show(void)
{
	LCD_DisplayStringLine(Line1, (u8*)"        Setting");		
	if(select == 0)
	{
		sprintf(Max_Volt_buf, "   Max Volt: %3.1fV", Max_Volt);
		LCD_SetBackColor(Green);		
		LCD_DisplayStringLine(Line2, (u8*)Max_Volt_buf);
		LCD_SetBackColor(White);
	}
	else 
	{
		sprintf(Max_Volt_buf, "   Max Volt: %3.1fV", Max_Volt);
		LCD_DisplayStringLine(Line2, (u8*)Max_Volt_buf);
	}
	if(select == 1)
	{
		sprintf(Min_Volt_buf, "   Min Volt: %3.1fV", Min_Volt);
		LCD_SetBackColor(Green);		
		LCD_DisplayStringLine(Line3, (u8*)Min_Volt_buf);
		LCD_SetBackColor(White);
	}
	else 
	{
		sprintf(Min_Volt_buf, "   Min Volt: %3.1fV", Min_Volt);
		LCD_DisplayStringLine(Line3, (u8*)Min_Volt_buf);
	}
	if(select == 2)
	{
		LCD_SetBackColor(Green);
		sprintf(upled_buf, "   Upper:LD%d", upled);
		LCD_DisplayStringLine(Line4, (u8*)upled_buf);
		LCD_SetBackColor(White);
	}
	else 
	{
		sprintf(upled_buf, "   Upper:LD%d", upled);
		LCD_DisplayStringLine(Line4, (u8*)upled_buf);
	}	
	if(select == 3)
	{
		LCD_SetBackColor(Green);
		sprintf(lowled_buf, "   Lower:LD%d", lowled);
		LCD_DisplayStringLine(Line5, (u8*)lowled_buf);	
		LCD_SetBackColor(White);
	}
	else 
	{
		sprintf(lowled_buf, "   Lower:LD%d", lowled);
		LCD_DisplayStringLine(Line5, (u8*)lowled_buf);	
	}			
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	
	LCD_Init();
	I2CInit();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

	LCD_Clear(White);
	LCD_SetTextColor(Blue);
	LCD_SetBackColor(White);

	upled = EEPROM_Read(0x00);
	HAL_Delay(5);
	lowled = EEPROM_Read(0x01);
	HAL_Delay(5);
	
//	EEPROM_Write(0x02, 30);
//	EEPROM_Write(0x03, 21);
	
	read_Max_Volt = EEPROM_Read(0x02);
	HAL_Delay(5);
	read_Min_Volt = EEPROM_Read(0x03);
	HAL_Delay(5);
	
	Max_Volt = (float)(read_Max_Volt / 10) + (float)(read_Max_Volt % 10) / 10.0f;
	Min_Volt = (float)(read_Min_Volt / 10) + (float)(read_Min_Volt % 10) / 10.0f;
	
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_ADC_Start(&hadc1);
		volt_value = HAL_ADC_GetValue(&hadc1);
		volt_R38 = volt_value / 4096.0f * 3.3f;
		Key_Scan();
		key_dispose();
		if(UI)
		{
			Para_Show();
		}
		else
		{
			Data_Show();
		}
		LED();
  }
  /* USER CODE END 3 */
}

总结

需要完整的工程的小伙伴可以私信我,或者下方留言,公众号回复:蓝桥杯嵌入式即可获得完整代码。