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 
相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms6 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下6 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。6 天前
2026.2.25监控学习
学习
im_AMBER6 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J6 天前
从“Hello World“ 开始 C++
c语言·c++·学习