嵌入式开发–STM32G431RBTx-产生pwm

定时器工作原理

image-20240306221155182

如图有反映stm32g431的定时器资源。

共10个定时器

定时器 定时器类型 个数
TIM6,7 基本定时器 2
TIM2,3,4 全功能通用定时器 3
TIM15,16,17 通用定时器(只有1或2个通道) 3
TIM1,8 高级控制定时器 2
image-20240320163019569
  • 当APB1/2分频系数为1时,给定时器的时钟为X1
  • 当APB1/2分频系数不为1时,给定时器时钟需X2

基本定时功能,当累加的时钟脉冲数超过预定值时,能触发中断或者触发DMA请求。

是专门用于驱动数模转换器(DAC)

基本定时器TIM16/17内部结构图

image-20240322155040869

配置定时器

设定TIM16定时器

image-20240322160539125

image-20240322160604694

设定系数

image-20240322160645847

第一个是分频系数(Prescaler)

第二个是周期计数值,按照分频后的时间进行计数(Counter Period)

80M的晶振除以8000,得到的工作频率为80 000 000/8 000=10 000

计算到ARR,就让ARR设置为100-1

此时可以得到一个频率为100hz的PWM波

image-20240322160715362

此处为占空比的设置,后续可以继续更改。

使用中断

image-20240320174839457

TIM17设置同上。

关于按键中断的实现

	struct keys key[4]={0,0,0};	

		if(htim->Instance==TIM3)
	{
		key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
    }

这段代码是一个中断回调函数,用于处理定时器 TIM3 的中断事件。代码中包含一个名为 key 的结构体数组,用于记录按键的状态。

在函数体中,首先通过读取 GPIO 引脚的状态,将按键的状态存储到 key 数组中的相应位置。其中,key[i].key_sta 表示第 i 个按键的状态。

接下来,使用一个循环遍历 key 数组的每个元素,对每个按键的状态进行判断和处理。

	for(int i=0;i<4;i++)
	{
		switch (key[i].judge_sta)
		{
			case 0:  //
			{
				if(key[i].key_sta==0) key[i].judge_sta=1;
			}
			break;
			case 1:
			{
				if(key[i].key_sta==0)
				{
					key[i].judge_sta=2;
					key[i].single_flag=1;
				}
				else key[i].judge_sta=0;
			}
			break;
			case 2:
			{
				if(key[i].key_sta==1)
				{
					key[i].judge_sta=0;						
				}
			}
			break;	
		}		
	}

switch 语句中,根据 key[i].judge_sta 的值来确定需要执行的操作。key[i].judge_sta 表示按键的判断状态。

key[i].judge_sta的值为 0 时,表示按键处于初始状态。

  • 如果按键的状态为按下(key[i].key_sta 等于 0),则将 key[i].judge_sta 的值设为 1,表示按键已按下。

key[i].judge_sta的值为 1 时,表示按键已按下。

  • 如果按键的状态仍然为按下,维持 key[i].judge_sta 的值为 1。
  • 如果按键的状态变为松开(key[i].key_sta 等于 1),则将 key[i].judge_sta 的值设为 2,表示按键已松开,并将 key[i].single_flag 的值设为 1,表示按键被单击。

key[i].judge_sta的值为 2 时,表示按键已松开。

  • 如果按键的状态变为按下,将 key[i].judge_sta 的值设为 0,表示按键已按下。

功能实现

一共有四个按键,按键0,按键1,按键2,按键3

按键 功能
按键0 LCD显示PA6,PA7的占空比
按键1 LCD显示PA6,PA7的占空比;PA6占空比加10
按键2 LCD显示PA6,PA7的占空比;PA7占空比加10
按键3 LCD显示PA6,PA7的占空比

添加如下配置

extern uint frq1,frq2;
extern float duty1,duty2;
uchar view=0;

uchar pa6_duty=10;
uchar pa7_duty=10;


	HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);//pwm输出开启
	HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//频率测量捕获定时器开启
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
    HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);//频率测量捕获定时器开启 间接通道
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
	
	__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);//设置初始pwm频率
	__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);


按键功能

void key_proc(void)
{

		
		if(key[1].single_flag==1)
		{
			pa6_duty+=10;
			if(pa6_duty>=100) pa6_duty=10;
			__HAL_TIM_SetCompare(&htim16,TIM_CHANNEL_1,pa6_duty);
			key[1].single_flag=0;
		}
		if(key[2].single_flag==1)
		{
			pa7_duty+=10;
			if(pa7_duty>=100) pa7_duty=10;
			__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty);
			key[2].single_flag=0;
		}
}	

void disp_proc(void)
{

		char text[30]; 
		sprintf(text,"      Para      ");
		LCD_DisplayStringLine(Line1, (uint8_t *)text);
		sprintf(text,"    PA6:%d      ",pa6_duty);
		LCD_DisplayStringLine(Line2, (uint8_t *)text);
		sprintf(text,"    PA7:%d      ",pa7_duty);
		LCD_DisplayStringLine(Line4, (uint8_t *)text);
		
		//清理界面残留
		sprintf(text,"                        ");
		LCD_DisplayStringLine(Line3, (uint8_t *)text);
		LCD_DisplayStringLine(Line5, (uint8_t *)text);

}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐