可调周期、占空比pwm工程(蜂鸣器提示效果)
(一)proteus虚拟仿真电路
这是基于51单片机开发板的proteus虚拟仿真电路。如果没有示波器,建议下载一个proteus进行虚拟仿真,链接: https://pan.baidu.com/s/1eTlMIcYVT9ySdQoOxdXi8w 提取码: mfqw,如果已经安装有虚拟仿真软件,可以自行建立工程。
上图部分为仿真电路元器件,点击AT89C51上面的P键可以对元器件进行搜索。
上图可引导找到电源和接地的符号。
完成C代码编写后,双击虚拟电路中的51单片机会出现上图窗口,单击红圈中的图标选择相应的文件,点击运行即可。
(二)C语言程序代码
以下为此次工程的C代码,如发现有不足之处可以加群 1138473316 一起探讨 。
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit BZ=P1^5; //蜂鸣器输出端口
sbit PWM=P2^0; //P2^0口输出PWM
sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2;
sbit key4=P3^3;
uint time, upper, floor; //time为中断计数变量,upper为占空比上限,floor为占空比下限,
uint count=30,cyc=100; //count为占空比初始值,cyc为周期中间变量,注:周期=cyc*10.
uchar i=4;
uchar a[17]={10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90};
/***********延时xms程序***********/
void Delayxms(uint z)
{
uchar x, y;
while(z--)
{
x = 2;
y = 239;
do
{
while (--y);
} while (--x);
}
}
/***********定时器0初始化***********/
void T0_init()
{
TMOD=0x01; //定时器0工作于方式1
TH0=(65536-10)/256; //定时器0初值,每10us产生一次中断
TL0=(65536-10)%256;
TR0=1;
ET0=1;
EA=1;
}
/*********主函数********************/
void main()
{
T0_init();
while(1)
{
Delayxms(2);
if(key1==0) //占空比上调键按下;
{
Delayxms(2); //按键消抖
while(key1==0);
Delayxms(2);
count+=cyc/20;
upper=9*(cyc/10);
i++;
if(count>upper)
{
i=16;
count=upper;
}
}
if(key2==0) //占空比下调键按下;
{
Delayxms(2);
while(key2==0);
Delayxms(2);
count-=cyc/20;
floor=cyc/10;
i--;
if(count<floor)
{
i=0;
count=floor;
}
}
if(key3==0) //周期中间变量上调键按下;
{
Delayxms(2);
while(key3==0);
Delayxms(2);
cyc+=100;
if(cyc>=1000) cyc=1000;
count=a[i];
count*=(cyc/100);
}
if(key4==0) //周期中间变量下调键按下;
{
Delayxms(2);
while(key4==0);
Delayxms(2);
cyc-=100;
if(cyc<100) cyc=100;
count=a[i];
count*=(cyc/100);
}
if(count>cyc/2) //蜂鸣器反转循环
{
BZ=~BZ;
}
}
}
/**************定时0中断处理******************/
void timer0_int() interrupt 1
{
TR0=0; //设置定时器初值期间,关闭定时器
TH0=(65536-10)/256; //定时器0初值,每10us产生一次中断
TL0=(65536-10)%256;
TR0=1;
time++;
if(time<count) PWM=1; //输出高电平
else if(time>=count && time<cyc) PWM=0; //输出低电平
else time=0;
}
来源:oschina
链接:https://my.oschina.net/u/4393607/blog/4372060