ARM嵌入式学习--第八天(PWM)

PWM

-PWM介绍

PWM (pulse Width Modulation)简称脉宽调制 ,是利用微处理器的数字输出来对模拟电路进行控制 的一种非常有效的技术,广泛应用在测量,通信,工控等方面

PWM的频率

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

PWM的周期

T=1/f,T是周期,f是频率 ,即如果频率为50HZ ,也就是说一个周期是20ms ,那么1秒钟就有50个PWM周期

占空比

一个脉冲周期 内,高电平的时间整个周期时间的比例(0%~100%)

总结

1.脉冲周期 (T),单位是时间,比如纳秒(ns),微秒(us),毫秒(ms)等

2.脉冲频率 (f),单位是HZ,KHZ等,与脉冲周期成倒数关系 ,f=1/T

3.脉冲宽度 (W),简称"脉宽",是脉冲高电平持续的时间 ,单位是时间

4.占空比 (D),脉宽除以脉冲周期的值百分比表示 ,比如50%,也常有小数或分数表示的,比如0.5或1/2

以上之间的关系如图所列的公式:

-PWM的工作原理分析(IMX6ull)

脉宽调制 (PWM)有一个16位计数器, 经过优化,可以从存储的样本音频图像中生成声音 ,还可以生成音调 ,它使用16位分辨率指的就是16位计数器4 x 16数据FIF0[缓存]

工作原理

PWM的输出是一个切换信号 ,其频率和占空比可以通过编程相应的寄存器来调制 ,它有一个16位向上计数器 ,从0x0000开始计数直到计数器值等于 PWM_PR+1,匹配发生后,计数器重置为0x0000(PWM_PR是周期寄存器

在计数周期的开始 ,PWM0引脚设置为1 (默认),计数器从0x0000开始向上计数采样值在采样 FIF0中,它的值在每个时钟周期和计数器的值比较 ,当采样值和计数器匹配 时,PWM0信号被清除为 0(默认),计数器继续计数,直到周期匹配发生,随后另一个周期开始

当PWM被启用时计数器开始运行 ,并使用周期和采样寄存器中的重置值生成输出 ,建议在启用PWM之前完成这些寄存器的编程

硬件复位****导致所有PWM计数和采样寄存器被清除FIF0被刷新,控制寄存器显示FIF0为空,可以写入,PWM被禁用软件复位 具有相同的结果,但是控制寄存器中DBGEN,STOPEN,DOZEN和WAITEN位的状态不受影响,只有PWM处于禁用状态,才可以进行软件复位

FIF0

数字采样值可以作为16位字加载到脉冲调制器中 ,可以使用控制器的BCTR和HCTR位来改变字节序,4字(16位)FIF0最大限度地减少了中断开销。当数据字的数量低于控制寄存器的FWM字段设置的水位时会产生可屏蔽中断

如果FIF0未满对PWM_SAR采样寄存器的写入会导致该值被存储到FIF0中,FIF0已满时的写入会设置状态寄存器中的FWE(FIF0写入错误)位 ,并且FIF0内容保持不变,FIF0可以随时写入,但只有在启用PWM时,才能读取 ,PWM_SR[FIF0AV]字段显示FIF0中当前包含多少数据字以及是否可以写入

-PWM重点寄存器介绍

PWM Control Register (PWMx_PWMCR)
PWM Counter Register (PWMx_PWMCNR)

只读脉冲宽度调制器计数器寄存器 (PWM_PWMCNR)包含当前计数值,可以随时读取而不会干扰计数器

PWM Period Register(PWMx_PWMPR)

PWM周期寄存器 (PWM_PWMPR)确定PWM输出信号的周期,计时器值匹配PERIOD+1后,计数器复位以开始另一个周期( PWMO[Hz] = PLCK[Hz]/period+2**)**

( 由于写入PWM_PWMPR导致的周期值的变化会导致计数器重置为零并开始新的计数周期**)**

PWM Sample Register(PWMx_PWMSAR)

PWM采样寄存器 (PWM_PWMSAR)是FIF0的输入,16位字被加载带FIF0的输入 。FIF0可以随时写入 ,但只有启用PWM时才能读取

-PWM驱动蜂鸣器

原理图分析

原理图通过GPIO_9这个IO来控制蜂鸣器,当GPIO_9输出低电平 的时蜂鸣器发声。设置GPIO1_9的MUX mod为PWM的工作模式,不同的占宽比让蜂鸣器发出的响声不一样

编程思路

1.使能GPIO和PWM时钟信号

2.管脚设置为PWM功能模式

3.复位PWM控制器

4.选择时钟信号确定PWM的输入时钟信号

5.设置PWM周期值和采样值

6.开启PWM,然后延时一段时间,最后关闭PWM

示例代码
pwm.c
cs 复制代码
#include  "pwm.h"

void pwm_gpio_init(){
    //开启时钟
    CCM_CCGR1 |= (0x3 << 26);
    // 设置复用器
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09 &=~(0xf<<0);
    //设置方向
    GPIO1->GDIR |= (0x1<<9);
}

//pwm的初始化
void pwm_init(){
    //开启时钟
    CCM->CCGR4 |= (0x3 << 18);
    //禁用PWM
    PWM2->PWMCR &= ~(0x1 <<0);
    //软件复位
    PWM2->PWMCR |= (0x1<<3);
    while (PWM2->PWMCR & (0x1 << 3)){
    }
    //选择时钟源
    PWM2->PWMCR &= ~(0x3<<16);
    PWM2->PWMCR |= (0x1 << 16);
    // 设置pwm的时钟分频器
    PWM2->PWMCR &= ~(0xfff << 4);
    PWM2->PWMCR |= (0x41 << 4);
    //设置周期
    PWM2->PWMPR = PERIOD - 2;
}

//打开PWM
void pwm_on(){
    // 使能pwm
    PWM2->PWMCR |= (0x1 << 0);
}

//关闭PWM
void pwm_off(){
    // 关闭pwm
    PWM2->PWMCR &= ~(0x1 << 0);
}

// 设置采样值
void pwm_set_sample_val(int val){
    PWM2->PWMSAR = val;
}

//测试
void pwm_test(){
    pwm_gpio_init();
    pwm_init();
    pwm_on();
    int i=0;
    for(;i<=10;i++){
        pwm_set_sample_val(i*100);
        gpt_delay_mseconds(500);
    }
    pwm_off();
}
pwm.h
cs 复制代码
#ifndef __PWM_HEAD_
#define __PWM_HEAD_

#include "../../include/imx6ull.h"
#include "../driver/gpt/gpt.h"
#include <stdio.h> 

#define PERIOD 1000

extern void pwm_test();
#endif 
相关推荐
cwtlw13 分钟前
CSS学习记录17
前端·css·笔记·学习·css3
Ryo HJ1 小时前
【AIGC学习笔记】——GraphRAG本地部署
笔记·学习·aigc
Anna_Tong1 小时前
Windows生态圈:如何改变我们的数字生活
windows·学习·生活·娱乐
明月清了个风3 小时前
数据结构与算法学习笔记----SPFA判断负环
笔记·学习
魔力军5 小时前
学习记录:electron主进程与渲染进程直接的通信示例【开箱即用】
javascript·学习·electron
许许前进6 小时前
学习记录(13):VR晕动症-VR Motion Sickness
学习·vr
真诚的灰灰6 小时前
MAPTR:在线矢量化高精地图构建的结构化建模与学习(2208)
人工智能·学习·机器学习·自动驾驶·汽车
权^10 小时前
[面试题]--索引用了什么数据结构?有什么特点?
数据结构·学习·mysql
小虎鲸7211 小时前
Scratch教学作品 | 圣诞节平台游戏——在节日中挑战冒险,收集礼物吧! ✨
学习·游戏·青少年编程