PWM波控制LED灯的亮暗

在做蓝桥杯第九届省赛题的时候,遇到了这样一个题目:实现4个不同等级的LED亮度分布。PWM波控制LED灯的亮暗_第1张图片

这个要求我们可以联想到第七届的省赛题,控制PWM波的输出,我们在这里也可以应用相同的原理,就是通过定时器来达到LED等不同等级的亮度分布。

目录

原理:

基础程序:

1.问题

2.程序

拓展练习:RB2的电压值控制LED灯的亮暗
 

原理:

假设PWM波的周期是10毫秒,通过短时间的视觉暂留效应,我们用定时器设置一个10毫秒的短周期。在10毫秒内,分出4个不同的区间(2.5毫秒,5毫秒,7.5毫秒,9.9毫秒),将这4个时间作为占空比,正周期内LED灯点亮,反周期内LED灯关闭。

基础程序:

题目:PWM脉冲信号的频率为100HZ,手动更改占空比的初始值,来控制LED灯的亮暗程度。

1.问题

我在写程序的时候,遇到了这样一个问题:LED灯和数码管产生冲突。

之前把数码管的程序写在了主函数的while循环内,LED灯放在了定时器的中断内,这样运行起来二者之间就会产生冲突。所以我把数码管的程序放在了另一个定时器的中断里,这样冲突问题即可解决。

uchar Digcom=0;
uchar Digbuf[8]={1,2,3,4,5,6,7,8};//数码管显示的初始值

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

	ET1=1;EA=1;
}

void timer1int() interrupt 3
{ 
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<

2.程序

频率为100HZ,周期T=10000微秒 (10毫秒),我们用100微秒的定时器0。

在一开始,我们先对占空比的大小(10毫秒内LED灯亮的时间)进行定义;我们更改这个值就可以控制亮暗。

uchar PWM_duty=20;//占空比为2,亮2毫秒

下面就是总程序:

#include 

#define uchar unsigned char
#define uint unsigned int
	
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar one,two,three,four,five,six,seven,eight;
uchar Digcom=0;
uchar Digbuf[8]={1,2,4,3,5,6,7,8};//数码管显示的初始值

uint tt;

uchar PWM_duty=20;//占空比 范围是0-100  周期10毫秒,定时器100微秒;所以是0-100

void Allinit();
void Delayms(uint ms);
void Keyscan();
void Timer0Init(void);		//10微秒@11.0592MHz
void Timer1Init(void);		//1毫秒@11.0592MHz

void main()
{
	Allinit();
	Timer0Init();
	Timer1Init();
	EA=1;
	while(1)
	{
		Keyscan();
	}
}

void timer0() interrupt 1
{
	tt++;
	if(tt==PWM_duty)
	{
	  P2|=0X80;P2&=0X9F;P0=0XFF;//关闭
	}
	else if(tt==100)
	{
		tt=0;
		P2|=0X80;P2&=0X9F;P0=0XFE;//开启
	}
}

void timer1int() interrupt 3
{ 
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<0;i--)
	for(j=845;j>0;j--);
}

拓展练习:RB2的电压值控制LED灯的亮暗

题目:通过读取RB2电压值,分成四个等级,来控制LED灯的亮暗

值得注意的是,LED点亮的程序不能直接赋值了,否则会引起RB2读取电压和定时器的冲突。

经检验,此种方法不会引起蜂鸣器的冲突。

程序如下:

#include 
#include "iic.h"
#include "intrins.h"


#define uchar unsigned char
#define uint unsigned int
	
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar Smg_num=0;
uchar Smg[8]={11,11,11,11,11,11,11,11};

uchar LED_Bit=0XFF;
uchar light=0;
uchar ad=0;
uint tt=0;

void Allinit();
void Delayms(uint ms);
void Timer0Init(void);		//1毫秒@11.0592MHz
void Timer2Init(void);		//1毫秒@11.0592MHz

void main()
{
	Allinit();
	Timer0Init();		
	Timer2Init();	
	while(1)
	{
		ad=AD_read(0X03);
		
		if(ad<64)light=1;
		else if((ad>=64)&&(ad<128))light=2;
		else if((ad>=128)&&(ad<192))light=3;
		else if(ad>=192)light=4;
		
		Smg[0]=light;
	}
}

void timer0() interrupt 1
{
	tt++;
	
	if(light==1)
	{
		if(tt==20)
		{
			P2|=0X80;P2&=0X9F;LED_Bit|=0X01;P0=LED_Bit;
		}
		else if(tt==100)
		{
			tt=0;
			P2|=0X80;P2&=0X9F;LED_Bit&=0XFE;P0=LED_Bit;
		}
	}
	else if(light==2)
	{
		if(tt==50)
		{
			P2|=0X80;P2&=0X9F;LED_Bit|=0X01;P0=LED_Bit;
		}
		else if(tt==100)
		{
			tt=0;
			P2|=0X80;P2&=0X9F;LED_Bit&=0XFE;P0=LED_Bit;
		}
	}
	else if(light==3)
	{
		if(tt==75)
		{
			P2|=0X80;P2&=0X9F;LED_Bit|=0X01;P0=LED_Bit;
		}
		else if(tt==100)
		{
			tt=0;
			P2|=0X80;P2&=0X9F;LED_Bit&=0XFE;P0=LED_Bit;
		}
	}
	else if(light==4)
	{
		if(tt==100)
		{
			tt=0;
			P2|=0X80;P2&=0X9F;LED_Bit&=0XFE;P0=LED_Bit;
		}
	}
}

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

	ET0=1;EA=1;
}

void timer2() interrupt 12
{
	P2|=0XC0;
	P2&=0XDF;
	P0=(1<0;i--)
	for(j=845;j>0;j--);
}

iic.c的程序如下:

#include "iic.h"
#include 
#include "intrins.h"

#define uchar unsigned char
#define DELAY_TIME 40

sbit SDA = P2^1;
sbit SCL = P2^0;

//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//I2C总线启动信号
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//I2C总线停止信号
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答或非应答信号
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//I2C总线发送一个字节数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//I2C总线接收一个字节数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

uchar AD_read(uchar add)
{
	uchar temp;
	
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0X91);
	IIC_WaitAck();	
	temp=IIC_RecByte();
	IIC_Stop();
	
	return temp;
}

uchar EEPROM_read(uchar add)
{
	uchar temp;
	
	IIC_Start();
	IIC_SendByte(0XA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0XA1);
	IIC_WaitAck();	
	temp=IIC_RecByte();
	IIC_Stop();
	
	return temp;
}

void EEPROM_write(uchar add,uchar dat)// EEEPROM 存储
{
	IIC_Start();
	IIC_SendByte(0XA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

void DA_write(uchar dat)// DA 输出电压(让板子显示你想让它显示的电压)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

iic.h的程序如下:

#ifndef _IIC_H
#define _IIC_H

#include 
#include "intrins.h"

#define uchar unsigned char

//sbit SDA = P2^1;
//sbit SCL = P2^0;

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
uchar AD_read(uchar add);
uchar EEPROM_read(uchar add);
void EEPROM_write(uchar add,uchar dat);
void DA_write(uchar dat);

#endif

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