STM32G431--基于HAL库(第十三届蓝桥杯嵌入式模拟题1)


前言

相关说明:

开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:第十三届蓝桥杯嵌入式模拟题1
题目难点:相对较易,主要需掌握调节PWM输出占空比及频率、ADC获取、以及定时器配置。


CubeMX配置、主要函数代码及说明:

一、CubeMX配置(第十三届模拟题完整版)

1.使能外部高速时钟:在这里插入图片描述

2.配置时钟树:在这里插入图片描述

3.GPIO:

在这里插入图片描述

4.ADC(检测R37电压值):在这里插入图片描述

5.TIM3(PWM):在这里插入图片描述

6.TIM6(0.1s中断):在这里插入图片描述

7.NVIC:在这里插入图片描述

二、代码相关定义、声明

1.函数声明

main.c
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//定时器回调函数
void D_change(void);	//D改变规则
void LCD_InitShow(void);//LCD初始化显示
void LCD_Refresh(void);	//LCD显示更新
void LED_change(void);	//LED2状态改变

gpio.h
void KEY_Scan(void);//按键扫描
void LED_AllClose(uint8_t *LED_Close);//LED更新显示

adc.h
double ADC_GetValue(void);//获取R37电压值

time.h
void PWN_OutPut(uint16_t Period,uint16_t Pulse);//配置PWM输出参数

2.宏定义

#define LED_GPIO_PORT GPIOC
#define LED1_GPIO_PIN GPIO_PIN_8
#define LED2_GPIO_PIN GPIO_PIN_9
#define LED3_GPIO_PIN GPIO_PIN_10
#define LED4_GPIO_PIN GPIO_PIN_11
#define LED5_GPIO_PIN GPIO_PIN_12
#define LED6_GPIO_PIN GPIO_PIN_13
#define LED7_GPIO_PIN GPIO_PIN_14
#define LED8_GPIO_PIN GPIO_PIN_15

#define ON 	GPIO_PIN_RESET
#define OFF	GPIO_PIN_SET

#define LED1(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED1_GPIO_PIN,a)
#define LED2(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED2_GPIO_PIN,a)
#define LED3(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED3_GPIO_PIN,a)
#define LED4(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED4_GPIO_PIN,a)
#define LED5(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED5_GPIO_PIN,a)
#define LED6(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED6_GPIO_PIN,a)
#define LED7(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED7_GPIO_PIN,a)
#define LED8(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED8_GPIO_PIN,a)

#define KEY1_GPIO_PORT GPIOB
#define KEY1_GPIO_PIN  GPIO_PIN_0
#define KEY2_GPIO_PORT GPIOB
#define KEY2_GPIO_PIN  GPIO_PIN_1
#define KEY3_GPIO_PORT GPIOB
#define KEY3_GPIO_PIN  GPIO_PIN_2
#define KEY4_GPIO_PORT GPIOA
#define KEY4_GPIO_PIN  GPIO_PIN_0

3.变量定义

main.c
double v_value;					//R37电压值
uint8_t D;						//占空比
uint16_t F=1000;				//PWM输出频率
uint16_t F_step=1000;			//F每次改变值
uint16_t F_max=10000;			//F上限
uint16_t F_min=1000;			//F下限
char str[30];					//用于组合字符串
uint8_t LCD_RefreshFlag=0;		//LCD更新标志位
uint8_t LED_Close[3]={
    
    1,1,0};	//LED关闭字符串(保存LED状态,值为1,则下标对应LED关闭)
uint8_t LED2_flag=0;			//LED2状态标志位 R37电压>1V时置1
uint32_t TIM_Clock=1000000;		//定时器6工作频率

tim.c
TIM_OC_InitTypeDef sConfigOC = {
    
    0};//配置该结构体为全局变量,MX配置后删除生成函数中的这句代码

三、主要函数

1.按键扫描

按键按下后的操作封装为函数,可降低函数耦合。

void KEY_Scan()
{
    
    
	static uint8_t clock=0;
	if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET && !clock)//++
	{
    
    
		HAL_Delay(10);
		if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET)
		{
    
    
			while(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET);
			Dat_change(add);
			LCD_Refresh();
		}
	}
	
	else if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET && !clock)//--
	{
    
    
		HAL_Delay(10);
		if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET)
		{
    
    
			while(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET);
			Dat_change(sub);
			LCD_Refresh();
		}
	}
	
	else if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET)
	{
    
    
		HAL_Delay(10);
		if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET)
		{
    
    
			while(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET);
			clock=!clock;
			LED_Close[1]=!LED_Close[1];
			LED_AllClose(LED_Close);
		}
	}
}

2.LED更新显示

将LED灯状态为灭还是亮,保存在LED_Close数组里,LCD就影响不了了,如果数组中值为1,则下标对应LED关闭,否则为开启,理解了逻辑很好写。具体可参考STM32LED–基于HAL库(第七届蓝桥杯嵌入式省赛)

void LED_AllClose(uint8_t *LED_Close)//LED更新显示
{
    
    
	uint8_t	i;
	LED1(ON);
	LED2(ON);
	for(i=1;i<3;i++)
	{
    
    
		if(LED_Close[i])
		{
    
    
			switch(i)
			{
    
    
				case 1:
					LED1(OFF);
					break;
				
				case 2:
					LED2(OFF);
					break;
			}
		}
	}
	LED3(OFF);
	LED4(OFF);
	LED5(OFF);
	LED6(OFF);
	LED7(OFF);
	LED8(OFF);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

3.PWM输出参数配置

PWM频率=定时器工作频率/重装载值
占空比=Pulse/重装载值*100%

void PWN_OutPut(uint16_t Period,uint16_t Pulse)//第一个参数为频率,第二个参数为占空比
{
    
    
	htim3.Init.Period = Period;//频率配置 PWM频率=定时器工作频率/重装载值
	sConfigOC.Pulse = Pulse;//占空比配置	占空比=Pulse/重装载值*100%
	HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//更改配置后需要重新Start才能生效
}

4.Main函数

int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

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

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC2_Init();
  MX_TIM3_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();//LCD初始化
	v_value=ADC_GetValue();//获取R37电压值
	D_change();//D值初始化
	LCD_InitShow();//LCD初始化显示
	LED_change();//LED状态改变
	TIM6->SR=0;//关闭定时器6中断标志位
	TIM6->CNT=0;//定时器6计数器清零
	HAL_TIM_Base_Start_IT(&htim6);//以中断方式开启定时器6
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//开启PWM
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		KEY_Scan();//按键扫描
		if(LCD_RefreshFlag>4)//每0.5s更新一次LCD以及PWM(更新频率可调节)
		{
    
    
			LCD_RefreshFlag=0;//LCD更新标志位清零
			v_value=ADC_GetValue();//重新获取R37电压值
			D_change();//D值更新
			LCD_Refresh();//LCD更新显示
			LED_change();//LED状态更新
			PWN_OutPut((TIM_Clock/F)-1,(D*1.0/100*TIM_Clock/F)-1);//PWM更新输出
		}
		LED_AllClose(LED_Close);//LED更新
  }
  /* USER CODE END 3 */
}

四、实验结果

1.初始状态

R37电压调节为1.5,对应D值为1.5/2*80=60;PWM初始频率1Khz
请添加图片描述

2.输出PWM

在这里插入图片描述

3.调节输出频率

在这里插入图片描述

4.输出PWM

在这里插入图片描述

五、源码(转载请注明出处)

在这里插入图片描述


总结

以上就是全部内容,如有错误请批评指正。

猜你喜欢

转载自blog.csdn.net/Octopus1633/article/details/123726256