PWM是守时器全名叫脉宽调制守时器。
主要有2个功用:
1守时
2计时
在咱们开发板上有5个pwm守时器。TIMER0到TIMER4。
其间TIMER4是没有输出的,作为内部时钟运用。而其他四个是GPB0~3的复用引脚功用。
四个中TIMER0还有个叫死区发生器的东西,用来对大功率的外设来限流的。
再提一个概念。叫占空比。即一个周期内高电平占总的电平时刻的比率。这个便是咱们说的脉宽调制。
现在来剖析内部结构。
守时器用的是PCLK的时钟,咱们的开发板PCLK是50Mhz。这个频率太高了,速度太快了,不方便咱们计时。所以咱们内部有2个分平器。
第一个分屏器是Timer0和1同享的。别的一个是3,4,5同享。能够分红1/2~1/16 。第2个分屏器是8位。每个守时器都有独自的。
之后。
再来介绍下内部的计数办法。内部有两个寄存器,TCNT 是计数递减的 减到0会从头reload TCNTB中的值 TCMP是当TCNT中的值与TCMP的值相一起,凹凸电平要倒置。这个便是调理占空比的办法。而TCNT到0的时分 TCMP也会去reload 不过load的是TCMPB中的值。
核算时刻的公式:例如咱们要算0.5s
0.5*( PCLK / (prescale*devide) ) = TCNTB
注意在第一次开端计数的时分,需求手动导入TCNT的值。
过程如下:
1设置数值到TCNTB
2翻开手动更新位
3翻开主动更新为和使能PWM位。
以下写个程序:
用PWM的完成小灯0.5秒闪,0.5秒暗。分屏1是1/4 分屏2是100 计数是0xffff。
以下是pwm.c
#include”s3c2440.h”
void init_led()
{
rGPECON = GPE12_out|GPE13_out;
}
void init_timer0()
{
rTCFG0 = 0x63;
rTCFG1 = 0x1;
rTCNTB0 = 0xFFFF;
rTCON = 0xa;//手动载入
rTCON = 0x9; //主动载入
}
void init_irq()
{
rINTMOD = 0;
rINTMSK = ~(1<<10); //设置了计数器TIMER0的屏蔽位翻开。
}
int main()
{
init_led();
init_irq();
init_timer0();
while(1);
}
以下是中止服务程序:
#include”s3c2440.h”
void ISR_Handle()
{
rGPEDAT ^= (3<<12);//用异或的办法能够完成履行一次点亮再履行一次灭灯
rSRCPND = 1<<10;//清中止
rINTPND = 1<<10;
}
其他makefile crt0.s pwm.lds s3c2440.h 文件省掉。
整个程序仍是比较简单的。
可是咱们并没有使用到它的PWM功用。由于咱们的引脚并没有连接到其他外设上,而是在GPB0~3复用的方位。所以要使用PWM,咱们只能选用模仿的办法。例如下面写了一个使用小灯替换闪耀的办法,制造出小灯逐渐变亮和小灯逐渐变暗的视觉。
#include”s3c2440.h”
void init_led()
{
rGPECON = 5<<24;
}
void delay()
{
long i=200;
do{
i–;
}
while(i>0);
}
void pwm_like(int duty) delay(); int main()
{
int i,j;
rGPEDAT = 0;
for(i=0;i
rGPEDAT = 3<<12;
for(j=0;j<100-duty;j++)
delay();
}
{
init_led();
while(1){
int duty1=0;
int duty2=100;
while(duty1<=100){
pwm_like(duty1); //这边是操控占空比从0到100
duty1++;
}
while(duty2>=0){
pwm_like(duty2);
duty2–;
}
}
return 0;
}