兆易GD32E508配置SHRTIM实现相位可调互补PWM带死区

简介

GD32E50X的SHRTIM与STM32的HRTIM工作原理高度相似,但是兆易官方只有从定时器发波的例子(批评),这里教大家使用主定时器来改变从定时器的起始相位的方式产生移相互补PWM(库函数配置方式)。

一、SHRTIM功能简介

SHRTIM 高分辨率时钟,在180MHz主频基础上64倍频,可以获得最高11.52GHz频率的PWM,用来产生1MHz方波可以获得11520的调整步长,隔壁STM32G4X4只有5440调整步长,或许GD32E50X就是用来对标STM32G4X4。
SHRTIM 拥有一个MASTER_TIMER和五个SLAVE_TIMER,结构框图如下:

二、库函数配置

1.SHRTIM.c配置

配置代码依次往下

GPIO配置:

	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);

    gpio_afio_port_config(AFIO_PA10_SHRTIMER_CFG, ENABLE);
    gpio_afio_port_config(AFIO_PA11_SHRTIMER_CFG, ENABLE);
	gpio_afio_port_config(AFIO_PB12_SHRTIMER_CFG, ENABLE);
	gpio_afio_port_config(AFIO_PB13_SHRTIMER_CFG, ENABLE);
    gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_10);
    gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_11);
	gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_12);
	gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_13);

SHRTIM结构体:

    shrtimer_baseinit_parameter_struct baseinit_para;
    shrtimer_timerinit_parameter_struct timerinit_para;
    shrtimer_timercfg_parameter_struct timercfg_para;
    shrtimer_comparecfg_parameter_struct comparecfg_para;
    shrtimer_channel_outputcfg_parameter_struct outcfg_para;
    shrtimer_deadtimecfg_parameter_struct deadtimecfg_para;     

SHRTIM配置:

    rcu_periph_clock_enable(RCU_SHRTIMER);
    rcu_shrtimer_clock_config(RCU_SHRTIMERSRC_CKSYS);
    
    shrtimer_dll_calibration_start(SHRTIMER0, SHRTIMER_CALIBRATION_ONCE);
    while(RESET == shrtimer_common_flag_get(SHRTIMER0, SHRTIMER_FLAG_DLLCAL));

    shrtimer_baseinit_struct_para_init(&baseinit_para);
    baseinit_para.period = 11520;
    baseinit_para.prescaler = SHRTIMER_PRESCALER_MUL64;
    baseinit_para.repetitioncounter = 0;
    baseinit_para.counter_mode = SHRTIMER_COUNTER_MODE_CONTINOUS;
    shrtimer_timers_base_init(SHRTIMER0, SHRTIMER_MASTER_TIMER, &baseinit_para);
    shrtimer_timers_base_init(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, &baseinit_para);
	shrtimer_timers_base_init(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, &baseinit_para);
	
	shrtimer_timerinit_struct_para_init(&timerinit_para);
    /*************MASTER_TIMER*************/
    timerinit_para.cnt_bunch = SHRTIMER_TIMERBUNCHNMODE_MAINTAINCLOCK;
    timerinit_para.dac_trigger = SHRTIMER_DAC_TRIGGER_NONE;
    timerinit_para.half_mode = SHRTIMER_HALFMODE_DISABLED;
    timerinit_para.repetition_update = SHRTIMER_UPDATEONREPETITION_DISABLED;
    timerinit_para.reset_sync = SHRTIMER_SYNCRESET_DISABLED;
    timerinit_para.shadow = SHRTIMER_SHADOW_DISABLED;
    timerinit_para.start_sync = SHRTIMER_SYNISTART_DISABLED;
    timerinit_para.update_selection = SHRTIMER_MT_ST_UPDATE_SELECTION_INDEPENDENT;
	shrtimer_timers_waveform_init(SHRTIMER0, SHRTIMER_MASTER_TIMER, &timerinit_para);
	
	/*************SLAVE_TIMER*************/
    timerinit_para.cnt_bunch = SHRTIMER_TIMERBUNCHNMODE_MAINTAINCLOCK;
    timerinit_para.dac_trigger = SHRTIMER_DAC_TRIGGER_NONE;
    timerinit_para.half_mode = SHRTIMER_HALFMODE_ENABLED; //互补模式使能
    timerinit_para.repetition_update = SHRTIMER_UPDATEONREPETITION_DISABLED;
    timerinit_para.reset_sync = SHRTIMER_SYNCRESET_DISABLED;
    timerinit_para.shadow = SHRTIMER_SHADOW_DISABLED;
    timerinit_para.start_sync = SHRTIMER_SYNISTART_DISABLED;
    timerinit_para.update_selection = SHRTIMER_MT_ST_UPDATE_SELECTION_INDEPENDENT;
    shrtimer_timers_waveform_init(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, &timerinit_para);
	shrtimer_timers_waveform_init(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, &timerinit_para);
	
	shrtimer_timercfg_struct_para_init(&timercfg_para);

    timercfg_para.balanced_mode = SHRTIMER_STXBALANCEDMODE_DISABLED;    
    timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_NONE;  
    timercfg_para.deadtime_enable = SHRTIMER_STXDEADTIME_DISABLED;
    timercfg_para.delayed_idle = SHRTIMER_STXDELAYED_IDLE_DISABLED;
    timercfg_para.fault_enable = SHRTIMER_STXFAULTENABLE_NONE;
    timercfg_para.fault_protect = SHRTIMER_STXFAULT_PROTECT_READWRITE;
    timercfg_para.reset_update = SHRTIMER_STXUPDATEONRESET_DISABLED;
    timercfg_para.update_source = SHRTIMER_STXUPDATETRIGGER_NONE;
    shrtimer_slavetimer_waveform_config(SHRTIMER0, SHRTIMER_MASTER_TIMER, &timercfg_para);

    timercfg_para.balanced_mode = SHRTIMER_STXBALANCEDMODE_DISABLED;    
    timercfg_para.deadtime_enable = SHRTIMER_STXDEADTIME_ENABLED; //死区使能
    timercfg_para.delayed_idle = SHRTIMER_STXDELAYED_IDLE_DISABLED;
    timercfg_para.fault_enable = SHRTIMER_STXFAULTENABLE_NONE;
    timercfg_para.fault_protect = SHRTIMER_STXFAULT_PROTECT_READWRITE;
    timercfg_para.reset_update = SHRTIMER_STXUPDATEONRESET_DISABLED;
    timercfg_para.update_source = SHRTIMER_STXUPDATETRIGGER_NONE;

    timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_MASTER_CMP0;  //这里设置从定时器起始计数点
    shrtimer_slavetimer_waveform_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, &timercfg_para);
  
    timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_MASTER_CMP1;  //这里设置从定时器起始计数点
	shrtimer_slavetimer_waveform_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, &timercfg_para);

    shrtimer_mastertimer_compare_value_config(SHRTIMER0, SHRTIMER_COMPARE0, 80);  // CMP0  
    shrtimer_mastertimer_compare_value_config(SHRTIMER0, SHRTIMER_COMPARE1, 80);  // CMP1
	/*************死区配置*************/
	shrtimer_deadtimercfg_struct_para_init(&deadtimecfg_para);
    deadtimecfg_para.fallingsign_protect = SHRTIMER_DEADTIME_FALLINGSIGN_PROTECT_DISABLE;
    deadtimecfg_para.falling_protect = SHRTIMER_DEADTIME_FALLING_PROTECT_DISABLE;
    deadtimecfg_para.falling_sign = SHRTIMER_DEADTIME_FALLINGSIGN_POSITIVE;
    deadtimecfg_para.falling_value = 0x0020;
    deadtimecfg_para.prescaler = SHRTIMER_DEADTIME_PRESCALER_MUL8;
    deadtimecfg_para.risingsign_protect = SHRTIMER_DEADTIME_RISINGSIGN_PROTECT_DISABLE;
    deadtimecfg_para.rising_protect = SHRTIMER_DEADTIME_RISING_PROTECT_DISABLE;
    deadtimecfg_para.rising_sign = SHRTIMER_DEADTIME_RISINGSIGN_POSITIVE;
    deadtimecfg_para.rising_value = 0x0020;
    shrtimer_slavetimer_deadtime_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, &deadtimecfg_para);
	shrtimer_slavetimer_deadtime_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, &deadtimecfg_para);
	
    /*************可以不定义*************/
    shrtimer_comparecfg_struct_para_init(&comparecfg_para);
    comparecfg_para.compare_value = 100;//设置SLAVE_TIMER1/2的PWM比较值,没有实质作用,可以不定义。
    shrtimer_slavetimer_waveform_compare_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, SHRTIMER_COMPARE0, &comparecfg_para);
    shrtimer_slavetimer_waveform_compare_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, SHRTIMER_COMPARE0, &comparecfg_para);
    /**************通道配置*************/
    shrtimer_channel_outputcfg_struct_para_init(&outcfg_para);
    outcfg_para.carrier_mode = SHRTIMER_CHANNEL_CARRIER_DISABLED;
    outcfg_para.deadtime_bunch = SHRTIMER_CHANNEL_BUNCH_ENTRY_REGULAR;
    outcfg_para.fault_state = SHRTIMER_CHANNEL_FAULTSTATE_NONE;
    outcfg_para.idle_bunch = SHRTIMER_CHANNEL_BUNCH_IDLE_DISABLE;
    outcfg_para.idle_state = SHRTIMER_CHANNEL_IDLESTATE_INACTIVE;
    outcfg_para.polarity = SHRTIMER_CHANNEL_POLARITY_HIGH;
    outcfg_para.reset_request = SHRTIMER_CHANNEL_RESET_PER;
    outcfg_para.set_request = SHRTIMER_CHANNEL_SET_CMP0;             
    shrtimer_slavetimer_waveform_channel_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, SHRTIMER_ST1_CH0, &outcfg_para);
    shrtimer_slavetimer_waveform_channel_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, SHRTIMER_ST1_CH1, &outcfg_para);

    shrtimer_channel_outputcfg_struct_para_init(&outcfg_para);
    outcfg_para.carrier_mode = SHRTIMER_CHANNEL_CARRIER_DISABLED;
    outcfg_para.deadtime_bunch = SHRTIMER_CHANNEL_BUNCH_ENTRY_REGULAR;
    outcfg_para.fault_state = SHRTIMER_CHANNEL_FAULTSTATE_NONE;
    outcfg_para.idle_bunch = SHRTIMER_CHANNEL_BUNCH_IDLE_DISABLE;
    outcfg_para.idle_state = SHRTIMER_CHANNEL_IDLESTATE_INACTIVE;
    outcfg_para.polarity = SHRTIMER_CHANNEL_POLARITY_HIGH;
    outcfg_para.reset_request = SHRTIMER_CHANNEL_RESET_PER;
    outcfg_para.set_request = SHRTIMER_CHANNEL_SET_CMP0;
	shrtimer_slavetimer_waveform_channel_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, SHRTIMER_ST2_CH0, &outcfg_para);
    shrtimer_slavetimer_waveform_channel_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, SHRTIMER_ST2_CH1, &outcfg_para);

    shrtimer_output_channel_enable(SHRTIMER0, SHRTIMER_ST1_CH0);//通道使能
    shrtimer_output_channel_enable(SHRTIMER0, SHRTIMER_ST1_CH1);
	shrtimer_output_channel_enable(SHRTIMER0, SHRTIMER_ST2_CH0);
    shrtimer_output_channel_enable(SHRTIMER0, SHRTIMER_ST2_CH1);
    
    shrtimer_timers_counter_enable(SHRTIMER0, SHRTIMER_MT_COUNTER);  //定时器计数使能
    shrtimer_timers_counter_enable(SHRTIMER0, SHRTIMER_ST1_COUNTER);
	shrtimer_timers_counter_enable(SHRTIMER0, SHRTIMER_ST2_COUNTER);

三、如何配置从定时器

如何配置从定时器来由主定时器控制起始计数点

1.从定时器配置

给出配置的结构体

typedef struct {
    uint32_t balanced_mode;                     /*!< specifies whether or not the balanced mode is enabled, refer to: set balanced mode */
    uint32_t fault_enable;                      /*!< specifies whether or not the fault channels are enabled for the Slave_TIMER, refer to: faut channel enabled for a Slave_TIMER*/
    uint32_t fault_protect ;                    /*!< specifies whether the write protection function is enable or not, refer to: protect fault enable */
    uint32_t deadtime_enable;                   /*!< specifies whether or not dead time insertion is enabled for the timer, refer to: dead time enable */
    uint32_t delayed_idle;                      /*!< the delayed IDLE mode, refer to: set delayed IDLE state mode */
    uint32_t update_source;                     /*!< the source triggering the Slave_TIMER registers update, refer to: update is done synchronously with any other Slave_TIMER or Master_TIMER update */
    uint32_t cnt_reset;                         /*!< the source triggering the Slave_TIMER counter reset, refer to: Slave_TIMER counter reset */
    uint32_t reset_update;                      /*!< specifies whether or not registers update is triggered when the timer counter is reset, refer to: update event generated by reset event */
}shrtimer_timercfg_parameter_struct;

主要是设置结构体中 cnt_reset 的值,该值可赋的值如下:

设置为 timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_MASTER_CMP0; 则Master的COMPARE0比较事件到来时,从定时器复位。

COMPARE0通过下面函数设置:
shrtimer_mastertimer_compare_value_config(SHRTIMER0, SHRTIMER_COMPARE0, 80);

如果用SHRTIMER_STXCNT_RESET_MASTER_PER,两个定时器相位同步。

配置代码例子如下:

    timercfg_para.balanced_mode = SHRTIMER_STXBALANCEDMODE_DISABLED;    
	timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_NONE;  
    timercfg_para.deadtime_enable = SHRTIMER_STXDEADTIME_DISABLED;
    timercfg_para.delayed_idle = SHRTIMER_STXDELAYED_IDLE_DISABLED;
    timercfg_para.fault_enable = SHRTIMER_STXFAULTENABLE_NONE;
    timercfg_para.fault_protect = SHRTIMER_STXFAULT_PROTECT_READWRITE;
    timercfg_para.reset_update = SHRTIMER_STXUPDATEONRESET_DISABLED;
    timercfg_para.update_source = SHRTIMER_STXUPDATETRIGGER_NONE;
    shrtimer_slavetimer_waveform_config(SHRTIMER0, SHRTIMER_MASTER_TIMER, &timercfg_para);
		
    timercfg_para.balanced_mode = SHRTIMER_STXBALANCEDMODE_DISABLED;    
    timercfg_para.deadtime_enable = SHRTIMER_STXDEADTIME_ENABLED;
    timercfg_para.delayed_idle = SHRTIMER_STXDELAYED_IDLE_DISABLED;
    timercfg_para.fault_enable = SHRTIMER_STXFAULTENABLE_NONE;
    timercfg_para.fault_protect = SHRTIMER_STXFAULT_PROTECT_READWRITE;
    timercfg_para.reset_update = SHRTIMER_STXUPDATEONRESET_DISABLED;
    timercfg_para.update_source = SHRTIMER_STXUPDATETRIGGER_NONE;
		
	timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_MASTER_CMP0;  
    shrtimer_slavetimer_waveform_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, &timercfg_para);
  
	timercfg_para.cnt_reset = SHRTIMER_STXCNT_RESET_MASTER_CMP1;  
	shrtimer_slavetimer_waveform_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER2, &timercfg_para);
		
	shrtimer_mastertimer_compare_value_config(SHRTIMER0, SHRTIMER_COMPARE0, 80);    
    shrtimer_mastertimer_compare_value_config(SHRTIMER0, SHRTIMER_COMPARE1, 80);

2.PWM通道配置

    shrtimer_channel_outputcfg_struct_para_init(&outcfg_para);
    outcfg_para.carrier_mode = SHRTIMER_CHANNEL_CARRIER_DISABLED;
    outcfg_para.deadtime_bunch = SHRTIMER_CHANNEL_BUNCH_ENTRY_REGULAR;
    outcfg_para.fault_state = SHRTIMER_CHANNEL_FAULTSTATE_NONE;
    outcfg_para.idle_bunch = SHRTIMER_CHANNEL_BUNCH_IDLE_DISABLE;
    outcfg_para.idle_state = SHRTIMER_CHANNEL_IDLESTATE_INACTIVE;
    outcfg_para.polarity = SHRTIMER_CHANNEL_POLARITY_HIGH;
    outcfg_para.reset_request = SHRTIMER_CHANNEL_RESET_PER;
    outcfg_para.set_request = SHRTIMER_CHANNEL_SET_CMP0;             
    shrtimer_slavetimer_waveform_channel_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, SHRTIMER_ST1_CH0, &outcfg_para);
    shrtimer_slavetimer_waveform_channel_config(SHRTIMER0, SHRTIMER_SLAVE_TIMER1, SHRTIMER_ST1_CH1, &outcfg_para);

主要利用以下两个结构体变量来设置互补PWM波形:
outcfg_para.reset_request = SHRTIMER_CHANNEL_RESET_PER;
outcfg_para.set_request = SHRTIMER_CHANNEL_SET_CMP0;
二者缺一不可!
该两值可以对调,结果是TIMER1与TIMER2同步时PWM相位初始相差180°。

3.功能展示

主函数如下:

int main(void)
{
  uint32_t i=80;
  systick_config();
  switch_system_clock_to_180m_hxtal();
  shrtimer_config();
    while(1)
		{
			i++;
			if(i>5700)
			i=80;
			delay_1ms(1.);
			shrtimer_mastertimer_compare_value_config(SHRTIMER0, SHRTIMER_COMPARE1, i);
		}

}

GD32 互补移相PWM

总结

本次进行了对GD32E508的SHRTIM波形产生的测试,证明该功能正常可用,SHRTIM功能确实很强大,可以利用该功能进行数控移相开关电源相关的开发。

物联沃分享整理
物联沃-IOTWORD物联网 » 兆易GD32E508配置SHRTIM实现相位可调互补PWM带死区

发表评论