前言
定时器(计数器)是单片机模块中一个比较重要的外设。利用其基本的计数、定时功能,我们可以作为较为精准的定时(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)
{
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配置
#define TFT_PORT GPIOB
#define TFT_BG_PIN GPIO_PIN_9
void GPIO_Init(void)
{
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
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 这个设定值。
void Timer3_Init(void)
{
timer_parameter_struct timer3_init;
timer_oc_parameter_struct timer3_ocintpara;
timer_deinit(TIMER3);
timer3_init.prescaler = 107;
timer3_init.alignedmode = TIMER_COUNTER_EDGE;
timer3_init.counterdirection = TIMER_COUNTER_UP;
timer3_init.period = 99;
timer3_init.clockdivision = TIMER_CKDIV_DIV1;
timer3_init.repetitioncounter = 0;
timer_init(TIMER3,&timer3_init);
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);
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);
timer_auto_reload_shadow_enable(TIMER3);
timer_enable(TIMER3);
}
三、主函数
- 配置好后,主函数不需要修改什么,用示波器检测对应IO的脚位即可。
int main(void)
{
SystemClock_Reconfig();
GPIO_Init();
Timer3_Init();
while(1)
{
}
}
timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_3,80);
|