M-Arch(番外11)GD32L233评测-PWM驱动有源蜂鸣器

前言

架构做得好,高产似母猪。

接口改一改,效果就出来。

开工第二天,花半个小时搞定pwm驱动有源蜂鸣器。

有源蜂鸣器

有源蜂鸣器,其内部包含震荡源,通电就可以响;

对于有源蜂鸣器而言,可通过PWM的高低电平控制蜂鸣器的蜂鸣频率,高电平响,低电平不响。

至于为什么用PWM口来驱动,是为了在设计上能够兼容无源蜂鸣器。

手头有一个网上淘来的有源蜂鸣器,长这样:

47c763aba23ef65fb59e4b2ca696e897.png
SFM-27-I

驱动代码

基本原理:通过调整PWM的宽度来控制蜂鸣器响的周期。

GD32L233的开发板并没有把所有的IO口都引出来,对应我的设计中,只有PB5可用。

定时器初始化:

void timer3_init(void)
{
    timer_deinit(TIMER2);
    rcu_periph_clock_enable(RCU_TIMER2);
#ifdef DAC_WAVE_TEST
    timerx_init(TIMER2, 639, 9);  // 100KHz 0.1ms
#endif
#ifdef BUZZER_TEST
    timerx_init(TIMER2, 15999, 1999);  // 4KHz 500ms
#endif
    timer_interrupt_enable(TIMER2, TIMER_INT_UP);
    nvic_irq_enable(TIMER2_IRQn, 3);
}

PWM初始化:

void timer3_pwm_init(void)
{
#ifdef BUZZER_TEST
    timerx_PWM_init(TIMER2, TIMER_CH_1, RCU_GPIOB, GPIOB, GPIO_PIN_5, 0);
#endif
}

PWM改变占空比和周期接口:

void timer3_pwm_change(uint16_t period, uint16_t pulse)
{
    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_1, pulse);
    timer_autoreload_value_config(TIMER2, period);
    timer_event_software_generate(TIMER2, TIMER_EVENT_SRC_UPG);
}

前面弄DS1302吃了AF的亏,这次特意去手册里面查了下AF的值,坑不到我了,-_-

GD32L233的PWM没有啥互补功能,参数比较少,初始化比较简单,封装的内部接口也是改吧改吧就能用:

/******************************************************************************************/
/******************************************************************************************/
/******************************************************************************************/
/******************************************************************************************/
static void timerx_init(uint32_t TIMx, uint16_t prescaler, uint16_t period)
{
    timerx_init_full(TIMx, prescaler, period, TIMER_CKDIV_DIV1, TIMER_COUNTER_UP, 0);
}

static void timerx_init_full(uint32_t TIMx, uint16_t prescaler, uint16_t period, uint16_t clock_div, uint16_t counter_mode, uint8_t repetition_counter)
{
    timer_parameter_struct timer_initpara;
    timer_initpara.prescaler         = prescaler;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = counter_mode;
    timer_initpara.period            = period;
    timer_initpara.clockdivision     = clock_div;
    timer_init(TIMx, &timer_initpara);
    
    timer_update_event_enable(TIMx);
    timer_enable(TIMx);
}

static uint32_t get_alt_func_num(uint32_t TIMx)
{
    switch (TIMx)
    {
        case TIMER1:
        case TIMER2:
            return GPIO_AF_1;
        case LPTIMER:
        case TIMER8:
        case TIMER11:
            return GPIO_AF_2;
        default:
            return GPIO_AF_2;
    }
    return 0;
}

static void timerx_PWM_init(uint32_t TIMx, uint16_t TIMCHx, rcu_periph_enum rcu, uint32_t gpio, uint16_t pin, uint16_t pulse)
{
    timer_oc_parameter_struct timer_ocintpara;

    gpio_init_af_mode(rcu, gpio, pin, GPIO_OSPEED_2MHZ, get_alt_func_num(TIMx));

    timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_channel_output_config(TIMx, TIMCHx, &timer_ocintpara);
    timer_channel_output_pulse_value_config(TIMx, TIMCHx, pulse);
    timer_channel_output_mode_config(TIMx, TIMCHx, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMx, TIMCHx, TIMER_OC_SHADOW_DISABLE);

    timer_auto_reload_shadow_enable(TIMx);
    timer_enable(TIMx);
}

测试代码:

static void buzzer_test(void)
{
#ifdef BUZZER_TEST
    #define BUZZER_500ms    1999
    #define BUZZER_1000ms   3999
    #define BUZZER_2000ms   7999
    static uint8_t index = 0;
    index++;
    if (index == 2)
    {
        timer3_pwm_change(BUZZER_500ms, BUZZER_500ms/2);
    }
    else if (index == 4)
    {
        timer3_pwm_change(BUZZER_1000ms, BUZZER_1000ms/2);
    }
    else if (index == 6)
    {
        timer3_pwm_change(BUZZER_2000ms, BUZZER_2000ms/2);
    }
    else if (index == 8)
    {
        index = 0;
    }
#endif
}

测试结果

PWM波形:

44aa7c69cc3c5a4fcce7757bf27cd441.png
PWM波形
fa895070612c0a2b4485d5f705618372.gif 8938f78c68c03db5e4d3802104fb3c90.gif 35e1f06e93714052a8e0c016fb9f56ed.png c4b144391411c88e20cf523a467241b7.gif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值