忙了一阵这个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,);
APP_PWM_INSTANCE(PWM1,1);
然后初始化一个PWM。
void pwm_init(uint32_t freq)
{
static uint8_t flag=; 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[] = APP_PWM_POLARITY_ACTIVE_LOW;
else
pwm_cfg2.pin_polarity[] = 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, , );
app_pwm_channel_duty_set(&PWM2, , ); // 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));
}
就是这两个怪事。记下来。