蓝桥杯第九届-彩灯控制

“彩灯控制器”的程序设计与调试(70分)

一、基本要求

1.1 使用 CT107D 单片机竞赛板,完成“彩灯控制器”功能的程序设计与调试;
1.2 设计与调试过程中,可参考组委会提供的“资源数据包”;
1.3 Keil 工程文件以准考证号命名,完成设计后,提交完整、可编译的 Keil工程文件到服务器。

二、硬件框图

在这里插入图片描述

三、功能描述

3.1 基本功能描述
通过单片机控制8个LED指示灯按照特定的顺序(工作模式)亮灭;指示灯的流转间隔可通过按键调整,亮度可由电位器RB2进行控制;各工作模式的流转间隔时间需在E2PROM中保存,并可在硬件重新上电后,自动载入。
3.2 设计说明
1)关闭蜂鸣器、继电器等与本试题程序设计无关的外设资源;
2)设备上电后默认数码管、LED 指示灯均为熄灭状态;
3)流转间隔可调整范围为 400ms-1200ms;
4)设备固定按照模式 1、模式 2、模式 3、模式 4 的次序循环往复运行。
3.3 LED 指示灯工作模式
1)模式 1:按照 L1、L2…L8 的顺序,从左到右单循环点亮。
2)模式 2:按照 L8、L7…L1 的顺序,从右到左单循环点亮。
3)模式 3:
在这里插入图片描述

模式 3 彩灯运行状态说明

4)模式 4:
在这里插入图片描述

模式 4 彩灯运行状态说明

3.4 亮度等级控制
检测电位器RB2的输出电压,控制8个LED指示灯的亮度,要求在0V-5V
的可调区间内,实现 4 个均匀分布的 LED 指示灯亮度等级。
3.5 按键功能
1)按键 S7 定义为“启动/停止”按键,按下后启动或停止 LED 的流转。
2)按键 S6 定义为“设置”按键,按键按下后数码管进入“流转间隔”
设置界面,如下图所示:在这里插入图片描述
通过按键 S6 可切换选择“运行模式”和“流转间隔”两个显示单元,
当前被选择的显示单元以 0.8 秒为间隔亮灭。
在这里插入图片描述
3)按键 S5 定义为“加”按键,在设置界面下,按下该键,若当前选择
的是运行模式,则运行模式编号加 1,若当前选择的是流转间隔,则
流转间隔增加 100ms。 4)按键 S4 定义为“减”按键,在设置界面下,按下该键,若当前选择
的是运行模式,则运行模式编号减 1,若当前选择的是流转间隔,则
流转间隔减少 100ms。 5)按键功能说明:
a)按键 S4、S5 的“加”、“减”功能只在“设置状态”下有效,数
值的调整应注意边界属性。
b)在非“设置状态”下,按下 S4 按键可显示指示灯当前的亮度等
级,4 个亮度等级从暗到亮,依次用数字 1、2、3、4 表示;松开
S4 按键,数码管显示关闭,亮度等级的显示格式如下图所示:

在这里插入图片描述

#include "base.h"

u8 SetInterface=0;		//0:熄灭	1:模式编号	2:流转间隔
u8 modeNumber=1;		//运行模式编号 1	2	3	4
u8 gaptime[]={0,4,4,4,4};		//流转间隔	400	500	……1200
u8 LEDmode1[9]={0xff,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};	
u8 LEDmode2[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
u8 LEDmode3[4]={0x81,0x42,0x24,0x18};
u8 LEDmode4[4]={0x18,0x24,0x42,0x81};
u8 PWMflag=10;			//1		4	7	10
u8 ShowBrightness=4;	//1		2	3	4
u8 P0temp=0xff;
u8 Rb2;

bit Flag800ms;
u8 KeyNumber;
u8 i;
u16 LEDdelay=0;
u8 LEDmode=0;//LED亮的运行模式编号 1	2	3	4
bit LEDpause=1;		//1:启动	0:停止

void main()
{
	Init_System();
	InitTimer0();
	for(i=1;i<5;i++)
	{
		gaptime[i]=AT24C02_ReadByte(i);
		Delay6ms();		
		if(gaptime[i]>12 || gaptime[i]<4)	
		{
			gaptime[i]=4;
		}
	}
	while(1)
	{	
//=================PWM=====		
		Rb2=Read_Rb2(3);
		if(Rb2 < 64)
		{
			PWMflag=1;ShowBrightness=1;
		}
		else if(Rb2 < 128)
		{
			PWMflag=4;ShowBrightness=2;
		}
		else if(Rb2 < 192)
		{
			PWMflag=7;ShowBrightness=3;
		}
		else
		{
			PWMflag=10;ShowBrightness=4;
		}

//============================按键======================
		KeyNumber=Key();
/*7*/	if(KeyNumber==7)	//启动,停止
		{
			LEDpause=~LEDpause;
		}
/*6*/	if(KeyNumber==6)	//换模式编号,流转间隔,熄灭
		{
			SetInterface=(SetInterface+1)%3;
			LEDmode=1;
		}
/*5*/	if(KeyNumber==5)	//模式+1 或 间隔+1
		{
			if(SetInterface==1)
			{
				modeNumber++;
				if(modeNumber==5)
				{
					modeNumber=1;
				}	
			}
			else if(SetInterface==2)
			{
				gaptime[modeNumber]++;
				if(gaptime[modeNumber]==13)
				{
					gaptime[modeNumber]=4;	
				}
			}					
		}	
/*4*/	if(KeyNumber==4)	//模式-1 或 间隔-1
		{
			if(SetInterface==1)
			{
				modeNumber--;
				if(modeNumber==0)
				{
					modeNumber=4;
				}	
			}
			else if(SetInterface==2)
			{
				gaptime[modeNumber]--;
				if(gaptime[modeNumber]==3)
				{
					gaptime[modeNumber]=12;	
				}
			}
		}	
//============================AT24C02======================	
		for(i=1;i<5;i++)
		{
			AT24C02_WriteByte(i,gaptime[i]);
			Delay6ms();		//!!!要记得写入后延时6ms
		}	
//============================display======================		
		if(P33==0 && SetInterface==0)
		{
			DisplayBrightness(ShowBrightness);
		}
		else
		{
			DisplaySet(modeNumber,gaptime[modeNumber]);		
		}
	}//while(1)
}


//tm0_isr		1ms
void tm0_isr()	interrupt 1
{
	static u16 cnt=0;
	static u8 LEDbit=0; //第几个LED亮L1~L8
	cnt++;
	TL0=65535-12000;
	TH0=(65535-12000)>>8;
	Display_scan();
//=====================================PWM=======
	if(cnt%10 < PWMflag)		//亮
	{
		P0=P0temp;Y4;
	}	
	else	//灭
	{
		P0=0xFF;Y4;
	}
//=====================================PWMend=======	
	if(cnt%20==0)
	{
		Key_scan();
	}
	if(cnt%800==0)
	{
		Flag800ms=~Flag800ms;
	}
//=================LED=============
	if( SetInterface==0	&& LEDpause==1)//0:熄灭	1:模式编号	2:流转间隔
	{
		if(cnt % (gaptime[1]*100)==0 && LEDmode==1)
		{
			LEDbit++;		
			P0temp=~LEDmode1[LEDbit];Y4;			
			if(LEDbit==8)
			{
				LEDbit=0;LEDmode=2;
			}
		}
		else if(cnt % (gaptime[2]*100)==0 && LEDmode==2)
		{	
			P0temp=~LEDmode2[LEDbit];Y4;
			LEDbit++;			
			if(LEDbit==8)
			{
				LEDbit=0;LEDmode=3;
			}
		}
		else if(cnt % (gaptime[3]*100)==0 && LEDmode==3)
		{	
			P0temp=~LEDmode3[LEDbit];Y4;
			LEDbit++;			
			if(LEDbit==4)
			{
				LEDbit=0;LEDmode=4;
			}
		}
		else if(cnt % (gaptime[4]*100)==0 && LEDmode==4)
		{	
			P0temp=~LEDmode4[LEDbit];Y4;
			LEDbit++;			
			if(LEDbit==4)
			{
				LEDbit=0;LEDmode=1;
			}
		}
	}
//=========================LEDend===============	
	cnt%=1200;
}


模块

#include "base.h"

u8 NixieTab[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
u8 show_Buffer[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
/*
0	--	0xC0
1	--	0xF9
2	--	0xA4
3	--	0xB0
4	--	0x99
5	--	0x92
6	--	0x82
7	--	0xF8
8	--	0x80
9	--	0x90
*/

void Init_System()
{
	P0=0x00;Y6;
	P0=0xff;Y7;
	P0=0x00;Y5;
	P0=0xff;Y4;
}
void InitTimer0()
{
	AUXR |= 0x80;
	TMOD=0x01;
	TL0=65535-11059;
	TH0=(65535-11059)>>8;
	TR0=1;
	ET0=1;
	EA=1;
}
void Display_scan()
{
	static u8 SMGvalue;
	P0=0x01<<SMGvalue;Y6;
	P0=show_Buffer[SMGvalue];Y7;
	SMGvalue=(SMGvalue+1)%8;
}
extern bit Flag800ms;
extern u8 SetInterface;
void DisplaySet(u8 mode,u16 time)	
{
	if(SetInterface==0)
	{
		show_Buffer[0]=0xff;
		show_Buffer[1]=0xff;
		show_Buffer[2]=0xff;
		
		show_Buffer[4]=0xff;
		show_Buffer[5]=0xff;
		show_Buffer[6]=0xff;
		show_Buffer[7]=0xff;
	}
	else if(Flag800ms==0 && SetInterface==1)
	{
		show_Buffer[0]=0xff;
		show_Buffer[1]=0xff;
		show_Buffer[2]=0xff;
	}
	else if(Flag800ms==0 && SetInterface==2)
	{
		show_Buffer[4]=0xff;
		show_Buffer[5]=0xff;
		show_Buffer[6]=0xff;
		show_Buffer[7]=0xff;
	}
	else
	{
		show_Buffer[0]=0xBF;
		show_Buffer[1]=NixieTab[mode%10];
		show_Buffer[2]=0xBF;
		if(time/10%10==0)
		{
			show_Buffer[4]=0xff;
		}
		else
		{
			show_Buffer[4]=NixieTab[time/10%10];
		}
		show_Buffer[5]=NixieTab[time%10];
		show_Buffer[6]=NixieTab[time*10%10];
		show_Buffer[7]=NixieTab[time*100%10];
	}
}
void DisplayBrightness(u8 ShowBrightness)
{
	show_Buffer[6]=0xbf;
	show_Buffer[7]=NixieTab[ShowBrightness];
}
u8 KeyNum;
u8 getKey()
{
	u8 getKey=0;	//必须=0,要不会出问题
	if(P30==0){getKey=7;}
	if(P31==0){getKey=6;}
	if(P32==0){getKey=5;}
	if(P33==0){getKey=4;}
	return getKey;
}
void Key_scan()
{	
	static u8 LastKey,NowKey;
	LastKey=NowKey;
	NowKey=getKey();
	if(LastKey==7 && NowKey==0)	//S7按下
	{
		KeyNum=7;
	}
	if(LastKey==6 && NowKey==0)	
	{
		KeyNum=6;
	}
	if(LastKey==5 && NowKey==0)	
	{
		KeyNum=5;
	}
	if(LastKey==4 && NowKey==0)	
	{
		KeyNum=4;
	}
//	return KeyNum;
}
u8 Key()
{
	u8 Key;
	Key=KeyNum;
	KeyNum=0;
	return Key;
}
//==================================AT24C02==================================
void Delay6ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 71;
	j = 6;
	do
	{
		while (--j);
	} while (--i);
}

void AT24C02_WriteByte(u8 WordAddress,Data)
{
	I2CStart();
	I2CSendByte(0xA0);
	I2CWaitAck();
	I2CSendByte(WordAddress);
	I2CWaitAck();
	I2CSendByte(Data);
	I2CWaitAck();
	I2CStop();
}

u8 AT24C02_ReadByte(u8 WordAddress)
{
	u8 Data;
	I2CStart();
	I2CSendByte(0xA0);
	I2CWaitAck();
	I2CSendByte(WordAddress);
	I2CWaitAck();

	I2CStart();
	I2CSendByte(0xA1);
	I2CWaitAck();
	Data=I2CReceiveByte();	
	I2CSendAck(1);
	I2CStop();
	
	return Data;
}
//==============================PCF8591======================================
u8 Read_Rb2(u8 WordAddress)
{
	u8 Data;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(WordAddress);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	Data=I2CReceiveByte();	
	I2CSendAck(1);
	I2CStop();
	return Data;
}


官方提供的iic文件

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "base.h"
#include "iic.h"

#define DELAY_TIME	5

sbit scl=P2^0;
sbit sda=P2^1;

//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值