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

在这里插入图片描述
主要涉及IIC通信中的 EEPROM和PCF8951。注意将驱动中的延时扩大8-12倍。在写本届赛题时字节超过2K,需要对软件进行破解,参考上篇

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

#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar led_start=0;
uchar mode=1;//模式编号
uchar set=0;//s6设置
uint  jiange=400;//流转间隔
uint  LED_tt=0,set_tt=0,AD_tt=0;//0.8秒闪烁
uint  RB2=0;//AD转换
uchar flag4=0;//s4长按标志
uchar LED_n=0;
uchar Light=0,LED_T=0;

void allinit();
void Delay1ms(uint ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void keyscan();
void Timer0Init(void);

void main()
{
  allinit();
	Timer0Init();
	mode=EEPROM_Read(0x10);
	Delay1ms(5);
	jiange=EEPROM_Read(0x20)*100;
	Delay1ms(5);
  yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
	while(1)
	{
//		RB2=AD_Read(0x03);
		if((set==0)&&(flag4==1))
		{
			if(RB2<64){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=1;}
			else if((RB2>=64)&&(RB2<128)){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=2;}
			else if((RB2>=128)&&(RB2<192)){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=3;}
			else if((RB2>=192)&&(RB2<255)){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=4;}
		}	
		else if(set==0)
		{
    yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
		}
			keyscan();
			display1(yi,er);
			display2(san,si);
			display3(wu,liu);
			display4(qi,ba);
	}

}

void keyscan()
{
if(P30==0)//s7
	{
			Delay1ms(5);
		  if(P30==0)
			{
				if(led_start==0)
					led_start=1;
				else if(led_start==1)
					led_start=0;
			}
	while(!P30);
	}
	
else if(P31==0)//s6
	{
			Delay1ms(5);
	  if(P31==0)
		{
					if(set==0)
						 {
						 set=1;set_tt=0;
									 if(jiange>=1000)
									 {
									 yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
									 }
									 else
									 {
									 yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
									 }
						 
						 }
						else if(set==1)
							{	
								set=2;set_tt=0;
									if(jiange>=1000)
									 {
									 yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
									 }
									 else
									 {
										yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
									 }
							 }
						else if(set==2)
									{
										set=0;set_tt=0;
										yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
										
										EEPROM_Write(mode,0x10);
										Delay1ms(5);
										EEPROM_Write(jiange/100,0x20);
										Delay1ms(5);
									}
						
		}
	while(!P31);
	}


	
	
else if(P32==0)//s5
	{
			Delay1ms(5);
  if(P32==0)
	{
			if(set==1)
     {
					mode+=1;
					if(mode>4)
					{
					mode=4;
					}
		 }
		 else if(set==2)
		 {
		 jiange+=100;
		 if(jiange>1200)
			{
			jiange=1200;
			}
		 
		 }
		
}
	while(!P32);
	}
	
	
else if(P33==0)//s4
	{
			Delay1ms(5);
		  if(P33==0)
			{
				flag4=1;			
			}
	}
			if((flag4==1)&&(P33==1))
			{
				flag4=0;
							if(set==1)
							{
									mode-=1;
									if(mode<1)
									{
									mode=1;
									}
							}
									else if(set==2)
							{
									jiange-=100;
									if(jiange<400)
									{
									jiange=400;
									}
							}

			
			}
				      
}

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;
}

void Timer0() interrupt 1
{
	set_tt++;
	LED_tt++;
	AD_tt++;
	
	if((LED_tt==1)&&(led_start==1))//每1ms扫描一次模式
	{
		if(mode==1)
		{
			P2=0X00;P0=0XFF;P2=0X80;P0=~(0X01<<LED_n);P2=0X00;
		}
		else if(mode==2)
		{
			P2=0X00;P0=0XFF;P2=0X80;P0=~(0X80>>LED_n);P2=0X00;
		}
		else if(mode==3)
		{
			P2=0X00;P0=0XFF;P2=0X80;
			if(LED_n==0)P0=0X7E;
			else if(LED_n==1)P0=0XBD;
			else if(LED_n==2)P0=0XDB;
			else if(LED_n==3)P0=0XE7;
			P2=0X00;
		}
		else if(mode==4)
		{
			P2=0X00;P0=0XFF;P2=0X80;
			if(LED_n==0)P0=0XE7;
			else if(LED_n==1)P0=0XDB;
			else if(LED_n==2)P0=0XBD;
			else if(LED_n==3)P0=0X7E;
			P2=0X00;
		}
	
	}
	else if(LED_tt==Light)//PWM控制 每一次循环20ms mode1 LED_tt=1亮 2-20熄灭  占空比5%  
												 //           mode2 LED_tt=1-4亮   占空比20%  
												 //            mode3 1-9占空比45%   mode4 1-19 占空比95% 
	{
		P2=0X00;P0=0XFF;P2=0X80;P0=0XFF;P2=0X00;
	}
	else if(LED_tt==20)//每20ms计时一次 LED_T +1
	{
		LED_tt=0;LED_T++;
		if((LED_T*20)>=jiange)//到了对应时间间隔之后 重新计时
		{
			LED_T=0;
			if(mode==1){LED_n++;if(LED_n>=8)LED_n=0;}
			else if(mode==2){LED_n++;if(LED_n>=8)LED_n=0;}
			else if(mode==3){LED_n++;if(LED_n>=4)LED_n=0;}
			else if(mode==4){LED_n++;if(LED_n>=4)LED_n=0;}	
		}		
	}
	if(AD_tt==200)//每200ms读取一次RB2值
	{
		AD_tt=0;
		RB2=AD_Read(0x03);
		if(RB2<64)Light=2;
		else if((RB2>=64)&&(RB2<128))Light=5;
		else if((RB2>=128)&&(RB2<192))Light=10;
		else if((RB2>=192)&&(RB2<256))Light=19;
	}	

	
if(set_tt==800)
{
  if(set==1)
	{
				if(jiange>=1000)
				{
				yi=11;er=11;san=11;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
				}
				else
				{
				yi=11;er=11;san=11;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
				}
	}
	else if(set==2)
	{
		if(jiange>=1000)
		 {
		 yi=10;er=mode;san=10;si=11;wu=11;liu=11;qi=11;ba=11;
		 }
		 else
		 {
			yi=10;er=mode;san=10;si=11;wu=11;liu=11;qi=11;ba=11;
		 }
	}		
							
}
	if(set_tt==1600)
	{
	set_tt=0;
		
			if(set==1)
	{
				if(jiange>=1000)
				{
				yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
				}
				else
				{
				yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
				}
	}
	else if(set==2)
	{
		if(jiange>=1000)
		 {
		 yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
		 }
		 else
		 {
			yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
		 }
	}
	
	
	
}
	
	

}



void allinit()
{
	P2=0X80;
	P0=0XFF;
	
	P2=0XC0;
	P0=0XFF;
	P2=0XE0;
	P0=0XFF;
	
	P2=0XA0;
	P0=0X00;
}
void Delay1ms(uint ms)		//@12.000MHz
{
	uint k;
	unsigned char i, j;
	for(k=ms;k>0;k--)
	{
				i = 12;
				j = 169;
				do
				{
					while (--j);
				} while (--i);
				
	}
}


void display1(uchar yi,uchar er)
{
	P2=0XC0;
	P0=0X01;
	P2=0XE0;
	P0=tab[yi];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X02;
	P2=0XE0;
	P0=tab[er];
	Delay1ms(1);

}

void display2(uchar san,uchar si)
{
	P2=0XC0;
	P0=0X04;
	P2=0XE0;
	P0=tab[san];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X08;
	P2=0XE0;
	P0=tab[si];
	Delay1ms(1);
}
void display3(uchar wu,uchar liu)
{
	P2=0XC0;
	P0=0X10;
	P2=0XE0;
	P0=tab[wu];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X20;
	P2=0XE0;
	P0=tab[liu];
	Delay1ms(1);

}

void display4(uchar qi,uchar ba)
{
	P2=0XC0;
	P0=0X40;
	P2=0XE0;
	P0=tab[qi];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X80;
	P2=0XE0;
	P0=tab[ba];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0XFF;
	P2=0XE0;
	P0=0XFF;//关闭所有数码管使其亮度一致
}



驱动参考

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

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

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}    


#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

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


//总线启动条件
void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}

////应答位控制
//void IIC_Ack(bit ackbit)
//{
//	if(ackbit) 
//	{	
//		SDA = 0;
//	}
//	else 
//	{
//		SDA = 1;
//	}
//	somenop;
//	SCL = 1;
//	somenop;
//	SCL = 0;
//	SDA = 1; 
//	somenop;
//}


//等待应答
bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}

//AD转换
unsigned char AD_Read(unsigned char add)
{
		unsigned char temp;
		IIC_Start(); 
	
		IIC_SendByte(0x90);
		IIC_WaitAck();
	
		IIC_SendByte(add);//采集AD信息的地址
		IIC_WaitAck();
	
		IIC_Stop();

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

//EEPROM读
unsigned char EEPROM_Read(unsigned char add)
{
		unsigned char 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;
}

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



#ifndef _IIC_H
#define _IIC_H

//函数声明
void IIC_Start(void); 
void IIC_Stop(void);  
void IIC_Ack(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void); 
//添加

//AD转换
unsigned char AD_Read(unsigned char add);
//EEPROM读
unsigned char EEPROM_Read(unsigned char add);
//EEPROM写
void EEPROM_Write(unsigned char dat,unsigned char add);

#endif

猜你喜欢

转载自blog.csdn.net/weixin_42244181/article/details/88723987