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

news2024/11/20 14:29:47

一.题目分析

(1).题目

 (2).题目分析

1.PWM输出分析

模式切换时,占空比要不变, 在五秒之内就要变化成目标频率,同时要求频率的步进值要小于200hz

为了使步进值小于200hz,那么在五秒的时间之内,每次变换200hz,则要变换大于20次,但要取整数,只能让次数等于25次,因此符合要求的是在五秒时间之内,每次变换160hz,计算如下

因此最终是每200ms/160hz/次

2.按键功能分析 

a. B1完成界面的切换

b. B2, 数据界面下,切换低高频模式,5秒内不可再次触发。在参数界面按下切换R和K,退出参数界面就生效。

c. B3调整参数加1

d. B4在参数界面调整参数减1。在数据界面,长按B4,锁定占空比不受R37电位器输出电压的控制,短按B4,解锁R37输出电压对占空比的控制。

长短按的判断方式

当按键按下,开始计时,松开按键时,判断这一过程持续了多久,小于两秒是短按,大于两秒是长按。

 3.统计功能分析 

高频低频输出模式下的最大速度分开统计,保持时间不足2秒的速度值不纳入统计:

定义两个数值,当前速度(Vn)和之前速度(Vf),每读一次速度值就记录到当前速度,同时将上一次的速度保存到之前速度值里,当读到当前速度和之前速度相等时,开始计时,当两秒达到,就把当前的数值保存到最大值里,然后重复之前的操作,并且不断更新最大值,最终找到真正的最大值 

 4.pwm输出功能分析 

分析电压值和占空比的线性关系

(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的执行速度
//__IO uint32_t uwTick_Usart_Set_Point = 0;//控制Usart_Proc的执行速度

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

//*LED专用变量
uint8_t ucLed = 0x01;

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

//*pwm相关变量
uint16_t PWM_T_Count;

//**自定义变量区
float R37_Voltage;
uint8_t Duty_hundredfold;
uint8_t Duty_Change_Lock;

uint8_t R_Ctrl = 1;
uint8_t R_Show = 1;
uint8_t K_Ctrl = 1;
uint8_t K_Show = 1;

uint32_t Freq;
float V;
float V_Storage[5];
float V_Index;
float V_Max_High_Freq_Out;
float V_Max_Low_Freq_Out;

uint8_t Out_Freq_Mode;

uint8_t Screen_Disp;


__IO uint32_t uwTick_Long_Short_Key_Point = 0;
uint8_t Long_Short_Key_Down_Flag;

uint8_t Out_Freq_Change_State;//0-没开启,1-低到高,2-高到低
uint8_t Out_Freq_Change_Times;
uint8_t High_Low_Freq_Change_N;
uint16_t Out_Freq = 4000;
//***子函数声明区
void Key_Proc(void);
void Led_Proc(void);
void Lcd_Proc(void);
void Usart_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();

    PWM_OUTPUT_TIM2_Init();
    F_TEST_TIM3_Init();

	/*外设使用基本配置*/
		
	//*输入捕获PWM启动
	HAL_TIM_Base_Start(&htim3);  /* 启动定时器 */
  HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);		
		
    HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);	//PA1
		
		__HAL_TIM_SET_AUTORELOAD(&htim2, (uint16_t)((1000000.0/Out_Freq)-1));
	
		
		
  while (1)
  {
		Key_Proc();
		Led_Proc();
		Lcd_Proc();
//		Usart_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;
	
	//********B1***********//
	if(unKey_Down == 1)//界面轮换
	{
		if(Screen_Disp == 0x00)
		{
			Screen_Disp = 0x10;
			ucLed &= (~0x01);		
			
		}
		else if((Screen_Disp&0xF0) == 0x10)
		{
			Screen_Disp = 0x20;
			
			R_Ctrl = R_Show;//退出生效
			K_Ctrl = K_Show;	
			
		}
		else if(Screen_Disp == 0x20)
		{
			Screen_Disp = 0x00;
			ucLed |= 0x01;			
		}
    LCD_Clear(Black);
	}
	
	//********B2***********//	
	if(unKey_Down == 2)//区分界面调整R和K,或者,高低频切换
	{
		if((Screen_Disp&0xF0) == 0x10)//参数界面
		{
			Screen_Disp ^= 0x01;
		}
		
		if(Screen_Disp == 0x00)//数据界面
		{
//			Out_Freq_Mode ^= 0x01;
			if(Out_Freq_Mode == 0)//如果此时是低频模式,进入低到高变化模式
				Out_Freq_Change_State	= 1;
			else//如果此时是高频模式,进入高到低变化模式
				Out_Freq_Change_State	= 2;				
			
			V_Storage[0] = 0;
			V_Storage[1] = 0;			
			V_Storage[2] = 0;			
			V_Storage[3] = 0;			
			V_Storage[4] = 0;
			
			
		}		
		
		
	
	}	
	
	//*******B3************//
	if(unKey_Down == 3)// 
	{
		
		if(Screen_Disp== 0x10)//参数界面,调整+R
		{
			if( ++R_Show == 11 ) 
				R_Show = 1;
		}
		else if(Screen_Disp== 0x11)//参数界面,调整+K
		{
			if( ++K_Show == 11 ) 
				K_Show = 1;			
		}		
		
		
	}		
	
	
	
	//*******B4************//	
	if(unKey_Down == 4)// 
	{
		if(Screen_Disp== 0x10)//参数界面,调整-R
		{
			if( --R_Show == 0 ) 
				R_Show = 10;			
		}
		else if(Screen_Disp== 0x11)//参数界面,调整-K
		{
			if( --K_Show == 0 ) 
				K_Show = 10;						
		}		
	}		
	
	
	if(Screen_Disp== 0x00)//数据界面
	{	
		if(unKey_Down == 4)
		{
			uwTick_Long_Short_Key_Point = uwTick;
//			Long_Short_Key_Down_Flag = 1;
		}
		if(ucKey_Up == 4)
		{		
			if((uwTick - uwTick_Long_Short_Key_Point)>2000)//长按生效
			{
				Duty_Change_Lock = 1;
				ucLed |= 0x04;					
			}
			else//短按生效
			{
				Duty_Change_Lock = 0;		
				ucLed &= (~0x04);						
			}		
		}
	}
}

4.LED扫描子函数

a. 逻辑导图

b. 程序源码

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

	
	
	//实现PWM输出
	if(Out_Freq_Change_State == 1)//低到高变化状态
	{
			Out_Freq += 160;
			__HAL_TIM_SET_AUTORELOAD(&htim2, (uint16_t)((1000000.0/Out_Freq)-1));			
			__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, (uint32_t)((1000000.0/Out_Freq)*0.01*Duty_hundredfold));		
		
			Out_Freq_Change_Times++;
			if(Out_Freq_Change_Times == 25)
			{
				Out_Freq_Change_State = 0;
				Out_Freq_Change_Times = 0;
				Out_Freq_Mode = 1;
				High_Low_Freq_Change_N++;
			}
	}
	else if(Out_Freq_Change_State == 2)//高到低变化状态
	{
			Out_Freq -= 160;
			__HAL_TIM_SET_AUTORELOAD(&htim2, (uint16_t)((1000000.0/Out_Freq)-1));			
			__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, (uint32_t)((1000000.0/Out_Freq)*0.01*Duty_hundredfold));					

			Out_Freq_Change_Times++;
			if(Out_Freq_Change_Times == 25)
			{
				Out_Freq_Change_State = 0;
				Out_Freq_Change_Times = 0;
				Out_Freq_Mode= 0;
				High_Low_Freq_Change_N++;				
			}		
	}
}

5.LCD扫描子函数

a. 逻辑导图

b. 程序源码

void Lcd_Proc(void)
{
	if((uwTick -  uwTick_Lcd_Set_Point)<100)	return;//减速函数
		uwTick_Lcd_Set_Point = uwTick;
//****数据采集区域
		//采集电压
		R37_Voltage = ((((float)getADC2())/4096)*3.3);
		
		//测算占空比
		if(Duty_Change_Lock == 0)//解锁状态
		{
			if(R37_Voltage <= 1)
				Duty_hundredfold = 10;
			else if(R37_Voltage >= 3)
				Duty_hundredfold = 85;
			else 
				Duty_hundredfold = (uint8_t)(R37_Voltage*37.5 - 27.5);
			
			__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, (uint32_t)((1000000.0/Out_Freq)*0.01*Duty_hundredfold));					
	  }

	
		
		//测量频率
		Freq = (uint32_t)(1000000.0/PWM_T_Count);
		
		//测算速度
		V = ((Freq * 0.0628 * R_Ctrl) / (float)K_Ctrl);
		V_Index++;
		if(V_Index == 5)
		{
			V_Index = 0;
				
			V_Storage[0] = V_Storage[1];
			V_Storage[1] = V_Storage[2];			
			V_Storage[2] = V_Storage[3];			
			V_Storage[3] = V_Storage[4];			
			V_Storage[4] = V;
			
			if((V_Storage[0] == V)&&(V_Storage[1] == V)&&(V_Storage[2] == V)&&(V_Storage[3] == V)&&(V_Storage[4] == V))//表示出现了有效速度
			{
				if(Out_Freq_Mode == 0)//低频模式
				{
					if(V >= V_Max_Low_Freq_Out )
					{
						V_Max_Low_Freq_Out = V;
					}
				}
				else//高频模式
				{
					if(V >= V_Max_High_Freq_Out )
					{
						V_Max_High_Freq_Out = V;
					}				
				}
			}
		}
		
		
//	sprintf((char *)Lcd_Disp_String, "R37_Vol:%6.3fV",R37_Voltage);
//	LCD_DisplayStringLine(Line8, Lcd_Disp_String);			
//	sprintf((char *)Lcd_Disp_String, "R39P:%05dHz",(unsigned int)(Freq));
//	LCD_DisplayStringLine(Line9, Lcd_Disp_String);			
		
//****数据显示区域
		if(Screen_Disp == 0x00)
		{
			sprintf((char *)Lcd_Disp_String, "        DATA        ");
			LCD_DisplayStringLine(Line1, Lcd_Disp_String);			
		
			if(Out_Freq_Mode == 0)
				sprintf((char *)Lcd_Disp_String, "     M=L  ");
			else
				sprintf((char *)Lcd_Disp_String, "     M=H  ");			
			LCD_DisplayStringLine(Line3, Lcd_Disp_String);	
			
			sprintf((char *)Lcd_Disp_String, "     P=%02d%%  ",(uint32_t)Duty_hundredfold);
			LCD_DisplayStringLine(Line4, Lcd_Disp_String);				
			
			sprintf((char *)Lcd_Disp_String, "     V=%.1f        ",V);
			LCD_DisplayStringLine(Line5, Lcd_Disp_String);				
		
		}
	  if((Screen_Disp&0xF0) == 0x10)
		{
			sprintf((char *)Lcd_Disp_String, "        PARA        ");
			LCD_DisplayStringLine(Line1, Lcd_Disp_String);		

			sprintf((char *)Lcd_Disp_String, "     R=%-d  ",(uint32_t)R_Show);
			LCD_DisplayStringLine(Line3, Lcd_Disp_String);	
			
			sprintf((char *)Lcd_Disp_String, "     K=%-d  ",(uint32_t)K_Show);
			LCD_DisplayStringLine(Line4, Lcd_Disp_String);	
			
		}
		if(Screen_Disp == 0x20)
		{
			sprintf((char *)Lcd_Disp_String, "        RECD        ");
			LCD_DisplayStringLine(Line1, Lcd_Disp_String);				
		
			sprintf((char *)Lcd_Disp_String, "     N=%-d   ",(uint32_t)High_Low_Freq_Change_N);
			LCD_DisplayStringLine(Line3, Lcd_Disp_String);				
			
			sprintf((char *)Lcd_Disp_String, "     MH=%.1f   ",V_Max_High_Freq_Out);
			LCD_DisplayStringLine(Line4, Lcd_Disp_String);						
			
			sprintf((char *)Lcd_Disp_String, "     ML=%.1f   ",V_Max_Low_Freq_Out);
			LCD_DisplayStringLine(Line5, Lcd_Disp_String);				
		}
 
		if(Out_Freq_Change_State != 0)
			ucLed ^= 0x02;
		else 
			ucLed &= (~0x02);				

		LED_Disp(ucLed);	

}

6. 输入捕获PWM中断回调

a. 程序源码

//输入捕获PWM中断回调
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	  if(htim->Instance==TIM3)
  {
				if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
			{
				PWM_T_Count =  HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;
			}
	}	
}

(2)BSP

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2199701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI绘画:人工智能颠覆艺术创作的新时代

*AI绘画的震撼与魅力* 你是否曾幻想过&#xff0c;手握画笔便能创造出前所未有的艺术作品&#xff1f;当我们谈及艺术&#xff0c;总会联想到那份独特的创意和灵感。而如今&#xff0c;随着人工智能的迅猛发展&#xff0c;AI绘画正以其独特的方式&#xff0c;颠覆着传统的艺术…

XTR115电流环电路原理研究【文献】

作者&#xff1a;昝 勇&#xff0c;罗永红&#xff0c;王沛莹 中航工业 摘要&#xff1a; 针对各种数据采集与监控中抗恶劣电磁干扰环境的需求&#xff0c;给出一种基于XTB115的低功耗两线4&#xff5e;20 mA电流环数据传输电路&#xff0c;首先讨论了XTR115的性能特点和工作原…

RabbitMQ简介及安装类

RabbitMQ概述-MQ介绍 RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;它支持多种消息协议&#xff0c;并且可以轻松地与多种编程语言和框架集成。RabbitMQ是使用Erlang语言编写的&#xff0c;因此它具有高并发和高可用性的特点。以下是RabbitMQ的一些关键特性和概念 消息…

两文读懂DDD领域驱动设计,举例说明,通俗易懂【值得收藏】

最近对架构莫名的感兴趣&#xff0c;慢慢觉得架构本身是为了提供方便&#xff0c;定制规范&#xff0c;目标一致并更好的协作&#xff0c;它的变动也并不是像变形金刚一样&#xff0c;而是像幼苗一样按规律成长起来的 DDD是一种方法也是一种思想&#xff0c;大家前面个别概念看…

C++-再探构造函数(进阶)

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 前言 来到类和对象最后一个章节&#xff0c;这里的难度已经极大程度的降低了 再探构造…

FFMpeg源码分析,关键结构体分析(一)

http://lazybing.github.io/blog/categories/ffmpegyuan-ma-fen-xi/ 一、下载FFmpeg的编译源码 进入网站&#xff1a;http://ffmpeg.org/download.html二、编译源码 执行下述命令&#xff1a; ./configure --prefix/usr/local/ffmpeg --enable-debug3 --enable-ffplay sudo …

22年408数据结构

第一题&#xff1a; 解析&#xff1a; 观察一下这个程序&#xff1a;我们注意到最外层的循环是从i1开始的&#xff0c;每次ii*2&#xff0c;直到i<n为止&#xff0c;假设程序总共执行k次执行&#xff0c;则有2^(k1)>n。则k1>log(2)n这里是以2为底n的对数, k>log(2)…

Oracle11g服务器linux 安装

一&#xff0e;安装前准备 1.检查硬件&#xff08;内存&#xff0c;交换分区&#xff0c;tmp分区&#xff0c;cpu信息&#xff0c;内核版本&#xff09; # grep MemTotal /proc/meminfo # grep SwapTotal /proc/meminfo # df -k /tmp&#xff08;>400M&#xff09; # grep …

汽车氛围灯行业分析:未来几年年复合增长率CAGR为7.15%

汽车氛围灯是一种起到装饰和指示作用的照明灯&#xff0c;它属于装饰类的照明灯。通常是红色、蓝色、绿色等&#xff0c;主要是为了使车厢更加绚丽&#xff0c;烘托气氛&#xff0c;营造室内情调。氛围灯能够具有以下特性&#xff1a;功能性、舒适性、设计感、豪华感、个性化、…

【C++】——继承

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

深入解析MySQL事务管理:ACID特性与基本操作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

自动猫砂盆是养猫新型智商税吗?测评2024年热门款智能猫砂盆分享

铲屎官们只要一察觉到猫主子拉屎&#xff0c;就要马上去铲掉&#xff0c;这不仅是为了猫砂盆中其他干净的猫砂&#xff0c;更是为了防止猫屎残留发臭&#xff0c;特别是便便这种东西&#xff0c;一旦放久了就很招虫子&#xff0c;家里出现这些虫子又要大扫除消杀&#xff0c;特…

2024 年顶级智能文档处理解决方案

在当今的数字时代&#xff0c;智能文档处理(IDP) 对于提高业务效率和降低成本至关重要。IDP 可实现文档处理的自动化&#xff0c;最大限度地减少人工劳动和错误。由于有众多 IDP 解决方案可供选择&#xff0c;因此选择合适的解决方案可能具有挑战性。 本指南回顾了 10 款最…

Android Handler消息机制完全解析-同步屏障(三)

Android 消息机制Handler完全解析(一) Android 消息机制Handler完全解析(二) 前面两篇我们主要讲了Handler消息机制的一些基础&#xff0c;今天来看下消息屏障&#xff0c;通过本篇文章你将学到如下知识点 (1)什么是同步屏障 (2)为什么要有同步屏障 (3)同步屏障的原理 (4…

获取时隔半个钟的三天

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

24下软考中级系统集成项目管理工程师怎么备考?

备考资料&#xff1a; 1.教材 教材可以准备由清华大学出版社出版的系统集成项目管理工程师教材&#xff0c;这也是官方所推荐的教材&#xff0c;准备这本书是绝对没错的。 2.真题 真题也是在备考过程中少不了的资料之一&#xff0c;而且系统集成项目管理工程师考试就是需要多…

初始项目托管到gitee教程,开箱即用

0.本地仓库与远程仓库关联&#xff08;需先在gitee创建仓库&#xff09; ①打开powershell生成ssh key ssh-keygen -t ed25519 -C "Gitee SSH Key"-t key 类型-C 注释 生成成功如下&#xff0c;并按下三次回车 ②查看公私钥文件 ls ~/.ssh/输出&#xff1a; id_…

华为---Super VLAN简介及示例配置

目录 1. Super VLAN技术产生背景 2. Super VLAN概念 3. Super VLAN应用场景 4. Super VLAN工作原理 5. Super-VLAN主要配置命令 6. Super-VLAN主要配置步骤 7. 示例配置 7.1 示例场景 7.2 网络拓扑 7.3 配置代码 7.4 代码解析 7.5 测试验证 1. Super VLAN技术产生背…

虹软人脸 报错 Can‘t find dependent libraries

系列文章目录 文章目录 系列文章目录一、虹软人脸 报错 Can‘t find dependent libraries 一、虹软人脸 报错 Can‘t find dependent libraries 在项目中使用了 虹软 人脸识别SDK&#xff0c;环境一直出错。 错误&#xff1a; Can’t find dependent libraries 从错误信息来…

项目启动 | 盘古信息赋能奥尼视讯数字化转型升级,实现全面数智化发展

随着信息技术的飞速发展与全球市场竞争的日益激烈&#xff0c;传统制造业正面临生存和发展的危机&#xff0c;制造企业为谋求发展&#xff0c;纷纷开启数字化转型之路&#xff0c;深度融入数字技术&#xff0c;实现生产流程的智能化、管理模式的精细化以及产品服务的个性化&…