目录
一、PWM简介
1.1蜂鸣器工作原理
有源蜂鸣器
无源蜂鸣器
1.2使用GPIO控制
1.3PWM控制
1.4PWM参数
周期
占空比
二、Exynos_4412下的PWM控制器
三、PWM寄存器详解
四、PWM编程
一、PWM简介
1.1蜂鸣器工作原理
有源蜂鸣器
有源蜂鸣器只要接上额定电源就可以发出声音
无源蜂鸣器
无源蜂鸣器利用电磁感应原理,为音圈接入交变电流后形成的电磁铁与永磁铁相吸或相斥而推动振膜发声
人可以听到20-20000Hz的声音
1.2使用GPIO控制
while(1)
{
GPX2.DAT=GPX2.DAT | (1 << 7);
Delay(1000000);
GPX2.DAT=GPX2.DAT & (~(1 << 7));
Delay(1000000);
}
这样虽然可以控制,但是太浪费CPU资源了。
1.3PWM控制
PWM(Pulse Width Modulation)即脉冲宽度调制,通过对脉冲的宽度进行调制,来获得所需要波形
1.4PWM参数
周期
占空比
一个周期中高电平时间与整个周期的比例称为占空比
二、Exynos_4412下的PWM控制器
有五个PWM定时器。可以产生中断。0-3支持GPIO,0有死区可以支持大电流.。4是内部定时器没有输出引脚(4412的PWM定时器和看门狗都是递减的)
PWM死区(Dead Zone)的作用和意义_Python-Jack的博客-CSDN博客
DSP里的PWM死区-电子发烧友网
PWM使用PCLK(100MHz)作为时钟源,timer 0和1共用一个8位的一级预分频器(1-256倍)
timer2,3,4共用另外一个8位一级分频器 然后每个timer都有一个自己的二级分频器(2,4,8,16)
把周期也就是这个159写进TCNTB,把占空比写进TCMTB
给计数器使能,需要手动关闭
TCNTB把159写进递减计数器,对外的输出引脚开始输出低电平,以前输出的是高电平
递减计数器减到109开始输出高电平
如果递减计数器到0产生中断
递减计数器自动重加载,然后一直循环
反向输出功能
三、PWM寄存器详解
这个实验不需要设置死区因为就应该蜂鸣器,然后咱们是定时器0所以设置【7:0】位就行。
看一下TCON,我们只需要关注timer0这部分
【4】死区的开关
【3】输出一个周期还是连续输出
【2】反向功能的开关
【1】 第一个周期TCNTB里的值不会自动装到递减计数器里,把这位写1就会把这个值装到递减计数器里,后续的会自动重装
【0】写1开启递减计数器,写0关闭
这俩上面讲工作原理时说过了,但是注意周期一定要比高电平这个寄存器里的值大
如果想知道递减计数器里的值可以读一下这个寄存器
四、PWM编程
为了听起来舒服一些这个实验配置频率为500Hz
还是先解压出来一个工程模板并改下名
先配置一下GPIO的引脚
#include "exynos_4412.h"
int main()
{
//GPD0_0设置PWM0输出功能
GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);
//PWM0一级分频 100倍
PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | (99);
//PWM0二级分频 1倍 PCLk/(99+1)/(0+1) = 1MHz
PWM.TCFG1 = PWM.TCFG1 & (~(0xF));
//设置PWM0自动重装
PWM.TCON = PWM.TCON | (1<<3);
//设置周期 500
PWM.TCNTB0 = 2000;
//占空比 50%
PWM.TCMPB0 = 1000;
//手动装载
PWM.TCON = PWM.TCON | (1 << 1);
//关闭手动装载
PWM.TCON = PWM.TCON & (~(1 << 1));
//使能PWM0
PWM.TCON = PWM.TCON | 1;
while(1)
{
}
return 0;
}
声音还可以,我们还可以让他间断响
#include "exynos_4412.h"
void delay(unsigned int time)
{
while(time --);
}
int main()
{
//GPD0_0设置PWM0输出功能
GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);
//PWM0一级分频 100倍
PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | (99);
//PWM0二级分频 1倍 PCLk/(99+1)/(0+1) = 1MHz
PWM.TCFG1 = PWM.TCFG1 & (~(0xF));
//设置PWM0自动重装
PWM.TCON = PWM.TCON | (1<<3);
//设置周期 500
PWM.TCNTB0 = 2000;
//占空比 50%
PWM.TCMPB0 = 1000;
//手动装载
PWM.TCON = PWM.TCON | (1 << 1);
//关闭手动装载
PWM.TCON = PWM.TCON & (~(1 << 1));
//使能PWM0
PWM.TCON = PWM.TCON | 1;
while(1)
{
PWM.TCON = PWM.TCON | 1;
delay(100000);
PWM.TCON = PWM.TCON & (~(1));
delay(100000);
}
return 0;
}
现在改成频率1000Hz,占空比60%试一试,这次声音有点像以前小灵通
#include "exynos_4412.h"
void delay(unsigned int time)
{
while(time --);
}
int main()
{
//GPD0_0设置PWM0输出功能
GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);
//PWM0一级分频 100倍
PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | (99);
//PWM0二级分频 1倍 PCLk/(99+1)/(0+1) = 1MHz
PWM.TCFG1 = PWM.TCFG1 & (~(0xF));
//设置PWM0自动重装
PWM.TCON = PWM.TCON | (1<<3);
//设置周期 1000
PWM.TCNTB0 = 1000;
//占空比 60%
PWM.TCMPB0 = 600;
//手动装载
PWM.TCON = PWM.TCON | (1 << 1);
//关闭手动装载
PWM.TCON = PWM.TCON & (~(1 << 1));
//使能PWM0
PWM.TCON = PWM.TCON | 1;
while(1)
{
PWM.TCON = PWM.TCON | 1;
delay(100000);
PWM.TCON = PWM.TCON & (~(1));
delay(100000);
}
return 0;
}