觉得自己再有必要开一篇PWM的文章了

对一个东西在不同的时间段总有不一样的体会。。。


贴上以前写过的有关PWM的文章

  • 51寻迹小车+蓝牙
  • 51定速器配置PWM技巧
  • 实战之呼吸灯

1、PWM初见

#include 

typedef unsigned char u8;

void CloseFucker();

void main()
{
	u8 i;
	u8 temp = 0;
	
	CloseFucker();
	
	P2 = (P2&0x1F) | 0x80;
	P0 = 0xFF;
	P2 = P2&0x1F;
	
	while(1)
	{
		for(i=0; i<200; i++)
		{
			if(i<10)
			{
				P2 = (P2&0x1F) | 0x80;
				P0 = 0xFE;
				P2 = P2 & 0x1F;
			}
			else
			{
				P2 = (P2&0x1F) | 0x80;
				P0 = 0xFF;
				P2 = P2 & 0x1F;
			}
		}
	}
}

void CloseFucker()
{
	P2 = (P2&0x1F) | 0xA0;
	P0 &= 0xAF;
	P2 = P2&0x1F;
}

实验现象:

觉得自己再有必要开一篇PWM的文章了_第1张图片

实验原理:

觉得自己再有必要开一篇PWM的文章了_第2张图片

2、静态亮度等级控制

#include 

typedef unsigned char u8;

u8 code LightLevel[8] = {0,1,2,4,8,16,32,64};
void CloseFucker();

void main()
{
	u8 i, j;
	u8 temp = 0;
	
	CloseFucker();
	
	P2 = (P2&0x1F) | 0x80;
	P0 = 0xFF;
	P2 = P2&0x1F;
	
	while(1)
	{
		for(i=0; i<64; i++)//共64个脉冲(其实就是对应的总周期)
		{
			for(j=0; j<8; j++)
			{
				if(LightLevel[j] <= i)
				{
					temp |= (1<

实验现象:

觉得自己再有必要开一篇PWM的文章了_第3张图片

实验原理:

i所在的for循环一共产生了64个脉冲j所在for循环控制8个LED的亮灭状态

L1的亮度等级是0,所以一直置1,那么对应占空比为100%,这里占空比是针对高低电平而言,一直是高电平,而小灯是低电平点亮,所以L1一直是灭!

其余小灯以此类推不难得出对应的现象。

觉得自己再有必要开一篇PWM的文章了_第4张图片

这里写图片描述

当然了这个程序还可以这样写:

#include 

typedef unsigned char u8;

u8 code LightLevel[8] = {0,1,2,4,8,16,32,64};
void CloseFucker();

void main()
{
	u8 i, j;
	u8 temp = 0;
	
	CloseFucker();
	
	P2 = (P2&0x1F) | 0x80;
	P0 = 0xFF;
	P2 = P2&0x1F;
	
	while(1)
	{
		for(i=0; i<64; i++)//共64个脉冲
		{
			temp = 0x00;	
			for(j=0; j<8; j++)
			{
				if(LightLevel[j] <= i)
				{
					temp |= (1<

跟之前底层时序的实现中,譬如
觉得自己再有必要开一篇PWM的文章了_第5张图片

觉得自己再有必要开一篇PWM的文章了_第6张图片

觉得自己再有必要开一篇PWM的文章了_第7张图片

都是一样的思路,一样的道理,可以细细体会下!

3、动态亮度级别控制之水滴低落

#include 

typedef unsigned char u8;

code u8 LightLevel[8]= {0,1,2,4,8,16,32,64}; //亮度等级
code u8 LightTime[16]= {16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};//每一等级持续时间实现加速效果

void CloseFucker();

void main()
{
	u8 i,j,k;
	u8 temp = 0, state, count;
	
	CloseFucker();
	
	P2 = (P2&0x1F) | 0x80;
	P0 = 0xFF;
	P2 = P2&0x1F;
	
	while(1)
	{
		//第一个水滴,逐渐变大!
		for(i=0; i<64; i++)//i控制亮度等级
		{
			for(j=0; j<64; j++)//j控制每个等级的持续时间
			{
				P2 = (P2&0x1F) | 0x80;
				P0 = 0xFE;
				P2 = P2&0x1F;
				
				for(k=0; k<64; k++)//k确定亮度等级
				{
					if(k>i)
					{
						P2 = (P2&0x1F) | 0x80;
						P0 = 0xFF;
						P2 = P2&0x1F;
					}
				}
			}
		}
		
		//流动拖尾实现
		for(state=0; state<16; state++)
		{
			for(count=0; count<=LightTime[state]; count++)
			{//每一状态维持LightTime[state]个脉冲
				for(j=0; j<64; j++)//总脉冲个数,控制总周期
				{
					temp = 0x00;
					for(k=0; k<8; k++)
					{
						if(LightLevel[k] <= j)
						{
							temp |= (1<> (7-state));
						P2 = P2&0x1F;
					}
					else
					{
						P2 = (P2&0x1F) | 0x80;
						P0 = ~((~temp) << (state-7));
						P2 = P2&0x1F;
					}
				}
			}
		}
	}
}

void CloseFucker()
{
	P2 = (P2&0x1F) | 0xA0;
	P0 &= 0xAF;
	P2 = P2&0x1F;
}

emmm,关于这段代码呢,感觉会理解起来比较吃力的是水滴的拖尾过程,不过也没关系,看图吧。

觉得自己再有必要开一篇PWM的文章了_第8张图片

还是挺形象呢!

4、定时器实现静态亮度等级 (一个定时器控制8个IO产生频率相同占空比不同的8路信号!)

上面的实例对于总周期的控制,是通过for循环实现的,显然太不专业了,所以才引入了定时器。

#include 

typedef unsigned char u8;

code u8 LightLevel[8]= {1,2,4,8,16,28,50,64}; 

void Timer0Init();
void CloseFucker();

void main()
{
	EA = 1;
	CloseFucker();
	Timer0Init();
	
	while(1);
}

void CloseFucker()
{
	P2 = (P2&0x1F) | 0xA0;
	P0 &= 0xAF;
	P2 = P2&0x1F;
}

void Timer0Init()		//10微秒@11.0592MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xF7;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
}

void InterruptTimer0() interrupt 1
{
	u8 i, temp = 0;
	static u8 count = 0;
	
	TH0 = 0xFF;
	TL0 = 0xF7;
	count++;
	count %= 64;//确保取值在0-63之间
	
	for(i=0; i<8; i++)
	{
		if(LightLevel[i] <= count)
		{
			temp |= (1<

你可能感兴趣的:(蓝桥杯之单片机)