用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比。
下面重点介绍用一个定时器的实现PWM的方法。以周期为1ms(1kHZ)为例,要产生其它频率的PWM波,程序中只需作简单修改即可。用一个定时器时(如定时器T0),首先要确定PWM的周期T和占空比D,确定了这些以后,就可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则D*T=n*t,类似的可以求出PWM低电平时间需要多少个时间基准n。因为这里我们是产生周期为1ms(1kHZ)的PWM,所以可设置中断的时间基准为0.01ms,,然后中断100次即为1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:
1、当time>=100时,time清零(此语句保证频率为1kHZ);2、当time>n时(n应该在0-100之间变化开),让单片相应的I/O口输出低电平;3、当time<=n时,让单片相应的I/O口输出高电平,此时占空比就为%n。
下面程序产生30%占空比的pwm:代码示例
#include
#define uint unsigned int#define uchar unsigned charsbit PWM=P2^0;// P2.0输出pwmuchar time; // 定义占空比的变量void main(){ TMOD=0x01;//定时器0工作方式1 TH0=0xff;//(65536-10)/256;//赋初值定时 TL0=0xf7;//(65536-10)%256;//0.01ms EA=1;//开总中断 ET0=1;//开定时器0中断 TR0=1;//启动定时器0 while(1) { } }void tim0() interrupt 1{ TR0=0;//赋初值时,关闭定时器 TH0=0xff;//(65536-10)/256;//赋初值定时 TL0=0xf7;//(65536-10)%256;//0.01ms TR0=1;//打开定时器 time++; if(time>=100) //1khz time=0; if(time<=30) //占空比%30,可改 PWM=1; else PWM=0;}