第九届蓝桥杯 模拟彩虹灯系统

【冉冰的成长日记003】
课设耽误的,可不怪我咕!!

先说程序的问题,我感觉不到那个亮度等级变化的区别,好似有又好似没有0.0。。。。。
第二,按键的刷新和LED模块有冲突,需要长按按键才好使。。。

其他没啥了,,,就这样吧

看看代码吧,据说分块写也并不能使变量增加,我就还是写到一个main.c里了,不要跟我学,hhhh

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

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

unsigned char code LED[]={
    
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xBF ,0xFF ,0xC6};//数码管
unsigned char LEDbuff[] = {
    
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; //数码管缓冲区

unsigned char code LED_M1[]={
    
    0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
unsigned char code LED_M2[]={
    
    0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
unsigned char code LED_M3[]={
    
    0x7E, 0xBD, 0xDB, 0xE7};
unsigned char code LED_M4[]={
    
    0xE7, 0xDB, 0xBD, 0x7E};

unsigned int cnt=0,num=0,clock=0;//中断计时
unsigned char AD=0,PWM_flag=0;//AD获取模拟量,PWM_flag用于亮度显示 
unsigned int EEPROM,EEPROM_flag=6;//EEPROM用于设置流转时间间隔
bit S7_start=0,S7_LED=0;//S7_LED停止和启动led	,S7_start用于数码管启动
unsigned char S6_M=1,S6_flag=0; // S6_M模式切换模式,S6_flag用于切换运行和间隔两个单元
bit check_S7=0,check_S6=0,check_S5=0,check_S4=0,Fl=0;//check用来按键消抖,Fl用来选中是以0.8s闪烁

void Timer0Init();	//定时器0,1ms
void Initial();		//模块初始化
void KEY();			//按键模块,包括S7.S6.S5.S4
void Display_3();		//数码管模块
void delay(unsigned int x);	  //延时函数
void Get();	   //每次上电后读取EEPROM内的数据,判断是否在4-12之间,如果在就不需要改变,如果不在默认重装初值为4,,
//我觉得这个思想好厉害,20级的大佬讲给我听的(p.s.:其实是大四的学长讲给他听的)
void LED_1();//彩虹灯的四种模式

void main()
{
    
    
	Timer0Init();
	Initial();	 //初始化函数
	AD_Init();	 //AD初始化
	Get();
	while(1)
	{
    
    
		delay(5);
		EEPROM_Write(0x01,EEPROM_flag);				 //将每次变化后的值再写入EEPROM内
		if(clock>=500)
		{
    
    
			AD=AD_Get();						   //AD值读取
			clock=0;
		}
		KEY();
		Display_3();
		LED_1();					 
	}
}

void delay(unsigned int x)			 //延时函数,ms单位
{
    
    
	int X=0,Y=0;
	for(X=0;X<x;X++)
	{
    
    
		for(Y=846;Y>0;Y--);
	}
		
}

void Get()
{
    
    
	EEPROM_flag = EEPROM_Get(0x01);
	if(EEPROM_flag<=4||EEPROM_flag>=12)	EEPROM_flag=4;
}

void Initial()		//初始化函数
{
    
    
	P2 = (P2&0x1F)|0x80;
	P0 = 0xFF;		//初始化LED

	P2 = (P2&0x1F)|0xA0;
	P0 = 0x00;		//初始化继电器和蜂鸣器

	P2 = (P2&0x1F)|0xC0;
	P0 = 0xFF;
	P2 = (P2&0x1F)|0xE0;
	P0 = 0xFF;      //初始化数码管
}

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

void Display_1()		 //把数码管拆成前四位和后四位,方便管理
{
    
    
	LEDbuff[7] = LED[10];
	LEDbuff[6] = LED[S6_M];
	LEDbuff[5] = LED[10];
	LEDbuff[4] = LED[11];
}

void Display_2()
{
    
    
 	if(EEPROM/1000==0)	LEDbuff[3] = LED[11];
	else	LEDbuff[3] = LED[EEPROM/1000];
	LEDbuff[2] = LED[EEPROM/100%10];
	LEDbuff[1] = LED[EEPROM/10%10];
	LEDbuff[0] = LED[EEPROM%10];		
}

void LED_1()		   //写成for语句和按键冲突,只好改变成switch语句了,即便如此,按键也需要长按才能百分百起作用
{
    
    
	static unsigned char j=0;
	if(S6_M==1&&S7_LED==1)
	{
    
    
		switch(j)
		{
    
    
			case 0:P2 = 0x80;P0 = LED_M1[0];j++;delay(EEPROM);break;
			case 1:P2 = 0x80;P0 = LED_M1[1];j++;delay(EEPROM);break;
			case 2:P2 = 0x80;P0 = LED_M1[2];j++;delay(EEPROM);break;
			case 3:P2 = 0x80;P0 = LED_M1[3];j++;delay(EEPROM);break;
			case 4:P2 = 0x80;P0 = LED_M1[4];j++;delay(EEPROM);break;
			case 5:P2 = 0x80;P0 = LED_M1[5];j++;delay(EEPROM);break;
			case 6:P2 = 0x80;P0 = LED_M1[6];j++;delay(EEPROM);break;
			case 7:P2 = 0x80;P0 = LED_M1[7];j=0;delay(EEPROM);break;
			default : break;
		}
	}

	if(S6_M==2&&S7_LED==1)
	{
    
    
		switch(j)
		{
    
    
			case 0:P2 = 0x80;P0 = LED_M2[0];j++;delay(EEPROM);break;
			case 1:P2 = 0x80;P0 = LED_M2[1];j++;delay(EEPROM);break;
			case 2:P2 = 0x80;P0 = LED_M2[2];j++;delay(EEPROM);break;
			case 3:P2 = 0x80;P0 = LED_M2[3];j++;delay(EEPROM);break;
			case 4:P2 = 0x80;P0 = LED_M2[4];j++;delay(EEPROM);break;
			case 5:P2 = 0x80;P0 = LED_M2[5];j++;delay(EEPROM);break;
			case 6:P2 = 0x80;P0 = LED_M2[6];j++;delay(EEPROM);break;
			case 7:P2 = 0x80;P0 = LED_M2[7];j=0;delay(EEPROM);break;
			default : break;
		}
	}

	if(S6_M==3&&S7_LED==1)
	{
    
    
		if(j>=4)	j =0;
		switch(j)
		{
    
    
			case 0:P2 = 0x80;P0 = LED_M3[0];j++;delay(EEPROM);break;
			case 1:P2 = 0x80;P0 = LED_M3[1];j++;delay(EEPROM);break;
			case 2:P2 = 0x80;P0 = LED_M3[2];j++;delay(EEPROM);break;
			case 3:P2 = 0x80;P0 = LED_M3[3];j=0;delay(EEPROM);break;
			default : break;
		}
	}

	if(S6_M==4&&S7_LED==1)
	{
    
    
		if(j>=4)	j =0;
		switch(j)
		{
    
    
			case 0:P2 = 0x80;P0 = LED_M4[0];j++;delay(EEPROM);break;
			case 1:P2 = 0x80;P0 = LED_M4[1];j++;delay(EEPROM);break;
			case 2:P2 = 0x80;P0 = LED_M4[2];j++;delay(EEPROM);break;
			case 3:P2 = 0x80;P0 = LED_M4[3];j=0;delay(EEPROM);break;
			default : break;
		}
	}

	if(S7_LED==0)
	{
    
    
	  P2 = (P2&0x1F)|0x80;	P0 = 0xFF;
	}
}

void Display_1_2()			   //数码管闪烁时的灭的状态
{
    
    
    LEDbuff[7] = LED[11];
	LEDbuff[6] = LED[11];
	LEDbuff[5] = LED[11];
	LEDbuff[4] = LED[11];
}

void Display_2_2()			   //数码管闪烁时的灭的状态
{
    
    							 
	LEDbuff[3] = LED[11];
	LEDbuff[2] = LED[11];
	LEDbuff[1] = LED[11];
	LEDbuff[0] = LED[11];
}

void Display_PWM()				//S4按键按下时的亮度等级
{
    
    
	LEDbuff[1] = LED[10];
	LEDbuff[0] = LED[PWM_flag];	
}
void Display_3()
{
    
    
	if(S7_start==1&&S6_flag==0)	{
    
    Display_1();Display_2();}
	if(S7_start==1&&S6_flag==1)  {
    
    Display_1_2();Display_2_2();}
	if(S7_start==1&&S6_flag==2)	
	{
    
    
		if(Fl==0)   {
    
    Display_1();Display_2();}
		if(Fl==1)	{
    
    Display_1_2();Display_2();}
	}
	if(S7_start==1&&S6_flag==3)
	{
    
    
		if(Fl==0)   {
    
    Display_1();Display_2();}
		if(Fl==1)	{
    
    Display_1();Display_2_2();}
	}
}

void KEY_S7()
{
    
    
	if(S7==0)
	{
    
    
		delay(5);
		if(S7==0)
			check_S7=1;
	}
	if((S7==1)&&(check_S7==1))
	{
    
    
		check_S7 = 0;
		S7_start = 1;
		S7_LED = ~S7_LED;	
	}	
}

void KEY_S6()
{
    
    
	if(S6==0)
	{
    
    
		delay(5);
		if(S6==0)
			check_S6=1;
	}
	if((S6==1)&&(check_S6==1))
	{
    
    
		check_S6=0;
		S6_flag++;
		if(S6_flag>=4)
			S6_flag=0;	
	}
}

void KEY_S5()
{
    
    
	if(S5==0)
	{
    
    
		delay(5);
		if(S5==0)
			check_S5=1;
	}
	if((S5==1)&&(check_S5==1))
	{
    
    
		check_S5=0;
		if(S6_flag==2)
		{
    
    
			S6_M++;
			if(S6_M>=5)
				S6_M=1;
		}
		if(S6_flag==3)
		{
    
    
			EEPROM_flag++;
			if(EEPROM_flag>=13)
				EEPROM_flag=4;
		}
	}	
}

void KEY_S4()
{
    
    
	if(S4==0)
	{
    
    
		delay(5);
		if(S4==0)
			check_S4=1;
	}
	if((S4==1)&&(check_S4==1))
	{
    
    
		check_S4=0;S7_start=1;
		if(S6_flag==2)
		{
    
    
			S6_M--;
			if(S6_M<=0)
				S6_M=3;
		}
		if(S6_flag==3)
		{
    
    
			EEPROM_flag--;
			if(EEPROM_flag<=4)
				EEPROM_flag=12;
		}
	}
	if(S4==0&&S6_flag==0)	 
	{
    
    S7_start=0;Display_PWM();}	
}

void KEY()
{
    
    
	KEY_S4();
	KEY_S5();
	KEY_S6();
	KEY_S7();
}

void PWM()
{
    
    
	if(AD>=0&&AD<64)	PWM_flag=1;
	if(AD>=64&&AD<128)	PWM_flag=2;
	if(AD>=128&&AD<192)	PWM_flag=3;
	if(AD>=192&&AD<256)	PWM_flag=4;

	if(PWM_flag==1&&S7_start==1)	
	{
    
    
		if(cnt<=EEPROM*0.25) S7_LED=1;
		if(cnt>=EEPROM*0.25&&cnt<=EEPROM) S7_LED=0;
		cnt=0;
	} 

	if(PWM_flag==2&&S7_start==1)	
	{
    
    
		if(cnt<=EEPROM*0.5) S7_LED=1;
		if(cnt>=EEPROM*0.5&&cnt<=EEPROM) S7_LED=0;
		cnt=0;
	} 

	if(PWM_flag==3&&S7_start==1)	
	{
    
    
		if(cnt<=EEPROM*0.75) S7_LED=1;
		if(cnt>=EEPROM*0.75&&cnt<=EEPROM) S7_LED=0;
		cnt=0;
	} 

}

void InterruptTimer0() interrupt 1
{
    
    
	static unsigned char i=0,j=0;
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if(S7_start==1)
	{
    
    
		switch(i)
		{
    
    
			case 0:P2 = 0xC0;P0=0x80;P2=0xE0;P0=LEDbuff[0];P2=0x00;i++;break;
			case 1:P2 = 0xC0;P0=0x40;P2=0xE0;P0=LEDbuff[1];P2=0x00;i++;break;
			case 2:P2 = 0xC0;P0=0x20;P2=0xE0;P0=LEDbuff[2];P2=0x00;i++;break;
			case 3:P2 = 0xC0;P0=0x10;P2=0xE0;P0=LEDbuff[3];P2=0x00;i++;break;
			case 4:P2 = 0xC0;P0=0x08;P2=0xE0;P0=LEDbuff[4];P2=0x00;i++;break;
			case 5:P2 = 0xC0;P0=0x04;P2=0xE0;P0=LEDbuff[5];P2=0x00;i++;break;
			case 6:P2 = 0xC0;P0=0x02;P2=0xE0;P0=LEDbuff[6];P2=0x00;i++;break;
			case 7:P2 = 0xC0;P0=0x01;P2=0xE0;P0=LEDbuff[7];P2=0x00;i=0;break;
			default : break;
		}
	}
	if(S7_start==0&&S4==0)
	{
    
    
		switch(j)
		{
    
    
			case 0:P2 = 0xC0;P0=0x80;P2=0xE0;P0=LEDbuff[0];P2=0x00;j++;break;
			case 1:P2 = 0xC0;P0=0x40;P2=0xE0;P0=LEDbuff[1];P2=0x00;j=0;break;
			default : break;
		}
	}
    EEPROM= EEPROM_flag*100;	   //EEPROM写成4-12方便获取初值,不需要高八位低八位的或运算
	cnt++;clock++;
	num++;if(num>=800){
    
    num=0;Fl=~Fl;}
	PWM();
}

嗯,我觉得我写的超级短,而且满简洁的,就是按键需要长按,要不好使的很,上方是main.c文件

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include<STC15F2K60S2.h>
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    
    
    do{
    
    _nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    
    
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
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;  					// 0:应答,1:非应答
    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;    
}

void AD_Init()			 //AD初始化
{
    
    
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(0x43);
	 IIC_WaitAck();
	 IIC_Stop();
}

unsigned char AD_Get()	   //AD获取
{
    
    
	 unsigned char temp=0;

	 IIC_Start();
	 IIC_SendByte(0x91);
	 IIC_WaitAck();
	 temp = IIC_RecByte();
	 IIC_Stop();
	 return temp;
} 

void EEPROM_Write(unsigned char add,unsigned char dat)				 //EEPROM数据写入
{
    
    
	IIC_Start();
	IIC_SendByte(0xA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

unsigned char EEPROM_Get(unsigned char add)			   //EEPROM数据读取
{
    
    
	unsigned char temp =0;
	IIC_Start();
	IIC_SendByte(0xA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();

	IIC_Start();
	IIC_SendByte(0xA1);
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_Stop();

	return temp;
}

iic里写了EEPROM和AD的内容,应该没人需要看,还是放上吧。。。。

#ifndef _IIC_H
#define _IIC_H
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

#include<STC15F2K60S2.h>
#include "intrins.h"
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);
void AD_Init();
unsigned char AD_Get(); 
void EEPROM_Write(unsigned char add,unsigned char dat);
unsigned char EEPROM_Get(unsigned char add);


#endif

IIC.h文件。。。。。。。

其实写了好久,还是太差了,就这吧,感谢观看

谢谢

猜你喜欢

转载自blog.csdn.net/sxx_xxs/article/details/115269294
今日推荐