蓝桥杯单片机--第九届省赛--彩灯控制器

本文详细展示了使用STC15单片机控制LED灯的代码,包括定时器配置、ADC读取、数码管操作和按键处理。代码实现了基本的功能,但结构复杂,寻求改进意见。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:代码展示

#include "stc15.h"
#include "intrins.h"
#include "iic.h"
#include "Display.h"

sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;

unsigned char ADC_num;
u8 mode=0;
u8 mode_set=0;
bit lz=0;  //0:启动流转 1:停止流转
u16 lztime1=400,lztime2=400,lztime3=400,lztime4=400;  //400ms-1200ms
u8 lztime_h[4],lztime_l[4];
u16 lztime;
u16 lztime_set;
u8 jiemian=0;  //0:熄灭数码管 1:设置界面 2:亮度界面
bit temp=0;  //0:设置运行模式 1:设置流转间隔
u8 liangdu=0;  //亮度等级
u8 liangdu_set=1;
u8 Key_Slow_Flag,Data_Slow_Flag,Smg_Slow_Flag,Led_Slow_Flag;
u8 led=0xFF;
u8 count=0;
bit shanshuo=0;  //数码管闪烁标志
u8 zkb=0;  //pwm占空比
u8 i1=0;
u8 i2=0;
u8 i3=0;
u8 i4=0;

void Key_Proc(void);
void Data_Proc(void);
void Smg_Proc(void);
void Led_Proc(void);
void LedDisplay(u8 LED);

void Delay2ms(void)	//@12.000MHz
{
	unsigned char data i, j;

	i = 24;
	j = 85;
	do
	{
		while (--j);
	} while (--i);
}

void Timer0_Init(void)		//2毫秒@12.000MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x40;				//设置定时初始值
	TH0 = 0xA2;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
    ET0=1;
    EA=1;
}

void Timer1_Init(void)		//100微秒@12.000MHz
{
	AUXR |= 0x40;			//定时器时钟1T模式
	TMOD &= 0x0F;			//设置定时器模式
	TL1 = 0x50;				//设置定时初始值
	TH1 = 0xFB;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
    ET1=1;
    EA=1;
}

void Init(u8 i)
{
    P2&=0x1F;
    switch(i)
    {
        case 4:P0=0xFF;HC138(i);P2&=0x1F;P0=0x00;break;
        case 5:HC138(i);break;
        case 6:HC138(i);break;
        case 7:P2&=0x1F;P0=0xFF;HC138(i);break;
    }
    P2&=0x1F;
}

void main(void)
{
    u8 i;
    Init(4);
    Init(5);
    Init(6);
    Init(7);
    AT24C02_Read(lztime_h,lztime_l,0,4);  //每次上电读取LED流转时间
    for(i=0;i<4;i++)
    {
        if(((lztime_h[i]<<8)|lztime_l[i])>=400&&((lztime_h[i]<<8)|lztime_l[i])<=1200)
        {
        }
        else
            break;
    }
    if(i==4)
    {
        lztime1=(lztime_h[0]<<8)|lztime_l[0];
        lztime2=(lztime_h[1]<<8)|lztime_l[1];
        lztime3=(lztime_h[2]<<8)|lztime_l[2];
        lztime4=(lztime_h[3]<<8)|lztime_l[3];
    }
    lztime=lztime1;
    lztime_set=lztime;
    Timer0_Init();
    Timer1_Init();
    while(1)
    {
        Key_Proc();
        Data_Proc();
        Smg_Proc();
        Led_Proc();
    }
}

void Timer0(void) interrupt 1
{
    static u16 i=0;
    if(++Key_Slow_Flag==5) Key_Slow_Flag=0;
    if(++Data_Slow_Flag==100) Data_Slow_Flag=0;
    if(++Smg_Slow_Flag==100) Smg_Slow_Flag=0;
    if(++Led_Slow_Flag==lztime/2) Led_Slow_Flag=0;

    i++;
    if(i==400)
    {
        shanshuo=~shanshuo;  //当处于设置界面时选中的模式或流转时间设置每隔0.8秒闪烁
        i=0;
    }
    SmgDisplay();
    LedDisplay(led);
}

void Timer1(void) interrupt 3  //pwm控制LED四个亮度等级
{
    static u8 cnt=0;
    cnt++;
    led=0xFF;
    if(cnt<=zkb)
    {
        if(mode==0)
        {
            led=led&(~(1<<i1));
        }
        else if(mode==1)
        {
            led=led&(~(0x80>>i2));
        }
        else if(mode==2)
        {
            led=led&(~(0x80>>i3));
            led=led&(~(1<<i3));
        }
        else if(mode==3)
        {
            led=led&(~(0x10<<i4));
            led=led&(~(0x08>>i4));
        }
    }
    else if(cnt>zkb)
    {
        if(mode==0)
        {
            led=led|(1<<i1);
        }
        else if(mode==1)
        {
            led=led|(0x80>>i2);
        }
        else if(mode==2)
        {
            led=led|(0x80>>i3);
            led=led|(1<<i3);
        }
        else if(mode==3)
        {
            led=led|(0x10<<i4);
            led=led|(0x08>>i4);
        }
    }
    if(cnt>99)
        cnt=0;
    
}

void Key_Proc(void)
{
    if(Key_Slow_Flag) return;
    Key_Slow_Flag=1;
    
    if(S7==0)  //控制是否启动流转
    {
        Delay2ms();
        if(S7==0)
        {
            lz=~lz;
            while(1)
            {
                if(S7==1)
                {
                    Delay2ms();
                    if(S7==1)
                        break;
                }
            }
        }
    }
    else if(S6==0)
    {
        Delay2ms();
        if(S6==0)
        {
            count++;
            if(count==1)  //S6按下一次进入界面1且选中模式设置
            {
                jiemian=1;
                temp=0;
            }
            else if(count==2) //S6按下两次进入界面1且选中流转时间设置
            {
                jiemian=1;
                temp=1;
            }
            else  //再次按下数码管熄灭,将设置的模式及流转时间赋值
            {
                jiemian=0;
                mode=mode_set;
                switch(mode)
                {
                    case 0:lztime1=lztime_set;lztime=lztime1;break;
                    case 1:lztime2=lztime_set;lztime=lztime2;break;
                    case 2:lztime3=lztime_set;lztime=lztime3;break;
                    case 3:lztime4=lztime_set;lztime=lztime4;break;
                }
                count=0;
            }
            while(1)
            {
                if(S6==1)
                {
                    Delay2ms();
                    if(S6==1)
                        break;
                }
            }
        }
    }
    else if(S5==0&&jiemian==1)  
    {
        Delay2ms();
        if(S5==0)
        {
            if(temp==0)
            {
                if(mode_set<=2)
                    mode_set++;
            }
            else if(temp==1)
            {
                if(lztime_set<=1100)
                    lztime_set+=100;
            }
            while(1)
            {
                if(S5==1)
                {
                    Delay2ms();
                    if(S5==1)
                        break;
                }
            }
        }
    }
    else if(S4==0&&jiemian==1)
    {
        Delay2ms();
        if(S4==0)
        {
            if(temp==0)
            {
                if(mode_set>=1)
                    mode_set--;
            }
            else if(temp==1)
            {
                if(lztime_set>=500)
                    lztime_set-=100;
            }
            while(1)
            {
                if(S4==1)
                {
                    Delay2ms();
                    if(S4==1)
                        break;
                }
            }
        }
    }
    if(S4==0&&jiemian!=1)
    {
        Delay2ms();
        if(S4==0)
        {
            jiemian=2;
        }
    }
    else if(S4==1&&jiemian==2)
    {
        Delay2ms();
        if(S4==1)
        {
            jiemian=0;
        }
    }
}

void Data_Proc(void)
{
    if(Data_Slow_Flag) return;
    Data_Slow_Flag=1;
    
    if(jiemian!=1)  //当不处于设置界面时将流转时间写入EEPROM
    {
        lztime_h[0]=lztime1>>8;
        lztime_h[1]=lztime2>>8;
        lztime_h[2]=lztime3>>8;
        lztime_h[3]=lztime4>>8;
        
        lztime_l[0]=lztime1;
        lztime_l[1]=lztime2;
        lztime_l[2]=lztime3;
        lztime_l[3]=lztime4;
        
        AT24C02_Write(lztime_h,lztime_l,0,4);
    }
    
    AD_Trans();
    if(ADC_num>=0&&ADC_num<64)  //通过Rb2通过占空比不同设置四个亮度等级
    {
        liangdu_set=1;
        zkb=25;
    }
    else if(ADC_num>=64&&ADC_num<128)
    {
        liangdu_set=2;
        zkb=50;
    }
    else if(ADC_num>=128&&ADC_num<192)
    {
        liangdu_set=3;
        zkb=75;
    }
    else if(ADC_num>=192&&ADC_num<=255)
    {
        liangdu_set=4;
        zkb=100;
    }
}

void Smg_Proc(void)
{
    if(Smg_Slow_Flag) return;
    Smg_Slow_Flag=1;
    
    if(jiemian==0)
        SmgOff();
    else if(jiemian==1)
        ConfigDisplay();
    else if(jiemian==2)
        LiangduDisplay();
}

void Led_Proc(void)
{
    if(Led_Slow_Flag) return;
    Led_Slow_Flag=1;
    if(mode==0&&lz==0)  
    {
        i1++;
        if(i1==8)
            i1=0;
    }
    else if(mode==1&&lz==0)
    {
        i2++;
        if(i2==8)
            i2=0;
    }
    else if(mode==2&&lz==0)
    {
        i3++;
        if(i3==4)
            i3=0;
    }
    else if(mode==3&&lz==0)
    {
        i4++;
        if(i4==4)
            i4=0;
    }
}

void LedDisplay(u8 LED)
{
    HC138(4);
    P0=LED;
    P2&=0x1F;
}


二、总结

     本代码基本上实现了彩灯控制器的所有功能,但代码有点繁杂,希望大家可以给出改进建议,共同进步!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值