扩展:PWM波形输出捕获
这里写目录标题
- 一、简介
- 二、具体功能描述
- 1、时钟源的选择:
- 2、预分频器:
- 3、计数模式:
- 向上计数模式:
- 向下计数模式:
- 中央对齐模式:
- 4、捕获/比较通道
- 输入捕获模式
- 输出比较模式:
- 5、PWM模式
- 6、正交译码器
- 三、示例
一、简介
基本定时器和系统时钟配置可以参考我的上一篇文章,
文章链接为:
【GD32系列–基本定时器Timer + 定时1ms 灯光间隔1s闪烁例程】
【GD32】_时钟架构及系统时钟频率配置
下表为各定时器的差异,以通用定时器TIME1为例。
由上表可知通用定时器也分为四大类,黑圈代表具有此功能,x代表无此功能,一目了然。
由系统框图可知TIMER5 TIMER1 TIMER2 TIMER13均挂在APB1总线下
。
而TIMER0/TIMER14/15/16均挂在APB2总线
下。
由图可见APB1 和APB2的预分频系数均为2
,即: RCU_APB1_CKAHB_DIV2,即 PCLK1=36M。
本例程系统时钟为72MHZ,因此定时器的时钟源: CK_TIMER=36*2=72MHZ
TIMER1 and TIMER2是4通道定时器,
每个通道均可配置模式:输入捕获模式,输出比较模式,可编程的PWM模式,单脉冲模式
;
具有自动重装载功能。
时钟源有4种
:内部时钟,内部触发,外部输入,外部触发;
计数器宽度
:16位(TIMER2),32位(TIMER1);
二、具体功能描述
1、时钟源的选择:
通用定时器L0可以由内部时钟源TIMER_CK或者由SMC(TIMERx_SMCFG寄存器位[2:0])控制的复用时钟源驱动。
通用定时器L0可以由内部时钟源TIMER_CK驱动,若禁能禁能从模式(SMC[2:0]==3’b000),默认用来驱动计数器预分频器的是内部时钟源CK_TIMER。当CEN置位,CK_TIMER经过预分频器产生PSC_CLK。
也可以选择外部时钟模式。
2、预分频器:
预分频器可将定时器的时钟(TIMER_CK)频率按1到65536之间的任意值分频,分频后的时钟PSC_CLK
驱动计数器计数。分频系数受预分频寄存器TIMERx_PSC控制
,这个控制寄存器 带有缓冲器,它能够在运行时被改变。
3、计数模式:
有三种:向上计数、向下计数和中央计数
向上计数模式:
a、计数器从0向上计数到自动加载值(在TIMERx_CAR寄存器定义),一旦计数达到自动加载值,会重新从0开始向上计数并产生上溢事件。(此时TIMERx_CTL0寄存器中的计数方向控制位DIR应设置为0)
b、当通过TIMERx_SWEVG寄存器的UPG位置1来设置更新事件时,计数值会被清0,并产生新事件。(如果TIMERx_CTL0寄存器的UPDIS置1,则禁止更新事件。 )
c、当发生更新事件时,所有的寄存器(自动重载寄存器,预分频寄存器)都将被更新。
示例:,当TIMERx_CAR=0x63时,即自动加载值为0x63时,计数器在不同预分频因子下的状态。
向下计数模式:
a、计数器从自动加载值(在TIMERx_CAR寄存器定义)向下连续计数到0,一旦计数到0,计数器会重新从自动加载值开始计数并产生下溢事件。(此时TIMERx_CTL0寄存器中的计数方向控制位DIR应设置为1)
b、当通过TIMERx_SWEVG寄存器的UPG位置1来设置更新事件时,计数值会被初始化为自动加载值,并产生新事件。(如果TIMERx_CTL0寄存器的UPDIS置1,则禁止更新事件。 )
c、当发生更新事件时,所有的寄存器(自动重载寄存器,预分频寄存器)都将被更新。
示例:,当TIMERx_CAR=0x63时,即自动加载值为0x63时,计数器在不同预分频因子下的状态。
中央对齐模式:
a、在此模式下,计数器交替的从0开始向上计数到自动加载值,然后在向下计数到0。
(具体为: 向上计数模式中,在计数器技术到(自动加载值-1)时产生一个上溢事件;向下计数模式中,在计数器计数到1时产生一个下溢事件。)此时TIMERx_CTL0 寄存器中的计数方向控制位DIR只读,表明了的计数方向。计数方向被硬件自动更新。
b、将TIMERx_SWEVG寄存器的UPG位置1可以初始化计数值为0,并产生一个更新事件,而无需考虑计数器在中央模式下是向上计数还是向下计数。如果 TIMERx_CTL0 寄存器的 UPDIS 置 1,则禁止更新事件。
上溢或者下溢时,TIMERx_INTF 寄存器中的 UPIF 位都会被置 1,然而 CHxIF 位置 1 与
TIMERx_CTL0 寄存器中 CAM 的值有关。
c、当发生更新事件时,所有的寄存器(自动重载寄存器,预分频寄存器)都将被更新。
4、捕获/比较通道
通用定时器的基本计时功能与基本定时器的工作方式相同,都是把时钟源经过预分频器输出到脉冲计数器 TIMx_CNT 累加,溢出时就产生中断或 DMA 请求。通用定时器比基本定时器多出的功能,是因为通用定时器多出了一种寄存器——捕获 / 比较寄存器 TIMx_CCR(capture/compare register)
,它在输入时被用于捕获(存储) 输入脉冲在电平发生翻转时脉冲计数器 TIMx_CNT 的当前计数值,从而实现脉冲的频率测量 ;在输出时被用来存储一个脉冲数值,把这个数值用于与脉冲计数器TIMx_CNT 的当前计数值进行比较,根据比较结果进行不同的电平输出。
通用定时器L0有四个独立的通道用于捕获输入或比较输出是否匹配。
每个通道都围绕一个通 道捕获比较寄存器建立,包括一个输入级
,通道控制器
和输出级
。
输入捕获模式
捕获模式允许通道测量一个波形时序,频率,周期,占空比等。
输入级包括一个数字滤波器, 一个通道极性选择,边沿检测和一个通道预分频器。如果在输入引脚上出现被选择的边沿, TIMERx_CHxCV寄存器会捕获计数器当前的值,同时CHxIF位被置1,如果CHxIE = 1则产生 通道中断。
配置步骤:
a、滤波器配置 (TIMERx_CHxCAPFLT)
b、边沿选择(TIMERx_CHCTL2寄存器中CHxP/CHxNP)
c、捕获源选择(TIMERx_CHCTL0寄存器中CHxMS):
d、中断使能 (TIMERx_DMAINTEN寄存器中CHxIE和CHxDEN):
使能相应中断,可以获得中断和DMA请求
e、捕获使能 (TIMERx_CHCTL2寄存器中CHxEN)
结果:当期望的输入信号发生时,TIMERx_CHxCV被设置成当前计数器的值,CHxIF为置1。
如果CHxIF位已经为1,则CHxOF位置1。根据TIMERx_DMAINTEN寄存器中CHxIE和
CHxDEN的配置,相应的中断和DMA请求会被提出。
直接产生:软件设置CHxG位,会直接产生中断和DMA请求。
输入捕获模式也可用来测量TIMERx_CHx引脚上信号的脉冲波宽度。
输出比较模式:
在输出比较模式,TIMERx可以产生时控脉冲,其位置,极性,持续时间和频率都是可编程的。 当一个输出通道的CHxVAL
寄存器与计数器的值匹配时,根据CHxCOMCTL
的配置,这个通道 的输出可以被置高电平,被置低电平或者反转。
当计数器的值与CHxVAL寄存器的值匹配时, CHxIF位被置1,如果CHxIE = 1则会产生中断,如果CHxDEN=1则会产生DMA请求。
配置步骤如下:
a:时钟配置: 配置定时器时钟源,预分频器等。
b:比较模式配置:
设置CHxCOMSEN位来配置输出比较影子寄存器;
设置CHxCOMCTL位来配置输出模式(置高电平/置低电平/反转);
设置CHxP/CHxNP位来选择有效电平的极性;
设置CHxEN使能输出。
c:通过CHxIE/CHxDEN位配置中断/DMA请求使能。
d:通过TIMERx_CAR寄存器和TIMERx_CHxCV寄存器配置输出比较时基: CHxVAL可以在运行时根据你所期望的波形而改变。
e:设置CEN位使能定时器。
三种比较输出模式:反转/置高电平/置低电平,当设置:CAR=0x63, CHxVAL=0x3时。
5、PWM模式
根据计数模式,我们可以分为两种PWM波:EAPWM(边沿对齐PWM)
和CAPWM
(中央对齐
PWM)
在 PWM 输 出模 式 下 ( PWM 模 式 0
是配置 CHxCOMCTL 为3’b110, PWM 模 式 1
是配 置CHxCOMCTL为3’b111),通道根据TIMERx_CAR寄存器和TIMERx_CHxCV寄存器的值,输出PWM波形。
以PWM模式0、向上计数为例:定时器输出通道开始时是高电平,当计数器的值 > 输出比较寄存器的值时,输出通道变为低电平,直到计数器达到重装载寄存器的值,产生溢出并复位。
PWM模式1的电平和PWM模式0互补,向上计数和向下计数的区别是输出比较寄存器和重装载寄存器的比较方式是相反的。
中央对齐PWM的工作模式:当计数器的值小于输出比较寄存器的值时,通道输出为空闲电平;当计数器的值大于输出比较寄存器的值时,通道输出的是有效电平。
6、正交译码器
正交译码器功能使用由 TIMERx_CH0 和 TIMERx_CH1 引脚生成的 CI0 和 CI1 正交信号各自相互作用产生计数值。
在每个输入源改变期间,DIR 位被硬件自动改变。输入源可以是只有 CI0,可以只有 CI1,或着可以同时有 TI1 和 TI2,通过设置 SMC=0x01, 0x02 或 0x03 来选择使用哪种
模式。正交译码器可以当作一个带有方向选择的外部时钟,这意味着计数器会在 0 和自动加载值之间连续的计数。因此,必须在计数器开始计数前配置 TIMERx_CAR 寄存器。
计数器计数方向改变的机制如表 16-5. 计数方向与编码器信号之间的关系所示。
三、示例
目标任务:使用输出比较模式,得到不同的占空比,来控制灯的亮度。
void pwm_duty_cycle_led_config(void)
{
/* TIMER5 configuration: generate 1ms
SystemCoreClock =72MHZ
TIMER1CLK = SystemCoreClock / 72= 1MHz */
/* enable the GPTO clock */
rcu_periph_clock_enable( RCU GPIOA);
//设置定时器0为pwm输出功能
/*Configure PA15 (TIMER1 CHO) as alternate function*/
gpio_mode_set (GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15):
gpio_output_options_set (GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_15):
gpio_af_set (GPIOA, GPIO_AF_2, GPIO_PIN_15)
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara:
rcu_periph_clock_enable (RCU_TIMER1):
timer_deinit (TIMER1):
/*初始化定时器参数*/
/* TIMER1 configuration */
timer_initpara.prescaler = 71;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 15999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;//周期1MHA /(15999+1)=62.5HZ
timer_init(TIMER1, &timer_initpara);
/* CH1.CH2 and CH3 configuration in PWM mode1 */
timer_ocintpara.ocpolarity =TIMER_OC_POLARITY_HIGH:
timer_ocintpara.outputstate = TIMER_CCX_ENABLE:
tiner_channel_output_config (TIMER1, TIMER_CH_0, &timer_ocintpara):
timer_channel_output_pulse_value_config (TIMER1, TIMER CH_0, 3999):
timer_channel_output_mode_config (TIMERi, TIMER_CH_O, TIMER_OC_MODE_PWMO):
tiner_channel_output_shadow_config (TIMERI, TIMER_CH_O, TIMER OC_SHADOw DISABLE):
/* auto-reload preload enable */
timer_auto_reload_shadow_enable (TIMER1):
/* auto-reload preload enable */
timer_enable (TIMER1):
timer_primary_output_config (TIMER1, ENABLE) :
}
//很亮
void pwm_led_low(void)
{
timer_channel_output_pulse_value_config (TIMER1, TIMER_CH_0,8999) :
}
void pwm_led_high(void)
{
timer_channel_output_pulse_value_config (TIMER1,TIMER_CH_0,899):
}
unsigned char key (void)
{
unsigned char status = 0:
status = (unsigned char)((GPIO_ISTAT(GPIOB)>>3)&0x00000001):
return status;
}
void main(void)
{
pwm_duty_cycle_led_config();
while(1)
{
if(0==key())
{
pwm_led_high();
}
else
{
pwm_led_low();
}
}
}