利用PWM实现呼吸灯
核心源码
#include "reg52.h"
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
sbit PWMOUT = P0^0;
u8 HighRH = 0;
u8 HighRL = 0;
u8 LowRH = 0;
u8 LowRL = 0;
void ConfigPWM(u16 fr, u8 dc);//注意一个频率一个占空比,频率是u16
void ClosePWM();
void CloseFucker();
void main()
{
u32 i;
CloseFucker();
P2 = (P2 & 0x1F) | 0x80;
P0 = 0xFF;//务必先关闭,然后才能选通对应的!
EA = 1;
while (1)//注意占空比指的是高电平的持续时间,CT107D小灯是低电平点亮。
{
ConfigPWM(100, 10); //频率100Hz,占空比10%
for (i=0; i<100000; i++);
ClosePWM();
ConfigPWM(100, 40); //频率100Hz,占空比40%
for (i=0; i<100000; i++);
ClosePWM();
ConfigPWM(100, 90); //频率100Hz,占空比90%
for (i=0; i<100000; i++);
ClosePWM(); //关闭PWM,相当于占空比100%
for (i=0; i<100000; i++);
}
}
void CloseFucker()
{
P2 = (P2 & 0x1F) | 0xA0; //关闭蜂鸣器和继电器
P0 = P0 & 0xAF;
P2 = 0x00;
}
void ConfigPWM(u16 fr, u8 dc) //这一段配置非常有意思
{
u32 tmp;//用来存临时总值
u16 high, low; //用来存高电平低电平的总值
tmp = (11059200/12)/fr;//算出对应频率的总值
high = (tmp*dc)/100;//算出高电平总值
low = tmp - high;//算出低电平总值
high = 65536 - high;//对应该的计数开始值
low = 65536 - low;
HighRH = (u8)(high >> 8);//它们四个是个全局变量,在中断给P00口赋值。
HighRL = (u8)high;
LowRH = (u8)(low >> 8);
LowRL = (u8)low;
//AUXR &= 0x7F;//这里我没加AUXR寄存器的相关设置,15上电默认是12T
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = HighRH;
TL0 = HighRL;
ET0 = 1;
TR0 = 1;
PWMOUT = 1;
}
void ClosePWM()
{
TR0 = 0;
ET0 = 0;
PWMOUT = 1;
}
void InterruptTimer() interrupt 1
{
if(PWMOUT == 1)
{
TH0 = LowRH;
TL0 = LowRL;
PWMOUT = 0;//注意,赋完值要记得把引脚的电平翻转啊!!!
}
else
{
TH0 = HighRH;
TL0 = HighRL;
PWMOUT = 1;
}
}