nRF51822 的兩路 PWM 極性

  忙了一陣這個PWM,玩着玩着終於發現了些規律。Nordic 也挺會坑爹的。app

  nRF51822 是沒有硬件 PWM 的,只能靠一系列難以理解的 PPI /GPIOTE/TIMER來實現,其實我想說,我醉了。函數

  幸虧SDK有這個的demo,否則真的很醉。這裏說的是SDK9.0.0。ui

  即使是有SDK,相信不少人都像我同樣,看下去會以爲暈頭轉向的,不過知道幾個函數的應用就能夠了。spa

  先記下怎麼開始用一個PWM。這裏我要用2路極性相反的PWM。code

先來初始化兩個個PWM實例,名字是PWM一、PWM2,用硬件Timer1/Timer2做爲基礎,千萬要切記Timer1/Timer2沒被佔用,而後記得打開Timer1/Timer2的宏。blog

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

而後初始化一個PWM。it

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 。這就是我想要說的重點。io

這個函數是能夠反覆使用以修改 PWM的頻率的,在再次使用時,先uninit它,以下:class

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));
}

就是這兩個怪事。記下來。

相關文章
相關標籤/搜索