目录
1 PWM简介
1.1 蜂鸣器工作原理
1.2 GPIO控制
1.3 PWM控制
2 Exynos4412下的 PWM控制器
2.1 总览
2.2 设置步骤
2.3 功能框图
2.4 特征
3 寄存器介绍
3.1 总览
3.2 TCFG0 一级分频寄存器
3.3 TCFG1 二级分频寄存器
3.4 TCON控制寄存器
3.5 TCNTB TCMPB TCNTO
4 PWM编程
4.1 原理图
5 练习
1 PWM简介
1.1 蜂鸣器工作原理
有源蜂鸣器
有源蜂鸣器只要接上额定电源就可以发出声音
无源蜂鸣器
无源蜂鸣器利用电磁感应原理,为音圈接入交变电流后形成的电磁铁与永磁铁相吸或相斥而推动振膜发声
1.2 GPIO控制
可以实现pwm的波形,但是占用cpu
1.3 PWM控制
PWM(Pulse Width Modulation)即脉冲宽度调制,通过对脉冲的宽度进行调制,来获得所需要波形
其实就是定时器
2 Exynos4412下的 PWM控制器
2.1 总览
Exynos 4412 SCP拥有五个32位脉冲宽度调制(PWM)定时器。这些定时器会为ARM子系统生成内部中断。此外,定时器0、1、2和3包括可驱动外部I/O信号的PWM功能。定时器0的PWM具有可选的死区生成器功能,以支持大电流设备。定时器4是一个内部定时器,没有输出引脚。
这些定时器使用APB-PCLK作为时钟源。定时器0和1共享可编程8位预分频器,用于对PCLK进行第一级分频。定时器2、3和4共享另一个8位预分频器。每个定时器都有自己的专用时钟分频器,提供第二级时钟分频(预分频器除以2、4、8或16)。
每个定时器都有自己的32位递减计数器;定时器时钟驱动该计数器。定时器计数缓冲寄存器(TCNTBn)加载递减计数器的初始值。如果递减计数器达到零,它会生成定时器中断请求,通知CPU定时器操作已完成。如果定时器递减计数器达到零,则相应的TCNTBn的值会自动重新加载到递减计数器中,开始下一个循环。但是,如果定时器停止运行,例如在定时器运行模式下清除TCONn的定时器使能位,TCNTBn的值不会重新加载到计数器中。
PWM功能使用TCMPBn寄存器的值。如果递减计数器的值与定时器控制逻辑中的比较寄存器的值匹配,定时器控制逻辑会改变输出电平。因此,比较寄存器确定PWM输出的开启时间或关闭时间。
每个定时器都是双缓冲结构,具有TCNTBn和TCMPBn寄存器,允许在周期中更新定时器参数。新值直到当前定时器周期完成后才会生效。
2.2 设置步骤
使用PWM作为脉冲发生器的步骤如下:
- 使用159(50 + 109)初始化TCNTBn寄存器,使用109初始化TCMPBn寄存器。
- 启动定时器:设置启动位,并手动将该位更新为关闭状态。
- 将TCNTBn值159加载到递减计数器中,然后将输出TOUTn设置为低电平。
- 如果递减计数器从TCNTBn计数到TCMPBn寄存器中的109,则输出从低电平变为高电平。
- 如果递减计数器达到0,则会生成一个中断请求。
- 递减计数器会自动重新加载TCNTBn。这将重新启动循环。
2.3 功能框图
2.4 特征
PWM的特性包括:
- 五个32位定时器。
- 两个8位时钟预分频器,用于对PCLK进行第一级分频。五个时钟分频器和多路复用器,用于对预分频器时钟进行第二级分频。
- 可编程时钟选择逻辑,用于每个PWM通道的独立控制。
- 四个独立的PWM通道,具有可编程的占空比控制和极性。
- 静态配置:停止PWM。
- 动态配置:PWM正在运行。
- 自动重载和单次脉冲模式。
- 两个PWM输出上的死区生成器。
- 等级中断生成。
PWM有两种操作模式,它们是:
- 自动重载模式:在该模式下,根据编程的占空比和极性生成连续的PWM脉冲。
- 单次脉冲模式:在该模式下,根据编程的占空比和极性仅生成一个PWM脉冲。
为了控制PWM的功能,提供了18个特殊功能寄存器。PWM是一个AMBA从属模块,具有可编程输出和时钟输入,并且PWM连接到高级外设总线(APB)。可以通过APB事务访问PWM内的这18个特殊功能寄存器。
其余信息略
3 寄存器介绍
3.1 总览
3.2 TCFG0 一级分频寄存器
用于配置两个8位预分频器和死区或者死区长度。一级分频
3.3 TCFG1 二级分频寄存器
控制五个多路选择位的定时器配置寄存器,二级分频
3.4 TCON控制寄存器
3.5 TCNTB TCMPB TCNTO
TCNTB定时器计数寄存器
TCMPB定时器比较寄存器
TCNTO定时器计数值读取寄存器(只读)
4 PWM编程
人的听力范围20Hz-20000hz,实现一个500hz的蜂鸣器
4.1 原理图
GPD0_0驱动蜂鸣器
对应PWM0通道
#include "exynos_4412.h"
void Delay(unsigned int Time)
{
while(Time --);
}
int main()
{
/*1.将GPD0_0引脚设置成PWM0的输出引脚*/
GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);
/*2.设置PWM0的一级分频 一级分频倍数设置为100倍*/
PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | 99;
/*2.设置PWM0的二级分频 二级分频倍数设置为1倍 递减计数器递减频率 = PLCK / (99 + 1) / 1 = 1M*/
PWM.TCFG1 = PWM.TCFG1 & (~(0xF));
/*4.设置PWM0为自动重装载,使其能够产生连续的脉冲信号*/
PWM.TCON = PWM.TCON | (1 << 3);
/*5.设置PWM0的频率为500HZ*/
PWM.TCNTB0 = 2000;
/*6.设置PWM0的占空比为50%*/
PWM.TCMPB0 = 1000;
/*7.将TCNTB0中的值手动装载到递减计数器*/
PWM.TCON = PWM.TCON | (1 << 1);
/*8.关闭手动更新*/
PWM.TCON = PWM.TCON & (~(1 << 1));
/*9.使能PWM0,递减计数器开始递减*/
PWM.TCON = PWM.TCON | 1;
while(1)
{
PWM.TCON = PWM.TCON | 1;
Delay(1000000);
PWM.TCON = PWM.TCON & (~(1));
Delay(1000000);
}
return 0;
}
5 练习
编程实现通过PWM控制蜂鸣器产生"嘀嘀"的声音
注:PWM的频率1000HZ,占空比%60
#include "exynos_4412.h"
void Delay(unsigned int Time)
{
while(Time --);
}
int main()
{
/*1.将GPD0_0引脚设置成PWM0的输出引脚*/
GPD0.CON = GPD0.CON & (~(0xF)) | (0x2);
/*2.设置PWM0的一级分频 一级分频倍数设置为100倍*/
PWM.TCFG0 = PWM.TCFG0 & (~(0xFF)) | 99;
/*2.设置PWM0的二级分频 二级分频倍数设置为1倍 递减计数器递减频率 = PLCK / (99 + 1) / 1 = 1M*/
PWM.TCFG1 = PWM.TCFG1 & (~(0xF));
/*4.设置PWM0为自动重装载,使其能够产生连续的脉冲信号*/
PWM.TCON = PWM.TCON | (1 << 3);
/*5.设置PWM0的频率为1000HZ*/
PWM.TCNTB0 = 1000;
/*6.设置PWM0的占空比为60%*/
PWM.TCMPB0 = 600;
/*7.将TCNTB0中的值手动装载到递减计数器*/
PWM.TCON = PWM.TCON | (1 << 1);
/*8.关闭手动更新*/
PWM.TCON = PWM.TCON & (~(1 << 1));
/*9.使能PWM0,递减计数器开始递减*/
PWM.TCON = PWM.TCON | 1;
while(1)
{
PWM.TCON = PWM.TCON | 1;
Delay(1000000);
PWM.TCON = PWM.TCON & (~(1));
Delay(1000000);
}
return 0;
}