特别说明:本文章需要使用过此pwm模块才会看明白,小白还是先去看看NRF52832芯片的pwm模块,如何再来看如何输出互补pwm。
初步使用NRF52832芯片的pwm模块,因为模块不能直接输出互补pwm,实现思路是用中央对齐方式去实现。
互补pwm有啥用,哈哈哈,旱的旱死,****
先看看pwm的一些工作模式:
要先理解这几种模式的特点
1-共用模式:4个通道共用极性,比较值,意思就是说4路pwm的方向一样,占空比一样
2-分组模式:2个通道分组共用一个极性和比较值,和共用模式类似,只是分成了2分
3-独立加载模式:每个通道极性独立,比较值独立,就是说可以随意改变占空比,和输出方向
4-波形模式:这个模式下只能使用前3个通道,后一个通道RAM用做计数值,也就是计数周期,即频率。(后面会用到这个)
------------------------
使用过这个芯片的pwm模块的看到这应该不陌生。
下面再说一下pwm模块的计数方式,这个也是实现互补的关键
1-向上计数 :计数器从0 - count
2-向下计数 :计数器从count -0
3-中心对齐计数,先向上计数,如何向下计数,所以整个周期会变成长,即频率会变成其它两种的一半,(要实现双边死区,需要使用这一种)
直接看代码吧:
#include <stdio.h>
#include <string.h>
#include "nrf_drv_pwm.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "boards.h"
//#include "bsp.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
// This is for tracking PWM instances being used, so we can unintialize only
// the relevant ones when switching from one demo to another.
#define USED_PWM(idx) (1UL << idx)
static uint8_t m_used = 0;
static uint16_t /*const*/ seq_values[] =
{
0<<15|1500,
1<<15|1000,
0<<15|1000,
2000
};
nrf_pwm_sequence_t seq =
{
.values.p_common = seq_values,//要回放的序列
.length = NRF_PWM_VALUES_LENGTH(seq_values),//长度
.repeats = 0,//重复次数为0
.end_delay = 0//结束的时候是否需要增加附带周期
};
static nrf_drv_pwm_config_t config0 =
{
.output_pins =
{
BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED, // channel 1
NRF_DRV_PWM_PIN_NOT_USED, // channel 2
NRF_DRV_PWM_PIN_NOT_USED, // channel 3
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,
.base_clock = NRF_PWM_CLK_16MHz,// 16MHz
.count_mode = PWM_MODE_UPDOWN_UpAndDown,//计数模式 中心对齐
.top_value = 2500,//计数器定点值,决定周期
.load_mode = NRF_PWM_LOAD_WAVE_FORM,//波形模式
.step_mode = NRF_PWM_STEP_AUTO//自动,重复次数后刷新
};
static void demo(void)
{
NRF_LOG_INFO("Demo");
APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));//初始化PWM
m_used |= USED_PWM(0);//使用PWM0模块
(void)nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
}
static int AARcount =200; //这个就是计数周期,即pwm频率
static void demo1(void)
{
char deal =10; //这里就是死区时间了
seq_values[0]=1<<15|AARcount/2; //通道0极性为1 ,比较值是计数值的一半,即占空比是50%
seq_values[1]=0<<15|AARcount/2+deal; //通道1极性为0
seq_values[3]=AARcount; //最大计算值
}
static void demo2(void)
{
seq_values[0]=1<<15|AARcount/2;
seq_values[1]=0<<15|AARcount/2+10;
seq_values[3]=AARcount;
}
//主函数,调用PWM输出。
int main(void)
{
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
NRF_LOG_INFO("PWM example started.");
demo();
for (;;)
{
//demo2();
nrf_delay_ms(2000);
demo1();
nrf_delay_ms(2000);
NRF_LOG_FLUSH();
}
}
/** @} */
这个代码是清风的例子改的,基本思路就是使用中央对齐,然后两个通道极性输出相反即可实现互补pwm,关键只要理解前面提到的pwm模块的两个特点即可。
实际波形如下,可以看到高低变化的时候有明显的死区,可以自行软件调节死区大小。