STM32PWM--based on HAL library (the 11th Blue Bridge Cup Embedded Provincial Competition)


foreword

相关说明:

Development board: CT117E-M4 (STM32G431RB Blue Bridge Cup embedded competition board)
Development environment: CubeMX+Keil5
Involved topics: The 11th Blue Bridge Cup Embedded Provincial Competition
Difficulties: relatively easy, less difficult
(this project is written Modular programming is used, which is more conducive to code reading and understanding.)


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

1. CubeMX configuration (full version of the eleventh simulation question)

1. Enable external high-speed clock:insert image description here

2. Configure the clock tree:insert image description here

3.GPIO:

insert image description here

4.TIM3、TIM17(PWM):insert image description here
insert image description here

5.TIM6 (0.5s interrupt):insert image description here

6.ADC (get R37 voltage value):insert image description here

7.NVIC (enable TIM6 interrupt):insert image description here

2. Code-related definitions and declarations

1. Function declaration

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. Macro definition

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. Variable Definition

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};//重新配置后需要删除下面函数中的这个语句

Three, the main function

1. Button related

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. Data changes

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 update display

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. Mode change

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 status update

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 output

TIM_OC_InitTypeDef sConfigOC = {0}; This structure is defined as a global variable here. After MX is reconfigured, you need to delete this statement in the tim.c generation function.

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 function

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 */
}

4. Experimental results

5. Source code (reproduced, please indicate the source)

insert image description here


Summarize

The above is all the content, if there is any error, please criticize and correct.

Guess you like

Origin blog.csdn.net/Octopus1633/article/details/123622881