当前位置: 首页 > article >正文

第十一届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)(大学组)

一.题目分析

(1).题目

 

 (2).题目分析

1.计时分析

只要遇到Vmin,就将计时时间重置为0,直到遇到Vmax结束计时

2.按键功能分析

a.B1显示和功能页面相互切换

b.B2每次按下Vmax加0.1,加到3.3V,再次按下返回3.3V

c.B3每次按下Vmin加0.1,加到3.3V,再次按下返回3.3V

d.设备从参数页面退出要判断数据是否合理,判断是否Vmax>Vmin+1 ,同时Vmax和Vmin 可以设置的范围是0.0V~3.3V

2.按键功能分析

a.若当前触发了计时功能,并且计时没有结束,LD1就点亮,否则就熄灭

b.如果判断按键设置的参数不合理,LD2点亮,直到参数合理才熄灭

 (3).逻辑框图

二.CubeMX配置

由于蓝桥杯使用的板子都是STM32G431RBT6,配置都是相同的,模板已经在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客配置完成,大家可以前往学习

三.相关代码实现

(1)MAIN

1.全局变量声明

#include "main.h"
#include "RCC\bsp_rcc.h"
#include "KEY_LED\bsp_key_led.h"
#include "LCD\bsp_lcd.h"
#include "ADC\bsp_adc.h"
#include "TIM\bsp_tim.h"

//***全局变量声明区
//*减速变量
__IO uint32_t uwTick_Key_Set_Point = 0;//控制Key_Proc的执行速度
__IO uint32_t uwTick_Led_Set_Point = 0;//控制Led_Proc的执行速度
__IO uint32_t uwTick_Lcd_Set_Point = 0;//控制Lcd_Proc的执行速度

//*按键扫描专用变量
uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old;

//*LED专用变量
uint8_t ucLed;

//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符

//*定时器专用变量
uint16_t Sec;

//*主逻辑使用的变量
uint8_t Disp_Flag;//用于显示屏幕的代号,0-数据界面,1-参数界面
uint8_t Vmax_Disp = 30;
uint8_t Vmax_Ctrl = 30;
uint8_t Vmin_Disp = 10;
uint8_t Vmin_Ctrl = 10;
uint16_t ADC_X100_Num;//AD采集的数值,放大了100倍
uint8_t Start_Timer_Key_Point = 0;//开始计时关键点,当小于Vmin时,此点为1,当下一次扫描,大于Vmin小于Vmax,此点为2
uint16_t ADC_Befor_Filter;//AD滤波前的数值
uint8_t Filter_Times;//滤波次数控制
void Key_Proc(void);
void Led_Proc(void);
void Lcd_Proc(void);

2.系统主函数

int main(void)
{

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

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

	/*bsp资源的初始化*/
	KEY_LED_Init();
	
	LCD_Init();
	LCD_Clear(Black);
    LCD_SetBackColor(Black);
    LCD_SetTextColor(White);	
    ADC2_Init();
	BASIC_TIM6_Init();

	ADC_X100_Num = ((uint16_t)((((float)getADC2())/4096)*330));
	HAL_Delay(1000);	
  while (1)
  {
		Key_Proc();
		Led_Proc();
		Lcd_Proc();
  }
}

3.子函数

按键扫描子函数

a.逻辑框图

b.程序源码

//***按键扫描子函数
void Key_Proc(void)
{
	if((uwTick -  uwTick_Key_Set_Point)<50)	return;//减速函数   
		uwTick_Key_Set_Point = uwTick;

	ucKey_Val = Key_Scan();
	unKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val); 
	ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val);	
	ucKey_Old = ucKey_Val;

	if(unKey_Down == 1)//B1按键调整屏幕显示内容
	{
		Disp_Flag ^= 0x01;//完成最低位0和1之间的切换
		
		if(Disp_Flag == 0x00)//从参数界面进入到数据界面
		{
			if(Vmax_Disp>=(Vmin_Disp+10))//判别参数设置的数据没有bug
			{
				Vmax_Ctrl = Vmax_Disp;
				Vmin_Ctrl = Vmin_Disp;
				ucLed &= (~0x02);//熄灭LD2小灯
			}
			else//判别数据出BUG了
			{
				ucLed |= 0x02;//点亮LD2小灯
			}
				
		}	
		
		if(Disp_Flag == 0x01)//从数据界面进入到参数界面
		{		
			 Vmax_Disp = Vmax_Ctrl;
			 Vmin_Disp = Vmin_Ctrl;		
		}
	}	
	
	if(Disp_Flag == 0x01)//如果在参数界面,可以调整Vmin和Vmax的数值
	{
		if(unKey_Down == 2)//B2按键调整Vmax增加0.1
		{
			 Vmax_Disp += 1;
			 if(Vmax_Disp > 33)
				 Vmax_Disp = 0;
		}			
		else if(unKey_Down == 3)//B3按键调整Vmin增加0.1
		{
			 Vmin_Disp += 1;
			 if(Vmin_Disp > 33)
				 Vmin_Disp = 0;
		}		
	}
}
LED扫描子函数

a.程序源码

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

	LED_Disp(ucLed);
}
LCD扫描子函数

a.逻辑框图

b.程序源码

void Lcd_Proc(void)
{
	if((uwTick -  uwTick_Lcd_Set_Point)<100)	return;//减速函数
		uwTick_Lcd_Set_Point = uwTick;	

	for(Filter_Times = 0; Filter_Times<=2; Filter_Times++)
	{
		ADC_Befor_Filter += getADC2();
		HAL_Delay(10);
	}
	
	ADC_X100_Num = ((uint16_t)((((float)ADC_Befor_Filter)/4096)*110));
	ADC_Befor_Filter = 0;
	
	//判别1
	if(ADC_X100_Num < (Vmin_Ctrl*10))//第一次采集,小于Vmin
	{
		Start_Timer_Key_Point = 1;//开始计时关键点一半有效。
	}
	
	//判别2
	if((ADC_X100_Num > (Vmin_Ctrl*10))&&(ADC_X100_Num < (Vmax_Ctrl*10)))//第二次采集,大于Vmin,小于Vmax
	{
		if(Start_Timer_Key_Point == 1)//当第一个关键点有效后,第二个关键点产生,置标志位
		{
			Start_Timer_Key_Point = 2;//开始计时关键点另一半有效
			Sec	= 0 ;	
			//*打开基本定时器
			HAL_TIM_Base_Start_IT(&htim6);//每1s触发一次中断	
      ucLed |= 0x01;//点亮LD1小灯			
		}
	}	
	
	//判别3
	if(ADC_X100_Num > (Vmax_Ctrl*10))//又一次采集,大于Vmax
	{		
			//*停止基本定时器
			HAL_TIM_Base_Stop_IT(&htim6);//每1s触发一次中断	
      ucLed &= (~0x01);//熄灭LD1小灯			
	}
	if(Disp_Flag == 0)//数据界面
	{
		sprintf((char *)Lcd_Disp_String, "      Data");
		LCD_DisplayStringLine(Line0, Lcd_Disp_String);	
	
		sprintf((char *)Lcd_Disp_String, " V:%4.2fV       ",(ADC_X100_Num*0.01));
    LCD_DisplayStringLine(Line2, Lcd_Disp_String);		

		sprintf((char *)Lcd_Disp_String, " T:%02ds        ",(unsigned int)Sec);
    LCD_DisplayStringLine(Line3, Lcd_Disp_String);				
	}
	
	else if(Disp_Flag == 1)//参数界面
	{
		sprintf((char *)Lcd_Disp_String, "      Para");
		LCD_DisplayStringLine(Line0, Lcd_Disp_String);	
	
		sprintf((char *)Lcd_Disp_String, " Vmax:%3.1fV         ",(Vmax_Disp*0.1));
    LCD_DisplayStringLine(Line2, Lcd_Disp_String);		

		sprintf((char *)Lcd_Disp_String, " Vmin:%3.1fV         ",(Vmin_Disp*0.1));
    LCD_DisplayStringLine(Line3, Lcd_Disp_String);	
	}
}
基本定时器6更新回调函数

a.程序源码

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM6)
  {
			Sec++;
	}
}

(2)BSP

在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习


http://www.kler.cn/news/326306.html

相关文章:

  • HTTPS协议详解:从原理到流程,全面解析安全传输的奥秘
  • 资产管理之源代码防泄密的挑战
  • Redis 简单的消息队列
  • 并发、并行和异步设计
  • Linux 信号保存
  • 【菜菜的sklearn机器学习】(4)随机森林
  • 六,MyBatis-Plus 扩展功能(逻辑删除,通用枚举,字段类型处理,自动填充功能,防全表更新与删除插件,MybatisX快速开发插件)
  • 探索基于知识图谱和 ChatGPT 结合制造服务推荐前沿
  • 【Android 14源码分析】WMS-窗口显示-流程概览与应用端流程分析
  • C语言中的日志机制:打造全面强大的日志系统
  • 翻译:Recent Event Camera Innovations: A Survey
  • 30秒内交易股票,程序化交易的定义与特点
  • 【Windows】自定义显示器的分辨率
  • @Transactional的实现原理
  • openKylin--安装 .net6.0
  • 【linux】gdb
  • 鸿蒙HarmonyOS之封装Http请求工具类
  • Spring Boot 进阶-第一个程序HelloWorld
  • C语言 | Leetcode C语言题解之第447题回旋镖的数量
  • knowLedge-Vue I18n 是 Vue.js 的国际化插件
  • SpringMVC源码-AbstractHandlerMethodMapping处理器映射器将@Controller修饰类方法存储到处理器映射器
  • 关于开发板与虚拟机网络不通问题排查
  • 在线点餐新体验:Spring Boot 点餐系统
  • excel不经过后台实现解析和预览(vue)
  • YOLOv8 Flask整合问题
  • Git 使用方法
  • c++泛型编程
  • 【hot100-java】【二叉树的层序遍历】
  • Excel:常用函数
  • vue中异步批量删除列表数据