【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛

文章目录

  • 前言
  • 一、题目
  • 二、模块初始化以及功能分析
    • 1.模块的初始化
    • 2.模块功能分析
  • 三、函数实现
      • 1.void Display(void);
      • 2.uint8_t KEY_Scan(uint8_t mode);
      • 3.void KEY_Handle(uint8_t key);
      • 4.uint16_t Get_ADC(void);
      • 5.void LED(uint8_t Bit);
      • 6.int main(void);
        • 初始化;
        • while(1);
      • 7.void SysTick_Handler(void);
      • 针对3.KEY_Handle遗留的问题;
  • 总结


前言

为了减少篇幅,各模块的初始化均在模块配置中,可以随时去翻看博客,还有function里面的函数,将不再罗列出来,只是截图展示。

一、题目

【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第1张图片
【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第2张图片
【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第3张图片
【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第4张图片

【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第5张图片
【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第6张图片

二、模块初始化以及功能分析

1.模块的初始化

需要用的模块:LCD、四个按键、LED、ADC(PB15)

2.模块功能分析

LCD:显示-----》Display();
按键:对参数进行调整-----》KEY_Handle();KEY_Scan();
LED:提示作用-----》LED();
ADC: 采集电压值-----》Get_ADC();

三、函数实现

1.void Display(void);

mode表示页面显示的两种状态
location表示设置某个参数,被选定为红色
Status表示电压状态

void Display(void)
{
	if(mode == 0)
	{
		LCD_DisplayStringLine(Line1,"        Main      ");
		
		sprintf((char *)str,"  Volt: %.2fV",Volt);
		LCD_DisplayStringLine(Line4,str);
		
		if(Status == 0)
			LCD_DisplayStringLine(Line6,"  Status: Normal ");
		else if(Status == 1)
			LCD_DisplayStringLine(Line6,"  Status: Upper ");
		else if(Status == 2)
			LCD_DisplayStringLine(Line6,"  Status: Lower ");
	}
	else if(mode == 1)
	{
		LCD_DisplayStringLine(Line1,"     Setting    ");
		
		if(Location == 0)	LCD_SetTextColor(Red);
		sprintf((char *)str,"  Max Volt: %.2fV",Volt_Range[0]);
		LCD_DisplayStringLine(Line2,str);
		LCD_SetTextColor(Black);
		
		if(Location == 1)	LCD_SetTextColor(Red);
		sprintf((char *)str,"  Min Volt: %.2fV",Volt_Range[1]);
		LCD_DisplayStringLine(Line4,str);
		LCD_SetTextColor(Black);
		
		if(Location == 2)	LCD_SetTextColor(Red);
		sprintf((char *)str,"  Upper: LD%d",Range[0]);
		LCD_DisplayStringLine(Line6,str);
		LCD_SetTextColor(Black);
		
		if(Location == 3)	LCD_SetTextColor(Red);
		sprintf((char *)str,"  Lower: LD%d",Range[1]);
		LCD_DisplayStringLine(Line8,str);
		LCD_SetTextColor(Black);
	}
}

2.uint8_t KEY_Scan(uint8_t mode);

uint8_t KEY_Scan(uint8_t mode)
{
	static uint8_t flag=1;
	if(mode)	flag = 1;
	if(flag &&(KEY_B1 == 0 || KEY_B2 == 0 || KEY_B3 == 0 ||	KEY_B4== 0 ))
	{
		HAL_Delay(10);
		flag = 0;
		if (KEY_B1 == 0)	return B1_Press;
		else if (KEY_B2 == 0) return B2_Press;
		else if (KEY_B3 == 0) return B3_Press;
		else if (KEY_B4 == 0) return B4_Press;
	}else if(KEY_B1 == KEY_B2 == KEY_B3 == KEY_B4 == 1)	flag = 1;
	return 0;
}

3.void KEY_Handle(uint8_t key);

在B1按下时显示页面切换(mode变化)
在B2按下时切换参数选择的地址(location变化)
在B3按下时对应参数加0.3/1
在B4按下时对应参数减0.3/1
仍然存在一个问题:代码表示的下限加到离上限0.3就不会再加,但是实测出来是,下限加到3.3才不会向上加(若有解决方法记得评论),但是好像也不偏离题意。

void KEY_Handle(uint8_t key)
{
	if(key == B1_Press)
	{
		mode = !mode;
		LCD_Clear(White);
	}
	else if(key == B2_Press)
	{
		if(Location == 4)	Location = 0;
		else
		{
			Location++;
			Location = Location % 4;
		}
	}
	else if(key == B3_Press && mode == 1)
	{
		if(Location == 0)//控制电压范围
		{
			if(Volt_Range[0] < 3.3f)	Volt_Range[Location] = Volt_Range[Location] + 0.3f;
		}
		else if(Location == 1)//控制电压范围
		{
			if(Volt_Range[0] - Volt_Range[1] > 0.3f)	Volt_Range[Location] = Volt_Range[Location] + 0.3f;
		}
		else if(Location == 2)//控制指示灯范围
		{
			if(Range[1]-Range[0] > 1)	Range[Location-2] = Range[Location-2] + 1;
		}
		else if(Location == 3)//控制指示灯范围
		{
			if(Range[1] < 8)	Range[Location-2] = Range[Location-2] + 1;
		}
	}
	else if(key == B4_Press && mode == 1)
	{
		if(Location == 0)//控制电压范围
		{
			if(Volt_Range[0]-Volt_Range[1]> 0.3f)	Volt_Range[Location] = Volt_Range[Location] - 0.3f;
		}
		else if(Location == 1)//控制电压范围
		{
			if(Volt_Range[1] > 0)		Volt_Range[Location] = Volt_Range[Location] - 0.3f;
		}
		else if(Location == 2)//控制指示灯范围
		{
			if(Range[0] > 1)	Range[Location-2] = Range[Location-2] - 1;
		}
		else if(Location == 3)//控制指示灯范围
		{
			if(Range[1] - Range[0] > 1)	Range[Location-2] = Range[Location-2] - 1;
		}
	}
}

4.uint16_t Get_ADC(void);

读取电压值,电压值为Get_ADC()*3.3/4096;

uint16_t Get_ADC(void)
{
	uint16_t temp = 0 ;
	HAL_ADC_Start(&hadc2);
	temp = HAL_ADC_GetValue(&hadc2);
	HAL_ADC_Stop(&hadc2);
	
	return temp;

5.void LED(uint8_t Bit);

void LED(uint8_t Bit)//LD1,就是第8位,则输入时应该加7
{
	static uint8_t i;
	/*0000 0000 0000 0000为GPIOC的16个IO,从第8个到15个为LED灯LD1-LD8
	让第Bit位亮,则给Bit位低,其他7个为高。
	若Bit为8,则1111 1110 **** ****
	*/
	GPIOC->ODR |= (0xff<<8);//8个灯都置1
	i = !i;
	if(i)	GPIOC->ODR &= ~(0x1<< Bit);//第Bit位亮
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

6.int main(void);

初始化;

【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第7张图片

	LCD_Init();
	
	LCD_Clear(White);
	LCD_SetTextColor(Black);
	
	Volt_Range[0] = 2.4;
	Volt_Range[1] = 1.2;
	Range[0] = 1;
	Range[1] = 2;

while(1);

【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第8张图片

Display();
key = KEY_Scan(0);
KEY_Handle(key);
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
if(nCount == 1)		Volt = Get_ADC()*3.3/4096;
if(Volt > Volt_Range[0])//超过上限
{
	Over = 1;
	Status = 1;
}
else if(Volt < Volt_Range[1])//超过下限
{
	Over = 1;
	Status = 2;
}
else 
{
	Over = 0;
	Status = 0;
}

if(num == 1)
{ 
	num = 0;
	if(Volt > Volt_Range[0])//超过上限
		LED(Range[0] + 7);
	else if(Volt < Volt_Range[1])//超过下限                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
		LED(Range[1] + 7);
}
else 
{
	GPIOC->ODR |= (0xff<<8);//8个灯都置1
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

7.void SysTick_Handler(void);

上面的time和nCount在哪变了,在哪计时呢?
就在滴答定时器里面咯。
大家打开stm32g4xx_it.c
【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第9张图片

	if(Over == 1)
	{
		if(j++>=200)
		{
			j = 0;
			num = 1;
		}
	}
	if(i++ >= 1000)
	{
		i = 0;
		nCount = 1;
	}

针对3.KEY_Handle遗留的问题;

对于上面的问题,暂且有一个解决方法:
【STM32G4】备战蓝桥杯嵌入式---实战---第十届嵌入式省赛_第10张图片
此处用0.31f及以上,小于0.6f均可让下限至少比上限低0.3.


总结

以上就是本次赛题的程序设计部分(变量定义部分,本人没有罗列出来嗷),在代码简洁方面本人做的不是很好,如有更好的设计方法可以在评论区留言。互相学习。

还等什么,赶快自己写一下,测试一下代码。本人亲测有效、嘿嘿

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