GD32F303固件库开发.13----定时器TIM捕获PWM测量频率与占空比
概述
本章配置GD32F303输出PWM,同时使用TIM测量PWM频率和正占空比。 查阅手册可以得知,PB11为定时器1的通道3,让其输出PWM,PA6为定时器2的通道0,让作为TIM定时器输入。 需要GD样片的可以加群申请:615061293 。
视频教学
https://www.bilibili.com/video/BV1tg411m7pb/
GD32F303固件库开发(13)----定时器TIM捕获PWM测量频率与占空比
csdn课程
课程更加详细。 https://download.csdn.net/course/detail/37144
生成例程
这里准备了自己绘制的开发板进行验证。 管脚图如下所示。
keil配置
microlib 进行了高度优化以使代码变得很小。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。 某些库函数的运行速度也比较慢,如果要使用printf(),必须开启。
使能串口
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_USART0);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200U);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
串口重定向
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
return ch;
}
串口重定向后就可以使用printf进行打印。
占空比与频率计算
占空比=(t1-t0)/(t2-t0) 频率=(t2-t0)/时钟频率= =(t2-t0)/(120M/(psc+1))
周期需要2个上升沿去判断,设定第一个上升沿time_flag由0->1,下降沿time_dowm_flag由0->1,此时就知道正占空比时间,当在产生上升沿时候,就可以计算出周期使用的时间。
GPIO初始化
void gpio_configuration(void)
{
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_6);
gpio_pin_remap_config(GPIO_TIMER1_PARTIAL_REMAP1, ENABLE);
gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_11);
}
开启中断
void nvic_configuration(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(TIMER2_IRQn, 1, 1);
}
TIM1输出PWM初始化
PWM频率计算如下所示。
void timer1_config(void)
{
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER1);
timer_deinit(TIMER1);
timer_initpara.prescaler = 119;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 1000;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1,&timer_initpara);
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER1,TIMER_CH_3,&timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_3,500);
timer_channel_output_mode_config(TIMER1,TIMER_CH_3,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1,TIMER_CH_3,TIMER_OC_SHADOW_DISABLE);
timer_auto_reload_shadow_enable(TIMER1);
timer_enable(TIMER1);
}
TIM2输入捕获设置
void timer2_config(void)
{
timer_ic_parameter_struct timer_icinitpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER2);
timer_deinit(TIMER2);
timer_initpara.prescaler = 120-1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 65535;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING;
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
timer_icinitpara.icfilter = 0x0;
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
timer_auto_reload_shadow_enable(TIMER2);
timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH0);
timer_interrupt_enable(TIMER2,TIMER_INT_CH0);
timer_enable(TIMER2);
}
中断
#define IR_IN1 gpio_input_bit_get (GPIOA, GPIO_PIN_6)
uint8_t time_up_flag=0;
uint8_t time_dowm_flag=0;
uint32_t time_up_num=0;
uint32_t time_dowm_num=0;
float time_frequency;
float time_duty;
void TIMER2_IRQHandler(void)
{
timer_ic_parameter_struct timer_icinitpara;
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
timer_icinitpara.icfilter = 0x0;
if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_FLAG_CH0)){
timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH0);
if(IR_IN1&&time_up_flag==0)
{
time_up_flag=1;
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING;
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
timer_counter_value_config(TIMER2 , 0);
}
else if(IR_IN1==0&&time_dowm_flag==0)
{
time_dowm_num = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0)+1;
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING;
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
time_dowm_flag=1;
}
else if(IR_IN1&&time_dowm_flag==1)
{
time_up_num = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0)+1;;
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING;
timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
time_dowm_flag=0;
timer_counter_value_config(TIMER2 , 0);
}
}
初始化
gpio_configuration();
nvic_configuration();
timer1_config();
timer2_config();
主程序
while (1)
{
time_frequency=1000000/time_up_num;
time_duty = (float)time_dowm_num/(float)time_up_num;
printf("\ntime_frequency=%.2f,time_duty=%.2f",time_frequency,time_duty*100) ;
delay_1ms(1000);
}
测试结果
当输出1k频率,50%正占空比。
|