nRF51822 的两路 PWM 极性

  忙了一阵这个PWM,玩着玩着终于发现了些规律。Nordic 也挺会坑爹的。

  nRF51822 是没有硬件 PWM 的,只能靠一系列难以理解的 PPI /GPIOTE/TIMER来实现,其实我想说,我醉了。

  幸好SDK有这个的demo,不然真的很醉。这里说的是SDK9.0.0。

  即便是有SDK,相信很多人都像我一样,看下去会觉得晕头转向的,不过知道几个函数的应用就可以了。

  先记下怎么开始用一个PWM。这里我要用2路极性相反的PWM。

先来初始化两个个PWM实例,名字是PWM1、PWM2,用硬件Timer1/Timer2作为基础,千万要切记Timer1/Timer2没被占用,然后记得打开Timer1/Timer2的宏。

#define TIMER1_ENABLED 1
#define TIMER2_ENABLED 1
APP_PWM_INSTANCE(PWM1,1);
APP_PWM_INSTANCE(PWM1,1);

然后初始化一个PWM。

void pwm_init(uint32_t freq)
{
    static uint8_t flag=0;
    
    uint32_t period_us = 1000000UL/freq;

     /* 2-channel PWM, 200Hz, output on DK LED pins. */
    app_pwm_config_t pwm_cfg = APP_PWM_DEFAULT_CONFIG_1CH(period_us, BEEF_PIN_E1);
    app_pwm_config_t pwm_cfg2 = APP_PWM_DEFAULT_CONFIG_1CH(period_us, BEEF_PIN_E2);

//    pwm_cfg2.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
    /* Switch the polarity of the second channel. */
//  pwm_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;
#if 1
    if(flag)
        pwm_cfg2.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;
    else
        pwm_cfg2.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
#endif

    flag = !flag;
    /* Initialize and enable PWM. */
    ret_code_t err_code;
    err_code = app_pwm_init(&PWM1,&pwm_cfg,pwm_ready_callback);
    APP_ERROR_CHECK(err_code); 
    err_code = app_pwm_init(&PWM2,&pwm_cfg2,pwm_ready_callback);
    APP_ERROR_CHECK(err_code); 

}

上面的代码你会注意到,我用了一个 flag 。这就是我想要说的重点。

这个函数是可以反复使用以修改 PWM的频率的,在再次使用时,先uninit它,如下:

void pwm_uninit(void)
{
    app_pwm_uninit(&PWM1);
    app_pwm_uninit(&PWM2);
}

我要说的重点是,第二次使用pwm_init()后然后enable_pwm,你就会发现这两路 的PWM的极性变成一样的了,所以我用一个flag,每次切换一下。解决了这个问题。

另外我发现修改占空比时,要等上一段时间才能修改完成,这点非常奇怪,懒得去追究原因了,所以才用了两个定时器来做这两路PWM。

void pwm_on(void)
{

    app_pwm_enable(&PWM1);
    app_pwm_enable(&PWM2);

    app_pwm_channel_duty_set(&PWM1, 0, 50);
    app_pwm_channel_duty_set(&PWM2, 0, 50);

//    ready_flag = false;
//    while (app_pwm_channel_duty_set(&PWM1, 0, 50) == NRF_ERROR_BUSY);
//    while(!ready_flag);
 //   APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, 50));
}

就是这两个怪事。记下来。

 

posted @ 2016-05-04 18:58  木棉城  阅读(2911)  评论(0编辑  收藏  举报