蓝桥杯单片机(六)PWM

本文内出现的函数在其他文章有讲:
蓝桥杯单片机(一)流水灯
蓝桥杯单片机(二)独立按键
蓝桥杯单片机(四)动态数码管
蓝桥杯单片机(五)定时器

蓝桥杯单片机(六)PWM_第1张图片
如图所示,有三列方波在图中,所谓PWM,就是指上述图中的方波,波形在高电平和低电平不断变化,只不过PWM的占空比可变,上图就是三种不同占空比的方波,所谓占空比就是,占空比=高电平的时间/周期的时间。
这次我们用单片机来模拟PWM输出:

#include 
#include "intrins.h"

void PWM(void);
void Delay1ms(void);

void main(void)
{
	while(1)
	{
	
	}
}

void PWM(void)
{
	P0=0X01;
	Delay1ms();
	P0=0X00;
	Delay1ms();
}

void Delay1ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}

我们让P00首先在高电平持续1ms,然后低电平持续1ms,不断循环,这就是一个占空比为50%的PWM波,有示波器可以拿示波器观察P00口波形。当然也可以用定时器来控制P00的输出,使PWM更加准确。
由于我没有示波器,所以采用PWM控制LED亮度来进行实验。
实验内容:通过按键控制PWM占空比控制LED亮度,数码管显示PWM占空比
程序如下:

#include
#include"intrins.h"

#define uchar unsigned char
#define uint unsigned int
	

void init(void);
void Delay5ms(void);
void Timer0Init(void);
void Timer1Init(void);
void Dkey_scan(void);

uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar SMG[8]={10,10,10,10,10,10,10,10};//初始显示10,全息数码管

char duty=50;
uchar num=5;
uchar LED=0xff;
uint t=0;

void main(void)
{
//初始化开发板,定时器0,定时器1
	init();
	Timer0Init();
	Timer1Init();
	EA=1;ET0=1;ET1=1;
	while(1)
	{		
		if(duty<100)
		{
			SMG[0]=SMG[1]=SMG[2]=SMG[3]=SMG[4]=10;
			SMG[5]=10;
			SMG[6]=duty/10;
			SMG[7]=duty%10;		
		}
		else
		{
			SMG[0]=SMG[1]=SMG[2]=SMG[3]=SMG[4]=10;
			SMG[5]=duty/100;
			SMG[6]=duty%100/10;
			SMG[7]=duty%10;				
		}
		Dkey_scan();
		P2=0X80;P0=LED;
	}
}

//定时器1中断服务函数,输出PWM
void time1() interrupt 3
{
	t++;
	if(t<((20*duty)/100))
	{
		LED |=0x01;
	}
	else if(t<20)
	{
		LED &=0xFE;
	}
	else
	{
		t=0;
	}
}
//定时器0显示数码管
void SMG_output() interrupt 1
{
	P2=(P2&0X1F)|0Xc0;
	P0=(1<<num);
	P2=(P2&0X1F)|0Xe0;
	P0=tab[SMG[num]];
	if(++num==8)num=5;	
}
//按键扫描程序
void Dkey_scan(void)
{
	static unsigned char keybyte=0;
	static unsigned char key;
	if(((P3&0X0F)!=0X0F)&&(keybyte==0))
	{
		Delay5ms();
		if((P3&0X0F)!=0X0F)
		{
			keybyte=1;key=P3&0x0f;
		}
	}
	if((keybyte==1)&&((P3&0X0F)==0X0F))
	{
		Delay5ms();
		if((P3&0X0F)==0X0F)
		{
			switch(key)
			{
				case 0x0e:
					duty -=10;
					if(duty<0) duty=0;
				break;
				
				case 0x0d:
					duty +=10;
					if(duty>100) duty=100;
				break;
			}
			keybyte=0;
		}
	}
}

void Timer0Init(void)		//500微秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xEA;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void Timer1Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0xCD;		//设置定时初值
	TH1 = 0xD4;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
}

void init(void)
{
	P2=(P2&0X1F)|0XA0;
	P0=0X00;
	P2=(P2&0X1F)|0X80;
	P0=0Xff;
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

最后效果如图:

可以看见LED逐渐变亮
有问题可以评论和私信

你可能感兴趣的:(单片机,蓝桥杯,嵌入式硬件)