硬件: NORDIC nRF 52840 SoC

软件: NORDIC nRF SDK Ver 15.2

功能:  nRF 52840 带3路PWM硬件模块,每个模块支持4通道,总共支持12路PWM通道



PWM Module 工程配置

于 sdk_config.h 文件 nRF_Drivers 配置中使能 PWM_ENABLED

于工程文件目录中添加  nrfx_pwm.c


软件编程实现

定义及初始化 PWM Module 实例

#include "nrf_drv_pwm.h"static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
static nrf_drv_pwm_t m_pwm1 = NRF_DRV_PWM_INSTANCE(1);
static nrf_drv_pwm_t m_pwm2 = NRF_DRV_PWM_INSTANCE(2);

PWM Module nrf_drv_pwm_config_t 参数设置

    nrf_drv_pwm_config_t const config0 ={.output_pins ={BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED, // channel 1BSP_LED_2 | NRF_DRV_PWM_PIN_INVERTED, // channel 2//    NRF_DRV_PWM_PIN_NOT_USED,       // NOT USEDBSP_LED_3 | NRF_DRV_PWM_PIN_INVERTED  // channel 3},.irq_priority = APP_IRQ_PRIORITY_LOWEST,.base_clock   = NRF_PWM_CLK_1MHz,.count_mode   = NRF_PWM_MODE_UP,.top_value    = 10000,.load_mode    = NRF_PWM_LOAD_INDIVIDUAL,.step_mode    = NRF_PWM_STEP_AUTO};nrf_drv_pwm_init(&m_pwm0, &config0, pwm0_handler);

脉冲发生计数器操作图示


PWM Module 模块加载 RAM 中的Multiple duty cycle array(sequences)并输出执行

count_mode 加载模式设置:
NRF_PWM_LOAD_COMMON: 4通道共用一个配置
NRF_PWM_LOAD_GROUPED: 1,2通道使用第一个值;3,4通道使用第二个值。
NRF_PWM_LOAD_INDIVIDUAL: 各通道完全独立,1通道对应第一个值,...,4通道对应第四个值。
NRF_PWM_LOAD_WAVE_FORM: 1,2,3独立,第四个值写入 top value

/*** @brief PWM decoder load modes.** The selected mode determines how the sequence data is read from RAM and* spread to the compare registers.*/
typedef enum
{NRF_PWM_LOAD_COMMON     = PWM_DECODER_LOAD_Common,     ///< 1st half word (16-bit) used in all PWM channels (0-3).NRF_PWM_LOAD_GROUPED    = PWM_DECODER_LOAD_Grouped,    ///< 1st half word (16-bit) used in channels 0 and 1; 2nd word in channels 2 and 3.NRF_PWM_LOAD_INDIVIDUAL = PWM_DECODER_LOAD_Individual, ///< 1st half word (16-bit) used in channel 0; 2nd in channel 1; 3rd in channel 2; 4th in channel 3.NRF_PWM_LOAD_WAVE_FORM  = PWM_DECODER_LOAD_WaveForm    ///< 1st half word (16-bit) used in channel 0; 2nd in channel 1; ... ; 4th as the top value for the pulse generator counter.
} nrf_pwm_dec_load_t;

PWM Module nrf_pwm_sequence_t 参数设置

基于 nrf_drv_pwm_config_t -> base_clock PWM 基准时钟,定义每个通道的占空比,不能超过 nrf_drv_pwm_config_t -> top_value。
如果四个通道均使用,则每个数组均有4个 PWM 周期数据,至少有一组数据,如{ 0x8000, 0, 0, 0 },通道1的 PWM 周期数是0x8000,通道2-4均为0。根据需要,也可使用不同的占空比来形成一个序列。

// --- load_mode: NRF_PWM_LOAD_INDIVIDUAL ---static nrf_pwm_values_individual_t /*const*/ seq_values[] ={{ 0x8000,      0,      0,      0 },{      0, 0x8000,      0,      0 },{      0,      0, 0x8000,      0 },{      0,      0,      0, 0x8000 }};nrf_pwm_sequence_t const seq ={.values.p_individual = seq_values,.length              = NRF_PWM_VALUES_LENGTH(seq_values),.repeats             = 0,.end_delay           = 0};// --- load_mode: NRF_PWM_LOAD_COMMON ---static nrf_pwm_values_common_t /*const*/ seq1_values[] ={0,0x8000,0,0x8000,0,0};nrf_pwm_sequence_t const seq1 ={.values.p_common = seq1_values,.length          = NRF_PWM_VALUES_LENGTH(seq1_values),.repeats         = 4,.end_delay       = 0};// --- load_mode: NRF_PWM_LOAD_GROUPED---static nrf_pwm_values_grouped_t /*const*/ pwm0_seq_values[] ={{      0,      0 },{ 0x8000,      0 },{      0, 0x8000 },{ 0x8000, 0x8000 }};nrf_pwm_sequence_t const pwm0_seq ={.values.p_grouped = pwm0_seq_values,.length           = NRF_PWM_VALUES_LENGTH(pwm0_seq_values),.repeats          = 1,.end_delay        = 0};

typedef struct
{nrf_pwm_values_t values; ///< Pointer to an array with duty cycle values. This array must be in Data RAM./**< This field is defined as an union of pointers*   to provide a convenient way to define duty*   cycle values in various loading modes*   (see @ref nrf_pwm_dec_load_t).*   In each value, the most significant bit (15)*   determines the polarity of the output and the*   others (14-0) compose the 15-bit value to be*   compared with the pulse generator counter. */uint16_t length;    ///< Number of 16-bit values in the array pointed by @p values.uint32_t repeats;   ///< Number of times that each duty cycle should be repeated (after being played once). Ignored in @ref NRF_PWM_STEP_TRIGGERED mode.uint32_t end_delay; ///< Additional time (in PWM periods) that the last duty cycle is to be kept after the sequence is played. Ignored in @ref NRF_PWM_STEP_TRIGGERED mode.
} nrf_pwm_sequence_t;

values:PWM Module 占空比数据
length:通过宏NRF_PWM_VALUES_LENGTH自动计算 PWM Module 数据长度
repeats:每个PWM 周期重复次数,注意是每个 PWM 周期!不是重复 sequece 时钟序列!
               如 PWM 数据是 { 0x8000, 0, 0, 0 }, { 0x4000, 0, 0, 0 },在repeats为 2 的情况下, PWM生效的数据为,
               channel 1 为: 0x8000,0x8000,0x4000,0x4000,第2-4通道均为: 0,0,0,0
end_delay: 每个sequence时钟序列中,最后一个PWM 周期重复的次数;
                  如: 通道1的PWM 周期数据为 {0x8000, 0},在end_delay为4的情况下,最后PWM的生效数据为:{0x8000, 0,0,0,0,0}


PWM 启动

(void)nrf_drv_pwm_simple_playback(&m_pwm0, &pwm0_seq, 1,NRF_DRV_PWM_FLAG_LOOP);
(void)nrf_drv_pwm_complex_playback(&m_pwm1, &pwm1_seq0, &pwm1_seq1, 1,NRF_DRV_PWM_FLAG_LOOP);
(void)nrf_drv_pwm_complex_playback(&m_pwm2, &pwm2_seq0, &pwm2_seq1, 1,NRF_DRV_PWM_FLAG_LOOP);//-----------------------------------------------
uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance,nrf_pwm_sequence_t const * p_sequence,uint16_t                   playback_count,uint32_t                   flags)
{
...
}

函数 nrf_drv_pwm_complex_playback() 来触发PWM,参数 p_instance 为 PWM Module 实例, 参数 p_sequence 为时钟序列数据 , playback_count为 PWM Module 执行次数,参数 flags可设两种值, NRF_DRV_PWM_FLAG_LOOP:永远重复,NRFX_PWM_FLAG_STOP: PWM 执行设定次数后结束.

还有一种函数模式,可定义两个参数 p_sequence !


3个 PWM Modulre,12 channels 通道 独立调节样例程序

#include <stdio.h>
#include <stdlib.h>
#include "nrf_drv_pwm.h"
#include "pca10056.h"
#include "nrf_log.h"// --- PWM Modulestatic nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
static nrf_drv_pwm_t m_pwm1 = NRF_DRV_PWM_INSTANCE(1);
static nrf_drv_pwm_t m_pwm2 = NRF_DRV_PWM_INSTANCE(2);static uint16_t const    m_PWM0_top_value  = 0x8000;
static uint16_t const   m_PWM1_top_value  = 0x8000;
static uint16_t const   m_PWM2_top_value  = 0x8000;static nrf_pwm_values_individual_t m_PWM0_seq_values;
static nrf_pwm_values_individual_t m_PWM1_seq_values;
static nrf_pwm_values_individual_t m_PWM2_seq_values;static nrf_pwm_sequence_t const    m_PWM0_seq =
{.values.p_individual = & m_PWM0_seq_values,.length              = NRF_PWM_VALUES_LENGTH( m_PWM0_seq_values),.repeats             = 0,.end_delay           = 0
};static nrf_pwm_sequence_t const    m_PWM1_seq =
{.values.p_individual = & m_PWM1_seq_values,.length              = NRF_PWM_VALUES_LENGTH( m_PWM1_seq_values),.repeats             = 0,.end_delay           = 0
};static nrf_pwm_sequence_t const    m_PWM2_seq =
{.values.p_individual = & m_PWM2_seq_values,.length              = NRF_PWM_VALUES_LENGTH( m_PWM2_seq_values),.repeats             = 0,.end_delay           = 0
};// 3 PWM Module, the value of 12 channels
uint16_t m_PWM_values[12] = {  0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000};static void PWM0_handler(nrf_drv_pwm_evt_type_t event_type)
{uint16_t * p_channels = (uint16_t *)& m_PWM0_seq_values;switch (event_type){case NRF_DRV_PWM_EVT_FINISHED:int i=0;for ( i=0;i<4;i++ ){p_channels[i] = m_PWM_values[i];}case NRFX_PWM_EVT_END_SEQ0:
//              NRF_LOG_INFO("-- PWM0 seq0 --");break;case NRFX_PWM_EVT_END_SEQ1:NRF_LOG_INFO("-- PWM0 seq1 --");break;case NRFX_PWM_EVT_STOPPED:NRF_LOG_INFO("-- PWM0 STOP --");break;default:break;}
}static void PWM1_handler(nrf_drv_pwm_evt_type_t event_type)
{uint16_t * p_channels = (uint16_t *)& m_PWM1_seq_values;switch (event_type){case NRF_DRV_PWM_EVT_FINISHED:int i=0;for ( i=0;i<4;i++ ){p_channels[i] = m_PWM_values[i+4];}case NRFX_PWM_EVT_END_SEQ0:
//              NRF_LOG_INFO("-- PWM1 seq0 --");break;case NRFX_PWM_EVT_END_SEQ1:NRF_LOG_INFO("-- PWM1 seq1 --");break;case NRFX_PWM_EVT_STOPPED:NRF_LOG_INFO("-- PWM1 STOP --");break;default:break;}
}static void PWM2_handler(nrf_drv_pwm_evt_type_t event_type)
{uint16_t * p_channels = (uint16_t *)& m_PWM2_seq_values;switch (event_type){case NRF_DRV_PWM_EVT_FINISHED:int i=0;for ( i=0;i<4;i++ ){p_channels[i] = m_PWM_values[i+8];}case NRFX_PWM_EVT_END_SEQ0:
//              NRF_LOG_INFO("-- PWM2 seq0 --");break;case NRFX_PWM_EVT_END_SEQ1:NRF_LOG_INFO("-- PWM2 seq1 --");break;case NRFX_PWM_EVT_STOPPED:NRF_LOG_INFO("-- PWM2 STOP --");break;default:break;}
}void PWM_init(void)
{nrf_drv_pwm_config_t const config0 ={.output_pins ={DO_CHANNEL_1 , // PWM0 CHANNEL-0DO_CHANNEL_2 , // PWM0 CHANNEL-1DO_CHANNEL_3 , // PWM0 CHANNEL-2DO_CHANNEL_4   // PWM0 CHANNEL-3},.irq_priority = APP_IRQ_PRIORITY_LOWEST,.base_clock   = NRF_PWM_CLK_2MHz,                        .count_mode   = NRF_PWM_MODE_UP,.top_value    = m_PWM0_top_value,.load_mode    = NRF_PWM_LOAD_INDIVIDUAL,.step_mode    = NRF_PWM_STEP_AUTO};nrf_drv_pwm_config_t const config1 ={.output_pins ={DO_CHANNEL_5 , // PWM1 CHANNEL-0DO_CHANNEL_6 , // PWM1 CHANNEL-1DO_CHANNEL_7 , // PWM1 CHANNEL-2DO_CHANNEL_8   // PWM1 CHANNEL-3},.irq_priority = APP_IRQ_PRIORITY_LOWEST,.base_clock   = NRF_PWM_CLK_2MHz,.count_mode   = NRF_PWM_MODE_UP,.top_value    = m_PWM1_top_value,.load_mode    = NRF_PWM_LOAD_INDIVIDUAL,.step_mode    = NRF_PWM_STEP_AUTO};     nrf_drv_pwm_config_t const config2 ={.output_pins ={DO_CHANNEL_9 , // PWM1 CHANNEL-0DO_CHANNEL_10 , // PWM1 CHANNEL-1DO_CHANNEL_11, // PWM1 CHANNEL-2DO_CHANNEL_12   // PWM1 CHANNEL-3},.irq_priority = APP_IRQ_PRIORITY_LOWEST,.base_clock   = NRF_PWM_CLK_2MHz,.count_mode   = NRF_PWM_MODE_UP,.top_value    = m_PWM2_top_value,.load_mode    = NRF_PWM_LOAD_INDIVIDUAL,.step_mode    = NRF_PWM_STEP_AUTO};   APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, PWM0_handler));APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm1, &config1, PWM1_handler));APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm2, &config2, PWM2_handler));m_PWM0_seq_values.channel_0 = 0x8000;m_PWM0_seq_values.channel_1 = 0x8000;m_PWM0_seq_values.channel_2 = 0x8000;m_PWM0_seq_values.channel_3 = 0x8000;m_PWM1_seq_values.channel_0 = 0x8000;m_PWM1_seq_values.channel_1 = 0x8000;m_PWM1_seq_values.channel_2 = 0x8000;m_PWM1_seq_values.channel_3 = 0x8000;m_PWM2_seq_values.channel_0 = 0x8000;m_PWM2_seq_values.channel_1 = 0x8000;m_PWM2_seq_values.channel_2 = 0x8000;m_PWM2_seq_values.channel_3 = 0x8000;(void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_PWM0_seq, 1,NRF_DRV_PWM_FLAG_LOOP);(void)nrf_drv_pwm_simple_playback(&m_pwm1, &m_PWM1_seq, 1,NRF_DRV_PWM_FLAG_LOOP);(void)nrf_drv_pwm_simple_playback(&m_pwm2, &m_PWM2_seq, 1,NRF_DRV_PWM_FLAG_LOOP);
}

NORDIC nRF52840 PWM Module 硬件功能实现相关推荐

  1. MCAL PWM Module详解

    关注"嵌入式软件实战派"公众号,回复"AUTOSAR"可获得AUTOSAR实战教程.​ 领导给一个小伙伴安排了个AUTOSAR配置任务:配置MCAL PWM调节 ...

  2. 网管光纤收发器产品硬件功能及网管收发器优点介绍

    飞畅科技生产研发的网管型光纤收发器具有非网管收发器的全部功能,各种速率,单模/多模,单纤/双纤.此设备的网管界面设置简单,功能全面.此系列网管收发器支持多种网管方式,包括SNMP,WEB和Consol ...

  3. SND0611支持PWM调光功能的线性恒流LED驱动芯片 完美代替SLM411A 用于在各种LED照明产品

    深力科电子SND0611支持PWM调光功能的线性恒流LED驱动芯片 完美代替SLM411A 用于在各种LED照明产品 SND0611 系列产品是用于产生单通道.高精度恒 流源的 LED 驱动芯片,在各 ...

  4. ABB机器人安全板硬件功能介绍+接线方法示例

    ABB机器人安全板硬件功能介绍+接线方法示例 ABB机器人有以下几种硬件停止功能,这些均属于EN 13849-1中描述的安全类别3,该安全类别是双通道发起的停止,如果发生单通道故障(例如接线不良),则 ...

  5. 板子测试基本硬件功能

    板子测试基本硬件功能 新板子生产出来的时候需要对基本功能进行测试,以确保硬件设计的正常 测试GPS/BD 测试命令和方法如下 DAPP:->:GPS-DEBUG-ONOFF:PRINTF=1,B ...

  6. 深力科SND111系列 带PWM调光功能的线性压降恒流LED驱动器, 内置过热保护代替数明SLM201A

    深力科SND111系列 带PWM调光功能的线性恒流LED驱动器, 内置过热保护代替数明SLM201A SND111系列用于产生单通道.高精度恒流 源的 LED 驱动芯片,在各种 LED 照明产品中非 ...

  7. H桥驱动电机,STM32 PWM互补输出功能误用分析

    如果排查的思路对你有帮助,请记住 消雨匆匆 or  大吊工. 码字和排查很累,仅此而已 硬件不是抄电路,拿烙铁,懂点软件,细致分析,找问题和破案搜集线索是一样的. 导航车设计项目中,一个新人设计了如下 ...

  8. 嵌入式实验(四):用STM32输出PWM波形/DAC功能完成波形输出

    0 实验目标 用STM32F103输出一路PWM波形,建议采用定时器方法.野火和网上大多数资源采用此方法,有完整源码.用示波器观察输出波形. 用STM32F103的DAC功能完成以下波形输出,用示波器 ...

  9. 用PWM实现DAC功能

    现在单片机型号很多,但是内部拥有12位DAC且性价比较高的芯片恨少,导致在芯片选型时,捉襟见肘.没办法,就想着用PWM实现DAC的功能,这只是初步理论,还没有实践过,先贴出来,后续实现再看效果如何吧. ...

最新文章

  1. mySql比较并获取当前时间x分钟之前的数据(时间是字符串类型)
  2. ActiveX组件及其注册 (轉)
  3. DCMTK:解压缩DICOM文件
  4. 微软准备开源PowerShell
  5. linux2.6 gcc 4.8.2,在Red Hat Enterprise linux 6.5上安装GCC 4.8.2
  6. 超30万字的中台实战100讲2.0最终版(建议收藏!)
  7. python pip install syntaxerror_解决pip install xxx报错SyntaxError: invalid syntax的问题
  8. 一文简介常见的机器学习算法
  9. 盘点那些适合写api接口的工具
  10. html+css+javascript实现抖音超火罗盘时钟 (免费附源码)
  11. JavaScript系列之while循环
  12. 读《期货市场计算机分析指南》笔记
  13. 只知道wxid怎么添加好友
  14. 什么是教养?不给人制造麻烦,就是最好的教养。
  15. 高中生参加的计算机奥赛是,高中生可参加哪些含金量较高的赛事?报名流程指南来了!...
  16. 【华为OD统一考试B卷 | 100分】按身高和体重排队(C++ Java JavaScript Python)
  17. 【深度学习】CNN 中 1x1 卷积核的作用
  18. 深入理解JVM(一)
  19. 编程小白学python路线图_零基础Python学习路线图,让你少走弯路
  20. 考研英语真题笔记 2020,Java数据结构面试题及答案

热门文章

  1. 怎么让图片放大不模糊?
  2. 拼多多继续ALL IN
  3. Ubuntu系统学习笔记(8)-常用Gedit编辑器快捷键
  4. 【WB32库开发】第9章 TIM1高级定时器——输出多路PWM
  5. python-cookie http.cookiejar用法
  6. JavaScript 09 - 函数
  7. WGAN (Wasserstein GAN)
  8. 元宇宙应用价值体现在哪些领域?
  9. 2020.7.25-参加海淀区科普节小学组数学测试 二等奖
  10. 如何将无限循环小数转化为分数