微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 第6课:PWM定时器

第6课:PWM定时器

时间:11-11 来源:互联网 点击:
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)
{
int i,j;
rGPEDAT = 0;
for(i=0;i

delay();
rGPEDAT = 3<12;
for(j=0;j<100-duty;j++)
delay();
}

int main()
{
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;
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top