西河刘卡车医 发表于 2025-4-15 22:27:11

【物联网】PWM控制蜂鸣器

一、PWM介绍

PWM(Pulse Width Modulation) 简称脉宽调制,是使用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在测量、通讯、工控等方面。
https://i-blog.csdnimg.cn/direct/5f25a8fee42e4a328ee367d0f2e34593.png
1.PWM的频率

是指在1秒钟内, 信号从高电平到低电平再回到高电平的次数,也就是说一秒钟PWM有多少个周期,单位HZ。
2.PWM的周期

T=1/f,T是周期,f是频率。
如果频率为50Hz ,也就是说一个周期是20ms,那么一秒钟就有 50次PWM周期。
是一个脉冲周期内,高电平的时间与整个周期时间的比例(0%-100%)
二、PWM工作原理分析

占空比是高电平
计数器可以决定输出信号的频率,比较器可以决定占空比是多少
https://i-blog.csdnimg.cn/direct/5e5927fd17c945c489919e5712372407.png
三、I.MX6ull PWM介绍

脉宽调制(PWM)有一个16位计数器,经过优化,可以从存储的样本音频图像中天生声音,还可以天生音调。它使用16位分辨率和4 x 16数据FIFO。
https://i-blog.csdnimg.cn/direct/f88874b1c57c4da5b4c3d820a75e0d75.png
1.时钟信号

(1)High-frequency reference clock (ipg_clk_highfreq) pat_ref
(这是一个高频时钟,由时钟控制模块(CCM)提供。当ipg_clk关闭时,处于低功耗模式,该时钟应打开)
(2)Low-frequency reference clock (ipg_clk_32k, CKIL)
(这是CCM提供的32 KHz低参考时钟。当ipg_clk关闭时,该时钟应该在低功耗模式下打开。因此,PWM在低功耗模式下使用该时钟运行)
(3) Peripheral clock (ipg_clk)
(该时钟在正常运行时应为开启状态。在低功耗模式下,可将其关闭)
(4) Peripheral access clock (ipg_clk_s)
(该时钟用于寄存器的读/写)
2.工作原理

   PWM的输出是一个切换信号,其频率和占空比可以通过编程相应的寄存器来调制。它有一个16位向上计数器,从0x0000开始计数,直到计数器值等于PWM_PR+1。匹配发生后,计数器重置为0x0000。
采样器≈比较器
   在计数周期周期的开始,PWMO引脚设置为1(默认),计数器从0x0000开始向上计数。采样值在采样FIFO中,它的值在每个时钟周期和计数器的值比较。当采样值和计数值匹配时,PWMO信号被扫除为零(默认)。计数器继承计数,直到周期匹配发生,随后另一个周期周期开始。
    当PWM被启用时,计数器开始运行,并使用周期和采样寄存器中的重置值天生输出。建议在启用PWM之前完成这些寄存器的编程。
    硬件复位导致全部PWM计数和采样寄存器被扫除,FIFO被革新。控制寄存器显示FIFO为空,可以写入,PWM被禁用。软件复位具有相同的效果,但是控制寄存器中DBGEN、STOPEN、DOZEN和WAITEN位的状态不受影响。即使PWM处于禁用状态,也可以断言软件复位。
3.FIFO

写采样值的时候 会加载到FIFO(缓冲区) 最多写4个16位的数据
如果溢出 会有一个异常寄存器被置1(状态寄存器中的FWE)
   数字采样值可以作为16位字加载到脉宽调制器中。可以使用控制寄存器的BCTR和HCTR位来改变字节序。4字(16位)FIFO最大限度地减少了中断开销。当数据字的数量低于控制寄存器中FWM字段设置的水位时,会产生可屏蔽中断。
    如果FIFO未满,对PWM_SAR样本寄存器的写入会导致该值被存储到FIFO中。FIFO已满时的写入会设置状态寄存器中的FWE(FIFO写入错误)位,并且FIFO内容保持稳定。FIFO可以随时写入,但只有在启用PWM时才能读取。PWM_SR字段显示FIFO中当前包罗多少数据字以及是否可以写入。
四、PWM重点寄存器介绍

1.PWM Control Register (PWMx_PWMCR)

25 24 23 22 什么工作模式 打盹模式(省电) 一般没用
19-18 控制开始使能的时候 是先高再低照旧先低再高
2-1 FIFO(缓冲区)的每一个值 可以使用多少次 一般就一次
https://i-blog.csdnimg.cn/direct/10ae1fc80965465c888398e2e0e9cfb0.png
https://i-blog.csdnimg.cn/direct/490f0f5366164e3f87626d9e709b68a4.png
https://i-blog.csdnimg.cn/direct/aaa535b92d81409dafd480fdfab39591.png
https://i-blog.csdnimg.cn/direct/3c411866218f46c18881e5e9a46327ec.png
2.PWM Counter Register (PWMx_PWMCNR)

只读脉冲宽度调制器计数器寄存器(PWM_PWMCNR)包罗当前计数值,可以随时读取而不会干扰计数器。
https://i-blog.csdnimg.cn/direct/4a3102b786204abdbf812033563499df.png
3.PWM Period Register (PWMx_PWMPR)

PWM周期寄存器(PWM_PWMPR)确定PWM输出信号的周期,计数器值匹配PERIOD+1后,计数器复位以开始另一个周期。
   PWMO (Hz) = PCLK(Hz) / (period +2)
由于写入PWM_PWMPR导致的周期值的变化会导致计数器重置为零并开始新的计数周期。
https://i-blog.csdnimg.cn/direct/fd70394b1bb74839bf99e13cdca4e430.png
4.PWM Sample Register (PWMx_PWMSAR)

PWM采样寄存器(PWM_PWMSAR)是FIFO的输入。16位字被加载到FIFO中。FIFO可以随时写入,但只有在启用PWM时才能读取。
https://i-blog.csdnimg.cn/direct/8e54501737b7438b91437b31a7dea13f.png
五、PWM驱动蜂鸣器

1.原理图分析

https://i-blog.csdnimg.cn/direct/d59fdc51d7f24c8fa7371f9ca2e0e558.png
蜂鸣器CAMERA_MOTOR_PWN_IN1gpio1.IO
2.编程思绪

• 使能GPIO和PWM时钟信号
• 管脚设置为PWM功能模式
• 复位PWM控制器
• 选择时钟信号确定PWM的输入时钟信号
• 设置PWM周期值和采样值
• 开启PWM,然后延时一段时间,最后关闭PWM
3.代码实现

运行的时候 需要看波形有没有变化
#include "imx6ull.h"

/**
* @brief 初始化蜂鸣器对应的PWM输出
* @param sample 占空比设定值(有效电平时间)
* @param period 周期值(决定PWM频率)
*/
void beep_init(uint32_t sample, uint32_t period)
{
    /* 开启 PWM2 和 IOMUX 模块的时钟 */
    CCM_CCGR1 |= (0x3 << 26);
    CCM_CCGR4 |= (0x3 << 18);

    /* 设置GPIO1_IO09复用为PWM2输出(ALT0) */
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09 &= ~(0xf << 0);// 先清零
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09 |= 0x0;          // 配置为ALT0模式

    /* 复位PWM模块 */
    PWM2->PWMCR |= (1 << 3);             // 软复位
    while(PWM2->PWMCR & (1 << 3));       // 等待复位完成

    /*
   * 设置PWM时钟:
   * PWM时钟源为IPG_CLK_ROOT,频率为66MHz
   * 设置预分频器为65,则PWM输入时钟为 66MHz / (65 + 1) = 1MHz
   */
    PWM2->PWMCR = (1 << 16) | (65 << 4); // CLKSRC=1 (IPG_CLK), PRESCALER=65

    /* 设置PWM周期和占空比 */
    PWM2->PWMPR= period - 2;   // 周期寄存器(减2是硬件要求)
    PWM2->PWMSAR = sample;       // 有效电平时间

    return;
}

/**
* @brief 启动蜂鸣器(开启PWM)
*/
void beep_start(void)
{
    PWM2->PWMCR |= (1 << 0);    // 使能PWM
}

/**
* @brief 停止蜂鸣器(关闭PWM)
*/
void beep_stop(void)
{
    PWM2->PWMCR &= ~(1 << 0);   // 关闭PWM
}

/**
* @brief 设置蜂鸣器PWM占空比
* @param value 占空比值(有效电平时间)
*/
void set_sample_value(uint32_t value)
{
    PWM2->PWMSAR = value;
}

/**
* @brief 蜂鸣器测试函数,逐渐调整占空比
*/
void beep_test(void)
{
    int i;

    /* 初始化蜂鸣器,PWM频率为1kHz,占空比初始为50% */
    beep_init(500, 1000);

    beep_start();

    /* 循环改变占空比,从0%到100% */
    for(i = 0; i <= 100; i++){
      set_sample_value(i * 10);      // 设置占空比
      gpt_delay_ms(500);            // 延时500ms
    }

    beep_stop();

    return;
}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【物联网】PWM控制蜂鸣器