蓝牙芯片nRF52832之PWM的使用

本文介绍了nRF52832蓝牙芯片在SDK15中使用PWM的步骤,包括驱动配置、初始化、序列数据定义及影响PWM输出的因素。通过示例代码和波形分析,阐述了如何实现不同占空比的PWM输出,并讨论了COUNTERTOP限制及拓展策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nRF52832蓝牙芯片,自带了3路PWM硬件模块,每个模块支持4路,总共支持12路PWM。在SDK15中提供了简化的API,能够快速、便捷的实现PWM功能。以驱动LED灯为例,介绍一下nRF5283在SDK15中PWM的使用步骤以及注意的问题。

SDK15 PWM的使用步骤

1. SDK 驱动配置中enable PWM模块

图1

2. 初始化PWM实例

	#include "nrf_drv_pwm.h"
	static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);

3. 初始化配置

	nrf_drv_pwm_config_t const config0 =
	{
		.output_pins =
		{
			BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
			BSP_LED_2 | NRF_DRV_PWM_PIN_INVERTED, // channel 1
			BSP_LED_3 | NRF_DRV_PWM_PIN_INVERTED, // channel 2
			BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED // channel 3
		},
		.irq_priority = APP_IRQ_PRIORITY_LOWEST,
		.base_clock = NRF_PWM_CLK_125kHz,
		.count_mode = NRF_PWM_MODE_UP,
		.top_value = 15625,
		.load_mode = NRF_PWM_LOAD_INDIVIDUAL,
		.step_mode = NRF_PWM_STEP_AUTO
	};
	APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));

每路PWM硬件模块支持4个channel,nrf_drv_pwm_config_t中:

  • output_pins:映射PWM输出的pin脚号(spec上硬件的定义如P0.00,P0.01,00,01就是pin脚号,开发板中4个LED用的p0.17 - p0.20端口, 对应的pin脚号就是17-20);如果对应的通道没有硬件连接就使用NRF_DRV_PWM_PIN_NOT_USED。每个通道可以使用NRF_DRV_PWM_PIN_INVERTED来设置空闲引脚的电平为高电平,不使用时空闲引脚的电平为低电平
  • irq_priority:定义中断优先级,一般不使用;
  • base_clock定义PWM的时钟,从16M的clock分频而来,最高16MHZ,最低125kHz, 这个非常重要,每个clock多长时间来计算cycle持续多长时间;
  • count_mode:有两种,一种是NRF_PWM_MODE_UP和NRF_PWM_MODE_UP_AND_DOWN。NRF_PWM_MODE_UP边沿对齐,NRF_PWM_MODE_UP_AND_DOWN中心对齐。两者区别如图2和图3所示;
  • top_value:定义PWM的每个duty cycle中clock的最大个数;
  • load_mo
### NRF52832 芯片上的 PWM 配置 NRF52832 是 Nordic Semiconductor 推出的一款低功耗蓝牙 SoC,支持通过外设控制器实现脉宽调制(PWM)。以下是关于如何在该芯片上配置和使用 PWM 功能的详细介绍。 #### 1. 使用 Zephyr RTOS 实现 PWM 控制 Zephyr 提供了一个简单的 API 来控制 PWM 输出。可以通过设备树文件指定引脚并编写相应的驱动程序来启用 PWM 功能[^4]。 ##### 设备树中的 PWM 定义 在 `nrf52dk_nrf52832-pinctrl.dtsi` 文件中可以找到与 GPIO 引脚相关的别名定义。例如: ```dts aliases { pwm-led0 = &pwm_led0; }; ``` 这表明 `pwm-led0` 已经被绑定到了某个特定的引脚。如果需要自定义其他引脚作为 PWM 输出,则可以在自己的 DTS 中扩展这些定义。 ##### 示例代码:初始化 PWM 并生成信号 下面是一个基于 Zephyr 的简单示例,展示如何设置 PWM 输出以点亮 LED 或者调节亮度。 ```c #include <zephyr.h> #include <drivers/pwm.h> #define PWM_DEV_NAME DT_LABEL(DT_NODELABEL(pwm0)) // 替换为实际使用PWM 外设名称 #define PWM_PIN 28 // 替换为目标引脚编号 #define PWM_FLAGS 0 // 默认标志位 void main(void) { const struct device *pwm_dev; pwm_dev = device_get_binding(PWM_DEV_NAME); if (!pwm_dev) { printk("Could not get PWM device\n"); return; } int ret = pwm_pin_set_usec(pwm_dev, PWM_PIN, 1000, 750, PWM_FLAGS); // 设置周期为 1ms,占空比为 75% if (ret != 0) { printk("Failed to set PWM parameters on pin %u (%d)\n", PWM_PIN, ret); } else { printk("Successfully configured PWM output.\n"); } } ``` 上述代码片段展示了如何利用 Zephyr 的 `pwm_pin_set_usec()` 函数设定一个具有固定频率和占空比的方波输出。 --- #### 2. 手动操作寄存器的方式 如果不借助操作系统框架而直接访问硬件寄存器的话,那么就需要熟悉 NRF52 系列 MCU 的内部结构以及其对应的寄存器地址布局表。通常情况下,这种做法适用于更底层的应用场景或者调试阶段。 假设我们要激活 PPI(Peripheral-to-Peripheral Interconnect),并通过定时器触发 PWM 更新事件序列,具体步骤可能涉及以下几个方面: - 初始化 TIMERx 模块; - 将比较匹配中断连接至 EGUy 输入端口; - 构建任务链使得每次计数溢出会自动刷新下一个周期内的高低电平持续时间长度。 由于这种方法较为复杂且容易出错,因此推荐优先考虑采用高级抽象层接口完成开发目标。 --- ####
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值