GD32F303调试小记(八)之定时器出PWM(基本功能)

前言

定时器(计数器)是单片机模块中一个比较重要的外设。利用其基本的计数、定时功能,我们可以作为较为精准的定时(1ms、5ms的定时);又或者根据计数功能,在多个相同周期内翻转某个IO的电平,就形成了我们所说的PWM波形。

PWM

即脉宽调制技术,若你之前未接触过PWM,你可以理解为就是调整高低电平时间的长短。假定我们以10ms为一个轮询,每前3ms给一个IO输出高电平,后7ms置为低电平,不难想象我们最终会输出一个什么样的方波。其中10ms就是我们所说的周期,与之互为倒数的就是频率,也就是100Hz。高电平占整个周期的大小为正占空比,低电平占整个周期的大小为负占空比。了解到以上几点,对PWM我们算是有基本的认识了。

  • 对于一般的Buck、Boost以及Buck-Boost电路中控制输出PWM可实现升降压控制。
  • 我们也可以利用PWM调节诸如灯这类的亮灭与明暗程度,如调节屏背光、呼吸灯这一类。
  • 在驱动H桥电机控制、亦或是推挽输出电路中一般根据实际电路设计,会输出多路PWM。它们之间可能是互补的、可能是错相的,考虑到开关管的实际开关断时间,还需要插入一定的死区时间。
  • 在逆变电路中,则需要在每个周期内调整占空比,对于这种应用,也叫SPWM。
  • 以上是对PWM周期相对固定的应用场所,当然也有调整频率的,也就是变频技术。在数字电路中,其本质还是PWM控制。

各模块程序编写

在配置前,请确保你已经有一个GD32F303包含其对应标准库的keil工程,工程可使用官方的例程或可按照GD32F303调试小记(零)之工程创建与编译创建。

一、定时器模块简介

请添加图片描述
请添加图片描述
请添加图片描述
以上摘自官方手册,简单来说。高级定时器的功能最全,通用定时器与基本定时器都是在此基础上做的功能删减。各位可以根据实际需要使用具体的定时器。这里只给出只给出基本输出PWM的示例,更详细的例程可参考官方例程

二、初始化配置

1. 时钟配置

void SystemClock_Reconfig(void)
{
    
    
	/* Enable all peripherals clocks you need*/
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	
	rcu_periph_clock_enable(RCU_TIMER3);
}

2. 输出IO配置

请添加图片描述

// TFT port and pins definition
#define TFT_PORT							GPIOB
#define TFT_BG_PIN						GPIO_PIN_9		//1:亮 		 0:不亮	

void GPIO_Init(void)
{
    
    
	/* 使用SW下载,不使用JTAG下载,管脚用作其它功能 */
	gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
	
	/* LCD_BG使用Timer3_CH3 PWM输出控制亮度(10kHz) */
	gpio_init(TFT_PORT,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,TFT_BG_PIN);
}

3.定时器初始化

  • 下述配置分成两个部分:
  • timer3_init这个结构体用于配置定时器3的基本工作参数。我配置成108分频(我的主频工作在108MHz)、100的计数值、分频后定时器内的时钟源不再分频以及工作在边缘向上计数模式。这样算下来,定时器3的时钟源频率为1MHz。而计数到100则变成了10kHz。最终我们的定时器3会以10kHz的频率重新装载我们的值,并产生一次中断(如果你配置了)。
  • timer3_ocintpara这个结构体则是配置输出的模式。我配置成计数输出通道开、互补通道关、输出极性为高、空闲输出为低、最后配置具体的输出通道为TIMER3_CH3。
  • 最后将其工作在PWM0模式,关闭输出比较功能。再打开整个定时器的自动重装载值。注意timer_channel_output_pulse_value_config()函数第三个参数设定的值不要超过timer3_init.period 这个设定值。
/* Timer3_CH3 PWM输出 */
void Timer3_Init(void)
{
    
    
	timer_parameter_struct timer3_init;
	timer_oc_parameter_struct timer3_ocintpara;
	
	timer_deinit(TIMER3);
	
	/* TIMER3 configuration */
	timer3_init.prescaler         = 107;
	timer3_init.alignedmode       = TIMER_COUNTER_EDGE;
	timer3_init.counterdirection  = TIMER_COUNTER_UP;
	timer3_init.period            = 99;							//10kHz
	timer3_init.clockdivision     = TIMER_CKDIV_DIV1;
	timer3_init.repetitioncounter = 0;
	timer_init(TIMER3,&timer3_init);
	
	/* CH3 configuration in PWM mode */
	timer3_ocintpara.outputstate  = TIMER_CCX_ENABLE;
	timer3_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
	timer3_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
	timer3_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
	timer3_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
	timer3_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

	timer_channel_output_config(TIMER3,TIMER_CH_3,&timer3_ocintpara);
	
	/* CH3 configuration in PWM mode0,duty cycle 30% */
	timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_3,30);
	timer_channel_output_mode_config(TIMER3,TIMER_CH_3,TIMER_OC_MODE_PWM0);
	timer_channel_output_shadow_config(TIMER3,TIMER_CH_3,TIMER_OC_SHADOW_DISABLE);
	
	/* auto-reload preload enable */
	timer_auto_reload_shadow_enable(TIMER3);
	/* enable TIMER3 */
	timer_enable(TIMER3);
}

三、主函数

  • 配置好后,主函数不需要修改什么,用示波器检测对应IO的脚位即可。
int main(void)
{
    
    	
	SystemClock_Reconfig();	
	GPIO_Init();
	Timer3_Init();
	
	while(1)
	{
    
    
	
	}
}
  • 想修改输出的PWM值时,调用下述即可:
timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_3,80);

猜你喜欢

转载自blog.csdn.net/qq_37554315/article/details/124569677