一、前言
本篇主要讲一下51单片机定时器实现PWM,并且使用到keil的示波器方便大家对定时器实现的PWM做一个直观的了解。 在此之前相信大家都对PWM(脉冲宽度调制)或多或少的都有一定了解。下面来一个简单的演示:
二、实现过程
(一)代码部分
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
sbit GPIO_OUT= P3 ^ 1; //定义P3^1口为输出
uchar Counter = 0, Compare = 5;
ulong Ture_int = 0, Flast_int = 0; //用于记录高低电平产生的次数,本代码没有使用
void Timer0Init(void) //100微秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x02; //设置定时器模式
TL0 = 0x9C; //设置定时初值
TH0 = 0x9C; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //定时器0中断开关
EA = 1; //中断总开关
}
void main()
{
Timer0Init();
while (1)
{
}
}
void Timer0_Routune() interrupt 1 //中断函数,定时器0的中断号为1
{
if (Counter == 20)
{
Counter = 0;
}
Counter++;
if (Counter <= Compare)
{
//Ture_int++;
GPIO_OUT = 0;
}
else
{
//Flast_int++;
GPIO_OUT = 1;
}
}
(二)定时器选择和设置
本次使用了定时器0,方式二(8位自动重载),设置成每100us就中断一次。当TL0加到FF(256)就会产生一次中断,并执行中断函数。所以如果我们想定时器100us产生一次中断的话就需要给TL0一个9C(156)的值,因为机器使用的时钟是12MHZ,每1us产生一个计数脉冲。
(三)PWM原理
实现PWM就需要对我们的脉冲宽度进行一个设定了,这里我把它放在了中断函数里面,每进入一次中断函数,counter计数值就会加一,如果counter小于我们设定的compare比较值,就会保持GPIO_OUT为低电平。直到进行到某次我们的counter比我们的compare大,就会对GPIO_OUT高电平。因此我们只需要修改compare就可以实现脉冲宽度的设定了。如上述代码,我们将compare设置成5,就会得到下面的波形图:
可以看到高电平占一个周期的四分之一。因为只有当counter累加到20才会重新置零。我们也可以修改累加置零的值来改变这个波形的频率。
我们也不难看出这个波形的频率为500hz,虽然只有500hz但是用来控制LED灯的亮度是一点问题也没有。
三、keilC51的使用说明
1、首先需要设置好我们的晶振频率,方便计算起见我这里使用的是12MHZ。
2、debug的设置
3、点击仿真,开始后找到示波器
4、按图中的步骤设置好,在其中输入PORT3.1。Display type选择bit(很多时候看不到波形就是这里搞错了)
5、设置完成后
6、点击开始执行后,马上就可以按停止执行查看波形了。
四、最后
以上就是使用51单片机定时器实现PWM的基本过程,如有错漏还望指出。