IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> nRF52832的PWM实现呼吸灯、驱动无源蜂鸣器 -> 正文阅读

[嵌入式]nRF52832的PWM实现呼吸灯、驱动无源蜂鸣器

? ? ? ? 人生第一份工作的第一个项目,要用到nRF52832的PWM驱动一个无源蜂鸣器。

一、通用装载模式——呼吸灯

????????首先分析一下官方SDK给的PWM实现呼吸灯的demo,如下(省去了和呼吸灯无关的部分)。

//PWM驱动程序实例ID,ID和外设编号对应,0:PWM0 1:PWM1 2:PWM2
#define PWM_INSTANCE  0 

//定义名称为m_pwm0的PWM驱动程序实例,参数为0表示该实例对应的PWM外设为PWM0
static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(PWM_INSTANCE);

static uint16_t const              m_top  = 10000;
static uint16_t const              m_step = 100;

//定义PWM序列(通用装载模式),该序列必须位于RAM中,因此要定义为static类型的
uint16_t step  = m_top / m_step;
static nrf_pwm_values_common_t seq0_values[m_step*2];
uint16_t value = 0;

static void pwm_common_init(void)
{
		//设置PWM序列中各个周期的值:逐步修改占空比,实现呼吸灯效果
		for (uint8_t i = 0; i < m_step; ++i)
		{
				value         += step;
				seq0_values[i] = value;
				seq0_values[m_step+i] = m_top - value;
		}
		//定义PWM初始化配置结构体并初始化参数
    nrfx_pwm_config_t const config0 =
    {
        .output_pins =
        {
            BSP_LED_0 | NRFX_PWM_PIN_INVERTED, //通道0映射到P0.17(驱动开发板上的指示灯D1),空闲状态输出高电平
            BSP_LED_1 | NRFX_PWM_PIN_INVERTED, //通道1映射到P0.18(驱动开发板上的指示灯D2),空闲状态输出高电平
            BSP_LED_2 | NRFX_PWM_PIN_INVERTED, //通道2映射到P0.19(驱动开发板上的指示灯D3),空闲状态输出高电平
            NRFX_PWM_PIN_NOT_USED              //通道3不使用
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
        .base_clock   = NRF_PWM_CLK_1MHz,       //PWM时钟频率设置为1MHz  
        .count_mode   = NRF_PWM_MODE_UP,        //向上计数模式
        .top_value    = m_top,                  //计数最大值为10000
        .load_mode    = NRF_PWM_LOAD_COMMON,    //通用装载模式
        .step_mode    = NRF_PWM_STEP_AUTO       //序列中的周期自动推进
    };
		//初始化PWM
    APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
}

//播放PWM
static void pwm_play(void)
{
    //定义PWM播放序列,播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
	  nrf_pwm_sequence_t const seq0 =
    {
        .values.p_common = seq0_values,//指向PWM序列
        .length          = NRF_PWM_VALUES_LENGTH(seq0_values),//PWM序列中包含的周期个数
        .repeats         = 0, //序列中周期重复次数为0
        .end_delay       = 0  //序列后不插入延时
    };
    //启动PWM序列播放,flags设置为NRFX_PWM_FLAG_LOOP:序列播放完成后,自动触发任务重新播放
		//如改为NRFX_PWM_FLAG_STOP,则播放结束后,PWM停止
    (void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1,
                                       NRFX_PWM_FLAG_LOOP);
}

int main(void)
{
	//初始化开发板上的4个LED,即将驱动LED的GPIO配置为输出,
  bsp_board_init(BSP_INIT_LEDS);
	pwm_common_init();
	pwm_play();
	while(true)  
	{  
	}
}

????????实现的呼吸灯现象是:LED_0,LED_1,LED_2在1秒的时间里由暗到亮,再在1秒内由亮到暗,不断循环。具体每个变量和每一行是啥意思,SDK里都说得很清楚了,这里就不再赘述,但是有几个关键的变量:m_top = 10000 ; m_step = 100 ; step = m_top / m_step;seq0_values[m_step*2]?,没有解释清楚,让我这个初学者琢磨了好久。

? ? ? ? 先直接上结论:

????????①在初始化函数里找到.base_clock时钟频率为1MHz,那么周期T = m_top / 1M = 10000 / 1000000 = 0.01s = 10ms ,那么频率f自然就等于1 / T ,即这个m_top是用来决定PWM的周期和频率的。

? ? ? ? ②为了实现灯在1秒内的亮暗变化,令m_step = 100 ,从而100*10ms = 1s ,正好是一次由暗变亮或者一次由亮变暗的时间 ,即这个m_step决定了一次亮度的线性变化所花费的时间

? ? ? ? ③?seq0_values[m_step*2]?这个数组的各个数值,决定的是各个小周期(10ms)的占空比,m_step*2则表示一个大周期(也就是暗→亮→暗)总共包含了m_step*2 个小周期(也就是10ms*200=2s)。第n个小周期的占空比 P =(10000 - seq0_values[n]) / 10000 。

? ? ? ? ④step决定的是单次占空比的变化量。seq0_values数组的前100个数的数值每次都+100,也就是占空比每次都减少1%,100个数正好减到0%;seq0_values数组的后100个数的数值每次都-100,也就是占空比每次都增加1%,100次正好加到100%?。

? ? ? ? 把这些个变量搞明白之后,驱动无源蜂鸣器简直手到擒来,但通用装载模式驱动波形不变的无源蜂鸣器太麻烦,用波形装载模式更好理解。? ? ? ? ??

二、波形装载模式——无源蜂鸣器

????????先看立创商城里给出的蜂鸣器信息:

? ? ? ?

? ? ? ??咱唯一要看的就是“频率2700Hz”,所需要的周期长度T = 1/2700 ≈ 370μs = 0.00037s 。保持时钟频率依旧是1MHz不变,根据结论①,m_top (也就是下文seq0_values[ ]的第四个数)= 0.00037 * 10^6 = 370?。

#define BUZZER 23
#define PWM_INSTANCE_BUZZER  0 
static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(PWM_INSTANCE_BUZZER);

static nrf_pwm_values_wave_form_t seq0_values[] =
{
	37*8,    //通道0,占空比20%
	370,     //通道1,占空比0
	370,     //通道2,占空比0
	370      //最大比较值
};

static void pwm0_common_init(void)      //初始化
{
		//定义PWM初始化配置结构体并初始化参数
    nrfx_pwm_config_t const config0 =
    {
        .output_pins =
        {
			BUZZER | NRFX_PWM_PIN_INVERTED,      //通道0映射到蜂鸣器口23
			NRFX_PWM_PIN_NOT_USED,               //通道1未使用
            NRFX_PWM_PIN_NOT_USED,               //通道2未使用
			NRFX_PWM_PIN_NOT_USED                //通道3在波形装载模式下从不使用
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
        .base_clock   = NRF_PWM_CLK_1MHz,       //PWM时钟频率设置为1MHz  
        .count_mode   = NRF_PWM_MODE_UP,        //向上计数模式
        .top_value    = 0,                      //使用波形装载模式时,该值被忽略
        .load_mode    = NRF_PWM_LOAD_WAVE_FORM, //波形装载模式
        .step_mode    = NRF_PWM_STEP_AUTO       //序列中的周期自动推进
    };
		//初始化PWM
    APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
}

static void pwm0_play(void)       //播放
{
    //定义PWM播放序列,播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
	  nrf_pwm_sequence_t const seq0 =
    {
        .values.p_wave_form = seq0_values,//指向PWM序列
        .length             = NRF_PWM_VALUES_LENGTH(seq0_values),//PWM序列中包含的周期个数
        .repeats            = 0, //序列中周期重复次数为0
        .end_delay          = 0  //序列后不插入延时
    };
    //启动PWM序列播放,flags设置为NRFX_PWM_FLAG_LOOP:序列播放完成后,自动触发任务重新播放
		//如改为NRFX_PWM_FLAG_STOP,则播放结束后,PWM停止
    (void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1,
                                       NRFX_PWM_FLAG_LOOP);
}

????????seq0_values数组中的前三个数是用来决定占空比的,一一对应config0.output_pins中的前三个通道的占空比,第四个数370和呼吸灯demo里的m_top是一个意思,是决定周期的数值,所以第四个通道不开(就算开了估计占空比也是0,没意义)。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 11:01:01  更:2022-07-03 11:01:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:47:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码