概述
本章配置GD32F303输出PWM,同时使用TIM测量PWM频率和正占空比。 查阅手册可以得知,PB11为定时器1的通道3,让其输出PWM,PA6为定时器2的通道0,让作为TIM定时器输入。 需要GD样片的可以加群申请:615061293 。
生成例程这里准备了自己绘制的开发板进行验证。
管脚图如下所示。
keil配置microlib 进行了高度优化以使代码变得很小。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。 某些库函数的运行速度也比较慢,如果要使用printf(),必须开启。
使能串口 复制/* 使能GPI0A,用PA9、PA10为串口 */ rcu_periph_clock_enable(RCU_GPIOA); /*使能串口0的时钟 */ rcu_periph_clock_enable(RCU_USART0); /*配置USARTx_Tx(PA9)为复用推挽输出*/ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); /*配置USARTx_RxPA9)为浮空输入 */ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); /* USART 配置 */ usart_deinit(USART0);//重置串口0 usart_baudrate_set(USART0, 115200U);//设置串口0的波特率为115200 usart_word_length_set(USART0, USART_WL_8BIT); // 帧数据字长 usart_stop_bit_set(USART0, USART_STB_1BIT); // 停止位1位 usart_parity_config(USART0, USART_PM_NONE); // 无奇偶校验位 usart_receive_config(USART0, USART_RECEIVE_ENABLE);//使能接收器 usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);//使能发送器 usart_enable(USART0);//使能USART 串口重定向 复制/* retarget the C library printf function to the USART */ 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初始化 复制/*! rief configure the GPIO ports param[in] none param[out] none etval none */ void gpio_configuration(void) { rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_AF); /*configure PA6 (TIMER2 CH0) as alternate function*/ gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_6); //TIMER1-CH3 gpio_pin_remap_config(GPIO_TIMER1_PARTIAL_REMAP1, ENABLE); gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_11); } 开启中断 复制/*! rief configure the nested vectored interrupt controller param[in] none param[out] none etval none */ 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) { /* ———————————————————————– TIMER1 configuration: generate 3 PWM signals with 3 different duty cycles: TIMER1CLK = SystemCoreClock / 120 = 1MHz TIMER1 channel0 duty cycle = (4000/ 16000)* 100 = 25% TIMER1 channel1 duty cycle = (8000/ 16000)* 100 = 50% TIMER1 channel2 duty cycle = (12000/ 16000)* 100 = 75% ———————————————————————– */ 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 = 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); /* CH0,CH1 and CH2 configuration in PWM mode */ 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); /* CH3 configuration in PWM mode0,duty cycle 50% */ 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); /* auto-reload preload enable */ timer_auto_reload_shadow_enable(TIMER1); /* auto-reload preload enable */ timer_enable(TIMER1); } TIM2输入捕获设置 复制void timer2_config(void) { /* TIMER2 configuration: input capture mode ——————- the external signal is connected to TIMER2 CH0 pin (PB4) the rising edge is used as active edge the TIMER2 CH0CV is used to compute the frequency value ———————————————————— */ timer_ic_parameter_struct timer_icinitpara; timer_parameter_struct timer_initpara; //开启定时器时钟 rcu_periph_clock_enable(RCU_TIMER2); timer_deinit(TIMER2); /* TIMER2 configuration */ timer_initpara.prescaler = 120–1;//定时器的时钟频率是120MHz,预分频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); /* TIMER2 configuration */ /* TIMER2 CH0 input capture configuration */ 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); /* auto-reload preload enable */ timer_auto_reload_shadow_enable(TIMER2);//自动重载使能 /* clear channel 0 interrupt bit */ timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH0);//CH0 通道中断清除 /* channel 0 interrupt enable */ timer_interrupt_enable(TIMER2,TIMER_INT_CH0);//CH0 通道中断使能 /* TIMER2 counter enable */ 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)){ /* clear channel 0 interrupt bit */ 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(” time_frequency=%.2f,time_duty=%.2f”,time_frequency,time_duty*100) ; delay_1ms(1000); } 测试结果当输出1k频率,50%正占空比。
审核编辑:汤梓红
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:GD32F303固件库开发(13)—-定时器TIM捕获PWM测量频率与占空比-gpio定时器 https://www.yhzz.com.cn/a/5987.html