蓝桥杯嵌入式STM32G431——第十一届第一场省赛真题及代码

第十一届第一场省赛真题

蓝桥杯嵌入式STM32G431——第十一届第一场省赛真题及代码_第1张图片
蓝桥杯嵌入式STM32G431——第十一届第一场省赛真题及代码_第2张图片
蓝桥杯嵌入式STM32G431——第十一届第一场省赛真题及代码_第3张图片
蓝桥杯嵌入式STM32G431——第十一届第一场省赛真题及代码_第4张图片

主函数部分代码(不包含各模块初始化代码)

#include "main.h"
#include "adc.h"
#include "lcd.h"
#include "led_key.h"
#include "rcc.h"
#include "tim.h"

//***通过滴答定时器实现执行速度控制变量
__IO uint32_t uwTick_LED_Speed_Ctrl;
__IO uint32_t uwTick_KEY_Speed_Ctrl;
__IO uint32_t uwTick_LCD_Speed_Ctrl;
__IO uint32_t uwTick_ADC_Speed_Ctrl;

//***全局变量区***//
uint8_t ucLED; //用于控制LED的变量
uint8_t key_value,key_down,key_up;	//按键的三行代码
static uint8_t key_old;
uint8_t LCD_String_Disp[21];	//LCD字串显示数组

uint8_t Time_Count; //用于时间计数1s加1
uint8_t Interface_Ctrl = 0; //界面控制 默认为数据界面-0 参数界面-1
uint8_t Volt_Max_Comp = 30; //Vmax参数默认为3.0 
uint8_t Volt_Min_Comp = 10; //Vmin参数默认为1.0
uint8_t Volt_Max_Active = 30; //Vmax有效值 
uint8_t Volt_Min_Active = 10; //Vmin有效值

float ADC_Volt; //一次ADC电压值变量
float ADC_Collected_Data_Sum; //十次电压值之和
uint8_t ADC_Collected_Data_Num;	//电压采集次数
float ADC_Collected_Data_Aver;	//十次电压值的平均值 滤波后的电压值 500m刷新一次

uint8_t Timing_Start;	//计时开始条件标志
uint8_t Timing_Stop;	//计时结束条件标志

//***子函数声明区***//
void SystemClock_Config(void);
void LED_Proc(void);
void KEY_Proc(void);
void LCD_Proc(void);
void ADC_Volt_Data_Proc(void);

//***主函数区***//
int main(void)
{
  HAL_Init();
  SystemClock_Config();
	
	//**外设初始化区
	LED_KEY_Init();
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	ADC2_Init();
	TIM6_Init();

  while (1)
  {
		ADC_Volt_Data_Proc();
    LED_Proc();
		KEY_Proc();
		LCD_Proc();  
  }
}

//***子函数区***//

void LED_Proc(void)
{
	if((uwTick - uwTick_LED_Speed_Ctrl)<100) return;
		uwTick_LED_Speed_Ctrl = uwTick;	//子函数100ms扫描执行一次
	
	LED_Disp(ucLED);
}

void KEY_Proc(void)
{
	if((uwTick - uwTick_KEY_Speed_Ctrl)<100) return;
		uwTick_KEY_Speed_Ctrl = uwTick;	//子函数100ms扫描执行一次
	
	key_value = KEY_Scan();
	key_down = key_value & (key_value ^ key_old);
	key_up = ~key_value & (key_value ^ key_old);
	key_old = key_value;
	
	switch(key_down)
	{
		case 1: //按键B1 切换选择数据界面或参数界面
			if(Interface_Ctrl == 0)
			{
				Interface_Ctrl = 1;		
				LCD_Clear(Black);
			}
			else
			{
				Interface_Ctrl = 0;
				
				if(Volt_Max_Comp >= (Volt_Min_Comp + 10)) //满足Vmax >= Vmin+1.0V 则设置的Vmax和Vmin有效	LD2关闭
				{
					Volt_Max_Active = Volt_Max_Comp;
					Volt_Min_Active = Volt_Min_Comp;
					ucLED &= 0x01;	//LD1保持 LD2关闭
				}
				else //如果条件不满足 LD2点亮
				{
					ucLED |= 0x02;
				}
				LCD_Clear(Black);
			}
			break;
			
		case 2: //按键B2 Vmax参数+0.1
			if(Interface_Ctrl == 1)
			{
				Volt_Max_Comp += 1;
				if(Volt_Max_Comp > 33)
					Volt_Max_Comp = 0;
			}
			break;
			
		case 3: //按键B3 Vmin参数+0.1
			if(Interface_Ctrl == 1)
			{
				Volt_Min_Comp += 1;
				if(Volt_Min_Comp > 33)
					Volt_Min_Comp = 0;
			}
			break;
	}
}

void ADC_Volt_Data_Proc(void)	//ADC电压数据采集数字滤波处理
{
	if((uwTick - uwTick_ADC_Speed_Ctrl)<50) return;
		uwTick_ADC_Speed_Ctrl = uwTick;	//ADC电压值每50ms采集一次
	
	//采用中值滤波的方法 500ms内采集十次后求平均值得滤波后电压
	ADC_Collected_Data_Num++;
	ADC_Volt = Get_ADC_Value()*3.3/4096;	//一次电压值的采集
	ADC_Collected_Data_Sum += ADC_Volt;
	if(ADC_Collected_Data_Num == 10)
	{
		ADC_Collected_Data_Aver = ADC_Collected_Data_Sum/10;	//滤波后得到的电压值
		ADC_Collected_Data_Sum = 0;
		ADC_Collected_Data_Num = 0;
	}
	
	//***计时处理
	if(ADC_Collected_Data_Aver < ((float)Volt_Min_Active/10.0f)) //只有在电压递增时才开始计时
		Timing_Start = 1;
		
	if(Timing_Start == 1) //如果满足计时条件
	{
		if(ADC_Collected_Data_Aver >= ((float)Volt_Min_Active/10.0f))	//当电压值大于下限电压值时
		{
				ucLED |= 0x01;	//触发计时LD1点亮
				Time_Count = 0;	//计数值清零
				HAL_TIM_Base_Start_IT(&htim6); //打开定时器中断 进入中断回调函数
				Timing_Start = 0;	//计时开始条件清零关闭
		}
	}
	
	if(ADC_Collected_Data_Aver < ((float)Volt_Max_Active/10.0f)) //只有在电压递增时打开计时停止标志
		Timing_Stop = 1;
	
	if(Timing_Stop == 1)	//当满足计时停止条件时
	{
		if(ADC_Collected_Data_Aver >= ((float)Volt_Max_Active/10.0f)) //当电压值大于上限电压值时
		{
			HAL_TIM_Base_Stop_IT(&htim6); //停止计时
			ucLED &= 0x02; //计时关闭LD1关闭 LD2保持
			Timing_Stop = 0; //计时停止条件清零关闭
		}
	}
}

void LCD_Proc(void)
{
	if((uwTick - uwTick_LCD_Speed_Ctrl)<150) return;
		uwTick_LCD_Speed_Ctrl = uwTick;	//子函数150ms扫描执行一次

	if(Interface_Ctrl == 0) //在数据显示界面
	{
		memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp, "      Data");
		LCD_DisplayStringLine(Line0, LCD_String_Disp);
		
		memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp, " V:%4.2fV",ADC_Collected_Data_Aver);
		LCD_DisplayStringLine(Line2, LCD_String_Disp);

		memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp, " T:%02ds",Time_Count);
		LCD_DisplayStringLine(Line3, LCD_String_Disp);				
	}
	else	//在参数设置界面
	{
		memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp, "      Para");
		LCD_DisplayStringLine(Line0, LCD_String_Disp);
		
		memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp, " Vmax:%3.1fV",(float)Volt_Max_Comp/10.0f);
		LCD_DisplayStringLine(Line2, LCD_String_Disp);

		memset(LCD_String_Disp,0,sizeof(LCD_String_Disp));
		sprintf((char*)LCD_String_Disp, " Vmin:%3.1fV",(float)Volt_Min_Comp/10.0f);
		LCD_DisplayStringLine(Line3, LCD_String_Disp);		
	}
}

//***基本定时器6更新回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim -> Instance == TIM6)
	{
		Time_Count++;	//定时器计数值1s加1
	}

第十一届第一场省赛工程代码

链接:https://pan.baidu.com/s/1kKphnG2xVGiF1t0MCeBATw
提取码:q9xl

你可能感兴趣的:(蓝桥杯嵌入式,stm32,蓝桥杯,单片机)