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

第十一届蓝桥杯嵌入式省赛程序设计题解析(基于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;//判别1if(ADC_X100_Num < (Vmin_Ctrl*10))//第一次采集,小于Vmin{Start_Timer_Key_Point = 1;//开始计时关键点一半有效。}//判别2if((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小灯			}}	//判别3if(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博客里面有详细的讲解,大家可前往此链接学习

相关文章:

  • 第五章 linux实战-挖矿 二
  • Azure OpenAI检索增强微调:使用 GPT-4o 对 GPT-4o mini 进行微调,以适应特定领域的应用
  • 【回眸】Tessy 单元测试软件使用指南(四)常见报错及解决方案与批量初始化的经验
  • 分布式难题-三座大山NPC
  • 微信卖茶叶套路
  • 华为源NAT技术与目的NAT技术
  • debian linux 只安装mysql client
  • 从GDAL中 读取遥感影像的信息
  • 67 自注意力_by《李沐:动手学深度学习v2》pytorch版
  • 【GAN 图像生成】
  • 【Python】Python多行输入储存为字典,值为列表
  • ServiceEntry WorkloadEntry WorkloadGroup
  • 《十年国庆游,洞察中国旅游新趋势》
  • GraphRAG
  • 模糊测试SFuzz亮相第32届中国国际信息通信展览会
  • Apache Pulsar 2.1 重磅发布
  • Apache的基本使用
  • CEF与代理
  • CODING 缺陷管理功能正式开始公测
  • ECMAScript6(0):ES6简明参考手册
  • httpie使用详解
  • Java 内存分配及垃圾回收机制初探
  • mysql外键的使用
  • Netty源码解析1-Buffer
  • Objective-C 中关联引用的概念
  • 对JS继承的一点思考
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 构建二叉树进行数值数组的去重及优化
  • 力扣(LeetCode)21
  • 前端
  • 微服务核心架构梳理
  • 我是如何设计 Upload 上传组件的
  • 用mpvue开发微信小程序
  • NLPIR智能语义技术让大数据挖掘更简单
  • ​人工智能书单(数学基础篇)
  • #includecmath
  • #pragma pack(1)
  • #宝哥教你#查看jquery绑定的事件函数
  • #职场发展#其他
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (Python) SOAP Web Service (HTTP POST)
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (分享)自己整理的一些简单awk实用语句
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (已解决)vscode如何选择python解释器
  • ***利用Ms05002溢出找“肉鸡
  • .net core 管理用户机密
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET 的程序集加载上下文
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • @ResponseBody
  • [C++]AVL树怎么转
  • [Cocoa]_[初级]_[绘制文本如何设置断行方式]