请参考:
http://hi.baidu.com/caterwang0871/blog/item/8e4709dfa96b53cb8c1029c7.html这里用的是定时器0方式2,改一下或许满足你的需求!
说明:项目中要使有PWM信号来驱动喇叭,且要有两种不同的声响要求;晶振为12MHz
使用时,Timer0Init()为主程序,详情请参考相关说明!
//--------------------------------------------------------------
//PWM2.c
//利用定时器中断来产生占空比为0.5,频率两档可选的PWM信号
//故障时单频率信号间歇输出,险情时两个不同频率信号交替输出
//--------------------------------------------------------------
//#include "c8051F040.h"
//sbit PWM=P4^7;
#include <reg51.h> //test in AT89C51
sbit PWM=P1^0;
unsigned char THD1,TLD1,THD2,TLD2; //定时器初值(两组)
unsigned char counter,n; //中断次数计数(时间)
unsigned char mod; //报警方式(故障--1 或是险情--2)
//1.定时器中断服务程序,定时器0,方式1
void Timer0Mod1(void) interrupt 1 using 1
{
counter++;
if(counter==100)
{n++;counter=0;}
switch(n)
{
case 0: //每个180ms=1.8ms*100
case 1:
case 2:
{
TH0=THD1;
TL0=TLD1;
PWM=~PWM; //IO状态取反,以产生一连续变化的波开,用于驱动speaker;
break;
}
case 3:
case 4:
case 5:
{
if(mod==1) //故障,每个180ms,5结束
{
TH0=THD1; //IO状态不变,speaker无声;
TL0=TLD1;
}
if(mod==2) //险情,每个130ms=1.3ms*100
{
TH0=THD2;
TL0=TLD2;
PWM=~PWM; //IO状态取反,以产生一连续变化的波开,用于驱动speaker;
}
break;
} //5
default: { n=0;break;}
}
if(mod==2&&n==2) n=3; //提前结束,以调整两个频率所的占空比
if(mod==2&&n==5) n=0;
}
//2.报警输出开关,输出有两种(f=277.8 or f=384.6,单位为HZ)
//参数:m为模式选择,1为故障,2为险情,其他任意值则关闭PWM信号输出--可用于消音)
void Timer0Init(unsigned char m)
{
//P4MDOUT=0x80; //设置P4.7为推挽输出
THD1=0xf8; //f=277.8Hz,t=1.8ms
TLD1=0xf8;
THD2=0xfa; //f=384.6Hz,t=1.3ms
TLD2=0xec;
counter=0;
n=0;
switch(m)
{
case 1: {mod=1; F0=1; break;} //故障
case 2: {mod=2; F0=1; break;} //险情
default : {F0=0; break;} //消音
}
if(F0)
{
TMOD|=0x01;
TH0=THD1;
TL0=TLD1;
ET0=1;
TR0=1;
EA=1;
}
else
{
ET0=0;
TR0=0;
}
}
void main(void) //测试用程序
{
while(1)
{
P3=0xff;
Timer0Init(1);
while(P3==0xff);
while(P3!=0xff);
Timer0Init(0);
while(P3==0xff);
while(P3!=0xff);
Timer0Init(2);
while(P3==0xff);
while(P3!=0xff);
Timer0Init(0);
while(P3==0xff);
while(P3!=0xff);
}
}