GD32F303固件库开发(13)----定时器TIM捕获PWM测量频率与占空比

发布者:JoyousJourney最新更新时间:2024-11-18 来源: elecfans关键字:GD32F303  固件库开发  定时器  TIM  捕获PWM  测量频率  占空比 手机看文章 扫描二维码
随时随地手机看文章

概述

本章配置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); // 计数清零,从头开始计

[1] [2]
关键字:GD32F303  固件库开发  定时器  TIM  捕获PWM  测量频率  占空比 引用地址:GD32F303固件库开发(13)----定时器TIM捕获PWM测量频率与占空比

上一篇:关于GD32F350R8的家庭环境智能控制系统的介绍和应用
下一篇:最后一页

推荐阅读最新更新时间:2024-11-18 10:36

stm32定时器(基本定时器)操作寄存器版
定时器本质 定时器的本质:计数器 定时器的构成:时钟源+计数器+重载值 1、stm32的定时器 stm32定时器数量较多、功能比较强;不同的定时器功能有不同。 stm32的定时器进行类型划分。分为三类:①基本定时器;②通用定时器;③高级定时器 基本定时器:用于定时器,还可以用于触发DAC(数模转换器)、ADC(模数转换器)工作。 通用定时器:具备基本定时器所有的功能;捕获输入、比较输出、捕获PWM波、生成PWM波、支持霍尔元件 高级定时器:具备通用定时器所有的功能:支持死区、刹车功能。 STM32F407的基本定时器有TIM6、TIM7. STM32F407的通用定时器有TIM2~TI
[单片机]
stm32<font color='red'>定时器</font>(基本<font color='red'>定时器</font>)操作寄存器版
stm32定时器主从模式
TIM2作master;TIM3,TIM4作slave 定时器2事件更新被用作触发输出TRGO 从定时器TIM3,TIM4工作在从模式:门控模式 触发选择设为:ITR1,这样TIM2的TRGO就连到了TIM3和TIM4的内部触发输入ITR1上,经过一系列选择器之后TIM2的TRGO就是TIM3和tim4的TRGI; 这样一来就可以通过控制TIM2的period和Pulse来控制TIM3和TIM4输出一定的脉冲个数;
[单片机]
stm32<font color='red'>定时器</font>主从模式
高压看门狗定时器提高车载系统安全性
汽车设计中,越来越多的电子系统正在逐步替代机械功能——从引擎定时控制到刹车、方向盘控制,而电子系统相对容易发生故障,这就需要谨慎考虑系统的安全性,确保系统具备较高的故障容限。不应该在发生单点故障时将司机或乘客至于危险处境,至少能够使汽车“跛行”到大路以外或最近的维修站。当电子设备发生故障时,为确保汽车的安全行驶需要利用监控电路开启备份电路,安全地接管系统操作。 在纯机械系统的汽车时代,引擎依照机械方式产生的信号点燃空气燃料混合器。机械分配器则选择适当的火花塞,沿线传递信号。刹车系统则将作用在踏板上的压力通过刹车轴、刹车总泵、液压管传送到制动钳。离合器和油门只是简单地受控于连接在踏板上的一条钢缆。方向盘通过一个金属舵轮、转向轴、转向
[嵌入式]
51单片机的定时器与计数器
1.0 1.0.1定时器 (1)51单片机的定时器是一个内部外设。 (2)定时器相当于CPU的一个“闹钟”。 (3)定时器是用计数器来实现的。 1.0.2计数器 (1)计数器可以计数外部脉冲的个数. (2)脉冲:(个人理解)单片机中一个低电平跳变成高电平在回到低电平的这么一个过程就称为一个脉冲。 1.0.3定时器是如何工作的 (1)第一步:先设置好定时器的时钟源(AT89C51单片机的时钟源只有一个不需要设置) (2)第二步:初始化时钟相关寄存器 (3)第三步:设置定时时间(计数个数) (4)第四步:设置中断处理程序(定时器总是与中断相互配合使用) (5)第五步:打开定时器 (6)第六步:定时器计数到后产生中断,然后执行中
[单片机]
分享关于stm32f407定时器时钟频率的问题
上午想要用Timer10做相对精确的延时功能,但是用示波器发现实际延时数值总是只有一半,百思不得其解。 仔细查阅各处资料结合实际研究后对stm32f407的14个定时器的时钟做一个总结: 从时钟树中我们可以得知(时钟树的图片可以直接参考6楼,感谢6楼xkwy补上的图): (1)高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11的时钟来源是APB2总线 (2)通用定时器timer2~timer5,通用定时器timer12~timer14以及基本定时器timer6,timer7的时钟来源是APB1总线 从STM32F4的内部时钟树可知,当APB1和APB2分频数为1的时候,TIM1、
[单片机]
单片机定时器0、1演示程序
//实验例程 大虾(DX-51)学习板 定时器0、1使用例程 #include reg52.h #include intrins.h //MCU51嵌入式专业仿真器占用3个字节程序空间0x003b,0x003c,0c003d, //使用code数组声明防止编译器将函数定位于此三字节所在程序空间上 unsigned char code DX58 _at_ 0x003b; unsigned char count; unsigned char direction; unsigned char delay1; unsigned char delay2; void timer0(void) interrupt 1 using 0 { T
[单片机]
51单片机定时器的应用以及计数初值的计算
#include reg51.h #define uchar unsigned char #define uint unsigned int sbit LED=P0^0; uchar t_count=0; int main(void) { TMOD=0x00; TH0=(8192-5000)/32; TL0=(8192-5000)%32; IE=0x82; TR0=1; while(1); } void LED_FLASH() interrupt 1 { TH0=(8192-5000)/32; TL0=(8192-5000)%32; if(++t_count==100) { LED=~
[单片机]
抗电磁干扰的PWM风扇控制器
  微芯科技(Microchip )公司提供一种工作于 PWM模式的风扇制冷速度控制器系列产品,用于无刷直流风扇(参考文献1)。为了利用PWM波形的占空比来控制风扇速度,可以使用外部 NTC(负温度系数)热敏电阻或微芯公司的一种PIC微控制器及其 SMBus 串行数据总线。图1示出了TC664 和 TC665 控制器数据资料描述的一种典型应用(参考文献2)。利用电容值为1mF的频率控制电容器CF和风扇控制器IC1产生一个PWM脉冲串,它的标称频率为30 Hz,依赖于温度或命令的占空比变化范围是30%~100%。   虽然使用PWM模式的控制器可以降低晶体管QA(它驱动风扇)的功耗,但 100 mA 方波电机驱动电流可能对附
[电源管理]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved