蓝桥杯第9届彩灯控制器

LED流水灯不同模式的控制,有四个模式,四个亮度等级,每个模式有不同的流转速度和规则。把亮度的pwm调节放在定时器里,pwm的高电平下判断是哪种模式,在每个模式里设不同的计时变量(计流转间隔)和计次变量(例如模式一LED有八个状态,计到8次后改变模式),时间到了就改变要亮的LED,计次数到了就改变模式。把给P0口赋值放在计时的if外面,这样每次在pwm代码里会给P0口赋值,但时间到了才改变LED状态;

完整代码

#include <STC15F2K60S2.H>
#include "iic.h"

typedef unsigned char u8;
unsigned char code smg_code[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x76,0x79,0x38};	//共阴数码管码表
unsigned char smg[8];
typedef struct
{
	u8 b1:1;
	u8 b2:1;
	u8 b3:1;
	u8 b4:1;
	u8 b5:1;
	u8 b6:1;
	u8 b7:1;
	u8 b8:1;
}bits;

typedef union 
{
	unsigned char Hex;
	bits b;
}HexToBits;

HexToBits led_ctrl;

void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
	P0 = p0dat;
	P2 = (P2&0x1f)|p2dat;
	P2 = (P2&0x1f)|0x00;
}
//定时器2
void Timer2Init(void)		//10us@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x88;		//设置定时初值
	T2H = 0xFF;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	
	EA = 1;
	IE2 |= 0x04;
}
//定时器0
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0 = 1;
}

//彩灯四个模式
unsigned int speed[4]={400,400,400,400};//初始化400ms
unsigned char mode=1;
unsigned char level=1;//亮度等级
unsigned int pwm=25;//pwm调整亮度
unsigned int cnt_pwm;//pwm计时 100ms
unsigned char i1=0,i2=0,i3=0,i4=0;	
//模式1
unsigned int cnt_led;
void led_mode1()
{

	if(cnt_led>=speed[0])
	{
		cnt_led=0;
		led_ctrl.Hex = ~((led_ctrl.Hex|0xff)&(0x01<<i1));
		if(i1==8)
		{
			mode++;
			i1=0; //必须要全部i清零,因为下面有i++;第二次循环时会等于1
			i2=0;
			i3=0;
			i4=0;
		}
		i1++;
	}
	vDevice_Process(0x80, led_ctrl.Hex);
}

//模式2
void led_mode2()
{
	if(cnt_led>=speed[1])
	{
		cnt_led=0;
		led_ctrl.Hex = ~((led_ctrl.Hex|0xff)&(0x80>>i2));
		if(i2==8)
		{
			mode++;
			i1=0;
			i2=0;
			i3=0;
			i4=0;
		}
		i2++;
	}
	vDevice_Process(0x80, led_ctrl.Hex);
}

//模式3
void led_mode3()
{
	if(cnt_led>=speed[2])
	{
		cnt_led=0;
		led_ctrl.Hex=0xff;
		switch(i3)
		{
			case 0:
				led_ctrl.b.b1=0;
				led_ctrl.b.b8=0;
			break;
			case 1:
				led_ctrl.b.b2=0;
				led_ctrl.b.b7=0;
			break;
			case 2:
				led_ctrl.b.b3=0;
				led_ctrl.b.b6=0;
			break;
			case 3:
				led_ctrl.b.b4=0;
				led_ctrl.b.b5=0;
			break;
			case 4:
				mode++;
				i1=0;
				i2=0;
				i3=0;
				i4=0;
			break;
		}
		i3++;
	}
	vDevice_Process(0x80, led_ctrl.Hex);
}

//模式4
void led_mode4()
{
	if(cnt_led>=speed[3])
	{
		cnt_led=0;
		led_ctrl.Hex=0xff;
		switch(i4)
		{
			case 0:
				led_ctrl.b.b4=0;
				led_ctrl.b.b5=0;
			break;
			case 1:
				led_ctrl.b.b3=0;
				led_ctrl.b.b6=0;
			break;
			case 2:
				led_ctrl.b.b2=0;
				led_ctrl.b.b7=0;
			break;
			case 3:
				led_ctrl.b.b1=0;
				led_ctrl.b.b8=0;
			break;
			case 4:
				mode=1;
				i1=0;
				i2=0;
				i3=0;
				i4=0;	
			break;
		}
		i4++;
	}
	vDevice_Process(0x80, led_ctrl.Hex);
}

//读取rb2电压
unsigned char rb2_dat;
unsigned int cnt_rb2;
void Read_u2()
{
	if(cnt_rb2>=10)//10ms读取一次电压
	{
		cnt_rb2=0;
		EA=0;
		rb2_dat=Read_rb2();  //0~255
		EA=1;
		if(rb2_dat<=64)
		{
			pwm=25;
			level=1;
		}
		else if(rb2_dat<=128)
		{
			pwm=50;
			level=2;
		}
		else if(rb2_dat<=192)
		{
			pwm=75;
			level=3;
		}
		else if(rb2_dat<=255)
		{
			pwm=100;
			level=4;
		}
	}
}

//数码管操作
unsigned char mode_set=0;//0非设置,1设置模式,2设置流转间隔
unsigned int cnt_smg; //闪烁
unsigned char mode_s=1;
void SMG_Process()
{
	if(mode_set==0)
	{
		smg[0] = 0x00;
		smg[1] = 0x00;
		smg[2] = 0x00;
		smg[3] = 0x00;
		smg[4] = 0x00;
		smg[5] = 0x00;
		smg[6] = 0x00;
		smg[7] = 0x00;
	}
	if(mode_set==1)
	{
		smg[0] = 0x40;
		if(cnt_smg<=800)
		{
			smg[1] = smg_code[mode_s];
		}
		else if(cnt_smg<=1600)
		{
			smg[1] = 0x00;
		}
		else
		{
			cnt_smg=0;
		}
		smg[2] = 0x40;
		smg[3] = 0x00;
		if(speed[mode_s-1]>999)smg[4] = smg_code[speed[mode_s-1]/1000];
		else smg[4] = 0x00;
		smg[5] = smg_code[speed[mode_s-1]/100%10];
		smg[6] = smg_code[speed[mode_s-1]/10%10];
		smg[7] = smg_code[speed[mode_s-1]%10];
	}
	
	if(mode_set==2)
	{
		smg[0] = 0x40;
		smg[1] = smg_code[mode_s];
		smg[2] = 0x40;
		smg[3] = 0x00;
		
		if(cnt_smg<=800)
		{
			if(speed[mode_s-1]>999)smg[4] = smg_code[speed[mode_s-1]/1000];
			else smg[4] = 0x00;
			smg[5] = smg_code[speed[mode_s-1]/100%10];
			smg[6] = smg_code[speed[mode_s-1]/10%10];
			smg[7] = smg_code[speed[mode_s-1]%10];
		}
		else if(cnt_smg<=1600)
		{
			smg[4] = 0x00;
			smg[5] = 0x00;
			smg[6] = 0x00;
			smg[7] = 0x00;
		}
		else
		{
			cnt_smg=0;
		}
	}
	
	if(mode_set==3)//显示亮度等级
	{
		smg[0] = 0x00;
		smg[1] = 0x00;
		smg[2] = 0x00;
		smg[3] = 0x00;
		smg[4] = 0x00;
		smg[5] = 0x00;
		smg[6] = 0x40;
		smg[7] = smg_code[level];
	}
	
}

//数码管显示
void SMG_Show()
{
	static unsigned char i=0;
	vDevice_Process(0xc0, 0x00);
	vDevice_Process(0xe0, ~smg[i]);
	vDevice_Process(0xc0, 0x01<<i);
	i=(i+1)%8;
}

//按键
unsigned char Trg,Cont;
void Three_Key()
{
	unsigned char ReadData = P3^0xff;
	Trg = ReadData&(ReadData^Cont);
	Cont = ReadData;
}

//按键判断
unsigned int cnt_key; 
bit led_open=1;

void Keys()
{
	if(cnt_key>=10)
	{
		cnt_key=0;
		Three_Key();
		if(Trg&0x01)//S7
		{
			led_open=!led_open;
			mode=1;
			led_ctrl.Hex=0xff;
			vDevice_Process(0x80, 0xff);
		}
		if(Trg&0x02)//S6
		{
			mode_set++;
			if(mode_set==3)
			{
				mode_set=0;
				Write_eeprom(0x01,speed[0]/10); //保存参数 是int型的
				Write_eeprom(0x03,speed[1]/10);
				Write_eeprom(0x05,speed[2]/10);
				Write_eeprom(0x07,speed[3]/10);
			}
			if(mode_set==3)
			{
				
			}
		}
		if(Trg&0x04)//S5
		{	
			if(mode_set==1)
			{
				if(mode_s<4)mode_s++;
			}
			if(mode_set==2)
			{
				if(speed[mode_s-1]<1200)
				{
					speed[mode_s-1]=speed[mode_s-1]+100;
				}		
			}
		}
		if(Trg&0x08)//S4
		{
			if(mode_set==1)
			{
				if(mode_s>1)mode_s--;
			}
			if(mode_set==2)
			{
				if(speed[mode_s-1]>400)
				speed[mode_s-1]=speed[mode_s-1]-100;
			}
		}		
		if(Cont&0x08) //长按s4
		{
			if(mode_set==0)
			{
				mode_set=3;
			}
		}
		else
		{
			if(mode_set==3)
			{
				mode_set=0;
			}
		}
	}
}
void System_init()
{
	led_ctrl.Hex=0xff;
	vDevice_Process(0x80, 0xff);
	vDevice_Process(0xa0, 0x00);
	
	speed[0] = (Read_eeprom(0x01)<<8)+Read_eeprom(0x02);
	speed[1] = (Read_eeprom(0x03)<<8)+Read_eeprom(0x04);
	speed[2] = (Read_eeprom(0x05)<<8)+Read_eeprom(0x06);
	speed[3] = (Read_eeprom(0x07)<<8)+Read_eeprom(0x08);

	if((speed[0]<400)|(speed[0]>1200))speed[0]=400;
	if((speed[1]<400)|(speed[1]>1200))speed[1]=400;
	if((speed[2]<400)|(speed[2]>1200))speed[2]=400;
	if((speed[3]<400)|(speed[3]>1200))speed[3]=400;
}

void main()
{
	System_init();
	Timer2Init();
	Timer0Init();
	while(1)
	{
		Read_u2();	
		SMG_Process();
		Keys();
	}
}



void Timer2() interrupt 12
{
	cnt_pwm++;
	if(led_open==1)
	{
		if(cnt_pwm<=pwm)
		{
			switch(mode)
			{
				case 1:
					led_mode1();
				break;
				case 2:
					led_mode2();
				break;
				case 3:
					led_mode3();
				break;
				case 4:
					led_mode4();
				break;
			}		
		}
		else if(cnt_pwm<=100)
		{
			vDevice_Process(0x80, 0xff);
		}
		else
		{
			switch(mode)
			{
				case 1:
					led_mode1();
				break;
				case 2:
					led_mode2();
				break;
				case 3:
					led_mode3();
				break;
				case 4:
					led_mode4();
				break;
			}
			cnt_pwm=0;
		}
	}
}

void Timer0() interrupt 1
{
	cnt_led++;
	cnt_rb2++;
	cnt_key++;
	if(mode_set!=0)cnt_smg++;
	SMG_Show();
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值