第十届蓝桥杯嵌入式省赛程序设计题(HAL库版)

蓝桥杯嵌入式(HAL库版)省赛系列文章

第六届蓝桥杯嵌入式省赛程序设计题(HAL库版)
第九届蓝桥杯嵌入式省赛程序设计题(HAL库版)
第十一届蓝桥杯嵌入式省赛程序设计题(HAL库版)
第十三届蓝桥杯嵌入式省赛程序设计题(HAL库版)



前言

报名参加蓝桥杯嵌入式组别,通过做往年省赛例题的方式进行能力整体提升,需要的小伙伴可以简单看一下哈,写的不好,还请大家多多包涵,欢迎大佬指出问题!
需要其他届赛题的朋友可以从顶部链接直达喔!
闲话少说,进入正题!


一、赛题要求

1.硬件框图

硬件框图

2.功能描述

基本功能数据显示界面
参数配置界面
参数配置界面要求
按键功能B1
按键功能B2
按键功能B3、B4
要求
初始状态:

  1. 默认输出提醒指示灯。
    超过上限提醒指示灯:LD1
    低于下限提醒指示灯:LD2
  2. 默认电压阈值参数。
    电压的上限值:2.4V
    电压的下限值:1.2V

根据上述任务要求,使用STM32CubeMX生成Keil文件进行程序编写。

二、配置工程

1.配置流程

使用STM32CubeMX的流程可以概括为四个步骤,分别为:选择芯片、配置引脚、配置时钟、建立工程

1.1选择芯片

蓝桥杯嵌入式平台所使用的芯片为STM32G431RBTx,故我们进行搜索并建立工程。
在这里插入图片描述

1.2配置引脚

LED灯由PC8-PC15控制,低电平点亮,由PD2引脚控制锁存,低电平变为高电平开锁,高电平变为低电平上锁,设置引脚模式为输出模式。在这里插入图片描述
开发板上共配备了4个按键,分别连接在PB0,PB1,PB2,PA0引脚上,设置引脚模式为输入模式。在这里插入图片描述
由于题目中设计电压测量,故需要配置ADC,参考原理图可知,R37与PB15相连,PB15为ADC2_IN15在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3配置时钟

时钟配置这里考虑到芯片最高频率为170MHz,所以我直接选择将HCLK一栏设置为最大值170MHz在这里插入图片描述

1.4建立工程

一定要将Toolchain/IDE更改为MDK-ARM,版本号根据大家的实际情况确定即可
在这里插入图片描述
这里我勾选的是只将必要的库文件粘贴过来,可以减小工程建立的大小。
在这里插入图片描述
至此,建立工程阶段结束,可以开始写代码啦!

三、软件实现(模块化编程)

1. 按键扫描

uint8_t Key_Scan(GPIO_TypeDef *GPIOx,uint16_t GPIO_PIN)
{
	if(HAL_GPIO_ReadPin(GPIOx,GPIO_PIN) == RESET)
	{
		while(HAL_GPIO_ReadPin(GPIOx,GPIO_PIN) == RESET)
			;
		return 2;
	}
	else
		return 1;
}

2. 按键控制电压参数改变(配合扫描函数使用)

void Key_Volt_Change(double *Volt)
{
	if (Key_Scan(B3_Plus_GPIO_Port,B3_Plus_Pin) == 2)
	{
		*Volt += 0.3;
		if(*Volt >= 3.3)
			*Volt = 3.3;
	}
	
	if(Key_Scan(B4_Minus_GPIO_Port,B4_Minus_Pin) == 2)
	{
		*Volt -= 0.3;
		if(*Volt <= 0)
			*Volt = 0;
	}
}

3. 按键控制指示灯序号改变(配合扫描函数使用)

void Key_LD_Change(uint16_t *LD)
{
	if (Key_Scan(B3_Plus_GPIO_Port,B3_Plus_Pin) == 2)
	{
		*LD += 1;
		if(*LD >= 8)
			*LD = 8;
	}
	
	if(Key_Scan(B4_Minus_GPIO_Port,B4_Minus_Pin) == 2)
	{
		*LD -= 1;
		if(*LD <= 1)
			*LD = 1;
	}
}

4. 读取ADC数值(启动->读取->返回)

double Get_ADC(void)
{
	HAL_ADC_Start(&hadc2);						//启动ADC2
	adc = HAL_ADC_GetValue(&hadc2);		//定义变量adc,用于获取ADC2的值
	
	return (adc*3.3/4096);						//函数返回值为adc*3.3/4096,3.3V为最大电压值,4096为12位的LSB
}

5. 上限报警

void LD_Upper_Warning(uint8_t Upper)
{
	GPIOC -> ODR = ~(0x0001 << (Upper + 7));
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_RESET);
	
	HAL_Delay(200);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_RESET);
}

6. 下限报警

void LD_Lower_Warning(uint8_t Lower)
{
	GPIOC -> ODR = ~(0x0001 << (Lower + 7));
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_RESET);
	
	HAL_Delay(200);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_RESET);
}

7. 正常工作情况

void LD_Normal()
{
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(LD_Control_GPIO_Port,LD_Control_Pin,GPIO_PIN_RESET);
}

8. 数据显示界面

if(KEYB1_FLAG == 0)
		{
			LCD_SetBackColor(Blue);
			LCD_SetTextColor(White);
			LCD_DisplayStringLine(Line0,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line1,(uint8_t*)"       Main         ");
			LCD_DisplayStringLine(Line2,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line3,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line4,(uint8_t*)"  Volt:             ");
			LCD_DisplayStringLine(Line5,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line6,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line7,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line8,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line9,(uint8_t*)"                    ");
			
			V = Get_ADC();
			sprintf(ADC_TEXT,"  Volt:%.2fV        ",V);
			LCD_DisplayStringLine(Line4,(uint8_t*)ADC_TEXT);
			
			if( V >= Max_Volt)
			{
				LCD_DisplayStringLine(Line6,(uint8_t*)"  Status:Upper      ");
				LD_Upper_Warning();
			}
			if( V < Max_Volt && V > Min_Volt)
			{
				LCD_DisplayStringLine(Line6,(uint8_t*)"  Status:Normal     ");
				LD_Normal();
			}
			if( V <= Min_Volt)
			{
				LCD_DisplayStringLine(Line6,(uint8_t*)"  Status:Lower      ");
				LD_Lower_Warning();
			}
			if(Key_Scan(B1_Setting_GPIO_Port,B1_Setting_Pin) ==2)
			{
				KEYB1_FLAG += 1;
			}
		}

9. 参数设置界面

else
		{
			if(Key_Scan(B2_Selection_GPIO_Port,B2_Selection_Pin) == 2)
				KEYB2_FLAG += 1;
			if(KEYB2_FLAG > 4)
				KEYB2_FLAG = 0;
			LCD_SetBackColor(White);
			LCD_SetTextColor(Blue);
			LCD_DisplayStringLine(Line0,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line1,(uint8_t*)"      Setting       ");
			LCD_DisplayStringLine(Line2,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line5,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line8,(uint8_t*)"                    ");
			LCD_DisplayStringLine(Line9,(uint8_t*)"                    ");
			sprintf(LCD_TEXT,"  Max Volt:%.2fV       ",Max_Volt);
			if(KEYB2_FLAG == 1)
			{
				LCD_SetBackColor(Green);
				LCD_DisplayStringLine(Line3,(uint8_t*)LCD_TEXT);
				LCD_SetBackColor(White);
				
				Key_Volt_Change(&Max_Volt);
			}
			else
				LCD_DisplayStringLine(Line3,(uint8_t*)LCD_TEXT);
			
			sprintf(LCD_TEXT,"  Min Volt:%.2fV       ",Min_Volt);
			if(KEYB2_FLAG == 2)
			{
				LCD_SetBackColor(Green);
				LCD_DisplayStringLine(Line4,(uint8_t*)LCD_TEXT);
				LCD_SetBackColor(White);
				
				Key_Volt_Change(&Min_Volt);
			}
			else
				LCD_DisplayStringLine(Line4,(uint8_t*)LCD_TEXT);
			
			sprintf(LD_TEXT,"  Upper:LD%d            ",Upper);
			if(KEYB2_FLAG == 3)
			{
				LCD_SetBackColor(Green);
				LCD_DisplayStringLine(Line6,(uint8_t*)LD_TEXT);
				LCD_SetBackColor(White);
				
				Key_LD_Change(&Upper);
			}
			else
				LCD_DisplayStringLine(Line6,(uint8_t*)LD_TEXT);
			
			sprintf(LD_TEXT,"  Lower:LD%d            ",Lower);
			if(KEYB2_FLAG == 4)
			{
				LCD_SetBackColor(Green);
				LCD_DisplayStringLine(Line7,(uint8_t*)LD_TEXT);
				LCD_SetBackColor(White);
				
				Key_LD_Change(&Lower);
			}
			else
				LCD_DisplayStringLine(Line7,(uint8_t*)LD_TEXT);
			
			if(Key_Scan(B1_Setting_GPIO_Port,B1_Setting_Pin) ==2)
			{
				KEYB1_FLAG += 1;
			}
			
			if(Upper == Lower)
			{
				LCD_SetTextColor(Red);
				LCD_DisplayStringLine(Line5,(uint8_t*)"  LD Conflicted!    ");
			}
			else
				LCD_DisplayStringLine(Line5,(uint8_t*)"                    ");
		}

10. 界面切换

if(KEYB1_FLAG >1)
			KEYB1_FLAG = 0;

总结

通过上述代码基本可以实现任务的全部要求,但存在频繁闪烁的问题,我也不是很清楚是因为硬件原因还是软件原因,还望各路大佬指出!

如果需要全部代码可以直接私信我哈,文章已经很长啦,就不放全部代码啦!希望与各位小伙伴一同进步呀!

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DayDayUp..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值