STM32PWM--基于HAL库(第十一届蓝桥杯嵌入式省赛)


前言

相关说明:

开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:第十一届蓝桥杯嵌入式省赛
题目难点:相对容易,较少难点
(本次项目编写运用了模块化编程,更有利于代码阅读与理解。)


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

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

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

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

3.GPIO:

在这里插入图片描述

4.TIM3、TIM17(PWM):在这里插入图片描述
在这里插入图片描述

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

6.ADC(获取R37电压值):在这里插入图片描述

7.NVIC(使能TIM6中断):在这里插入图片描述

二、代码相关定义、声明

1.函数声明

main.c
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim);//定时器中断函数
void LCD_Init_Show(void);		//LCD初始化界面
void LCD_Refresh(uint8_t page);	//LCD更新函数
void Data_change(uint8_t dat);	//数据改变函数
void LED_Refresh(void);			//LED更新函数
void Mode_Change(void);			//模式改变函数

tim.h
void PWM_OutPut(uint16_t PA6_pulse,uint16_t PA7_pulse);		//PWM输出配置

gpio.h
void KEY_Scan(void);					//按键扫描
void LED_AllClose(uint8_t *LED_close);	//LED关闭

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

2.宏定义

gpio.h
#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_PI   GPIO_PIN_0

main.h
#define PA6 1
#define PA7 2

3.变量定义

main.c
double v_value;					//R37的电压值
char *pwm_mode="AUTO";			//PWM占空比控制模式
uint8_t PA6_air=10;				//PA6输出PWM的占空比 (10即10%)
uint8_t PA7_air=10;				//PA7输出PWM的占空比
uint8_t air_step=10;			//占空比每次改变值
uint8_t air_max=90;				//最大占空比
uint8_t air_min=10;				//最小占空比
uint8_t page_now=1;				//LCD显示页(1为数据页/2为配置页)
uint8_t PWM_refresh_flag=0;		//PWM更新标志位(每0.5s更新一次)
uint8_t LED_close[3]={
    
    0,0,0};	//LED关闭数组(为1则下标对应LED关闭)
char str[30];					//组合字符串

tim.c
TIM_OC_InitTypeDef sConfigOC = {
    
    0};//重新配置后需要删除下面函数中的这个语句

三、主要函数

1.按键相关

key.c
/* KEY */
void Setting_Mode()//配置模式
{
    
    
	while(1)
	{
    
    
			if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET)
			{
    
    
				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);
					LCD_Refresh(1);//LCD更新显示
					break;//退出循环
				}
			}
	
		else if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET)//PA6++
		{
    
    
			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);
				Data_change(PA6);//PA6数据改变
				LCD_Refresh(2);//LCD更新显示
			}
		}
		
		else if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET)//PA7++
		{
    
    
			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);
				Data_change(PA7);//PA7数据改变
				LCD_Refresh(2);//LCD更新显示
			}
		}
		LED_Refresh();
	}
}

void KEY_Scan()//按键扫描
{
    
    
	if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET)
	{
    
    
		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);
			LCD_Refresh(2);
			Setting_Mode();
		}
	}
	
	else if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET)
	{
    
    
		HAL_Delay(10);
		if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET)
		{
    
    
			while(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET);
		  Mode_Change();
		}
	}
}

2.数据更改

main.c
void Data_change(uint8_t dat)//数据更改
{
    
    
	switch(dat)
	{
    
    
		case PA6:
			PA6_air+=air_step;
			if(PA6_air>air_max)
				PA6_air=air_min;
			break;
		
		case PA7:
			PA7_air+=air_step;
			if(PA7_air>air_max)
				PA7_air=air_min;
			break;
	}
}

3.LCD更新显示

main.c
void LCD_Refresh(uint8_t page)//LCD更新显示
{
    
    
	if(page==1)//数据界面
	{
    
    
		page_now=1;
		LED_close[2]=0;
		LCD_DisplayStringLine(Line0,(unsigned char*)"      Data          ");
		sprintf(str,"    V:%.2fV         ",v_value);
		LCD_DisplayStringLine(Line2,(unsigned char*)str);
		sprintf(str,"    Mode:%s         ",pwm_mode);
		LCD_DisplayStringLine(Line4,(unsigned char*)str);
	}
	else if(page==2)//参数界面
	{
    
    
		page_now=2;
		LED_close[2]=1;
		LCD_DisplayStringLine(Line0,(unsigned char*)"      Para          ");
		sprintf(str,"    PA6:%d%%        ",PA6_air);
		LCD_DisplayStringLine(Line2,(unsigned char*)str);
		sprintf(str,"    PA7:%d%%        ",PA7_air);
		LCD_DisplayStringLine(Line4,(unsigned char*)str);
	}
}

4.模式更改

main.c
void Mode_Change()//模式更改
{
    
    
	if(strcmp(pwm_mode,"AUTO")==0)
	{
    
    
		pwm_mode="MANU";
		LED_close[1]=1;
	}
	else 
	{
    
    
		pwm_mode="AUTO";
		LED_close[1]=0;
	}
}

5.LED状态更新

main.c
/* LED */
void LED_Refresh()//LCD状态更新
{
    
    
	LED_AllClose(LED_close); 
	if(strcmp(pwm_mode,"AUTO")==0)
	{
    
    
		LED1(ON);
	}
	
	if(page_now==1)
	{
    
    
		LED2(ON);
	}
}

6.PWM输出

TIM_OC_InitTypeDef sConfigOC = {0};这个结构体在这定义为全局变量,MX重新配置后需要删除tim.c生成函数中的这个语句。

tim.c
void PWM_OutPut(uint16_t	PA6_pulse,uint16_t	PA7_pulse)//PWM输出函数
{
    
    
	sConfigOC.Pulse=PA6_pulse;
	HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) ;
	HAL_TIM_PWM_Init(&htim3);
	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
	
	sConfigOC.Pulse=PA7_pulse;
	HAL_TIM_PWM_ConfigChannel(&htim17, &sConfigOC, TIM_CHANNEL_1) ;
	HAL_TIM_PWM_Init(&htim17);
	HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
}

7.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_TIM17_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
	LCD_Init();//LCD初始化
	TIM6->SR=0;//定时器更新标志位清零
	TIM6->CNT=0;//定时器计数值清零
	HAL_TIM_Base_Start_IT(&htim6);//定时器开始计时
	v_value=ADC_GetValue();//获取ADC的值
	PWM_OutPut(v_value/3.3*(9999+1),v_value/3.3*(4999+1));//初始为AUTO模式
	LCD_Init_Show();//LCD初始化显示
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
		KEY_Scan();//按键扫描
		v_value=ADC_GetValue();//获取ADC的值
		LCD_Refresh(1);//LCD更新显示
		LED_Refresh();//LED更新显示
		if(PWM_refresh_flag==1)//每0.5S更新一次PWM
		{
    
    
			PWM_refresh_flag=0;
			if(strcmp(pwm_mode,"AUTO")==0)//如果为AUTO模式
			{
    
    
				PWM_OutPut(v_value/3.3*(9999+1),v_value/3.3*(4999+1));
			}
			else //如果为Menu模式
			{
    
    
				PWM_OutPut(PA6_air*1.0/100*(9999+1),PA7_air*1.0/100*(4999+1));
			}
		}
		HAL_Delay(50);//LCD更新延时,减少冲突
  }
  /* USER CODE END 3 */
}

四、实验结果

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

在这里插入图片描述


总结

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

猜你喜欢

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