⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 跑马灯源程序.c

📁 多功能51单片机跑马灯
💻 C
字号:
//程序说明
//在本程序中,默认使用51单片机的P0、P2两个端口作为16个跑马灯的驱动端口
//P1端口作为数码管驱动端口,P3端口的0、1、2脚接按键。若要修改端口只需在
//宏定义中修改就行了。另外本程序默认使用7段共阴极数码管,若需要使用共阳极
//数码管只需将"uchar code LEDDisplayCode[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F};"注释掉,
//并将"uchar code LEDDisplayCode[] = {0x40,0x79,0x2B,0x30,0x19,0x12,0x02,0x78,0x00};"恢复就行了。
#include <REG52.H>
#define LED1_8	P0		//左8个LED,起始P0.0对应LED1,依次对应
#define LED9_16	P2		//右8个LED,起始P2.0对应LED9,依次对应
#define _7SEG	P1		//7段数码管
#define KEYBOARD	P3	//键盘
#define uchar	unsigned char
#define uint	unsigned int
uint code SpeedCode[]={1,3,5,7,10,14,18,23,27,32,40,50,65,80,100,120,140,170,200,240,280,320,360,400,500,600,700,800,900,1000};//速度码
uchar code LEDDisplayCode[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F};//七段共阴极数码管0到8字码
//uchar code LEDDisplayCode[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00};//七段共阳极数码管0到8字码
uchar mode;
uint count,systemSpeed,speedNum,index; 
bit direction,flag;
void Delay1ms(uint num)	//num ms延时函数
{
	uint i,j;
	for(i=0;i<num;i++)
		for(j=0;j<125;j++);	//1ms延时
}

void Display(uchar Value)		//数码管驱动函数
{
	_7SEG = LEDDisplayCode[Value];
}

uchar KeyScan(void)			//键盘读入函数
{
	uchar check1,check2,key = 0x00;
	check1 = KEYBOARD&0x07;		//第一次读键盘值
	if(check1==0x07)
		return 0x00;
	
	Delay1ms(10);
	check2 = KEYBOARD&0x07;		//第二次读键盘值
	if(check2==check1)			//若两次值相同,无键按下,返回0值
		return 0x00;

	if(!(check1&0x01))			//key1键被按下
		key|=0x01;
	if(!(check1&0x02))			//key2键被按下
		key|=0x02;
	if(!(check1&0x04))			//key3键被按下
		key|=0x04;
	return key;					//返回键值

}

void LEDShow(uint LEDStatus)
{
	LED1_8 = ~(LEDStatus&0x00FF);
	LED9_16 = ~((LEDStatus>>8)&0x00FF); 
}

void Timer1(void) interrupt 3	//T1 interrupt service routine
{
	if(++count>=systemSpeed)	/*利用计数1000次,使用12MHz晶振时等同计时1ms,
									当中断次数小于systemSpeed次时,保持原有跑马运行模式不变,仅当中断次数超过
									systemSpeed次时才改变一次跑马运行模式,同时systemSpeed置0。这就避免了
									过多使用延时函数,既造成CPU资源浪费,又使按键失灵的弊端(注:过多使用延
									时造成按键失灵,是我在实验中遇到的问题。分析原因我认为在键盘扫描函数中,使
									用了10ms延时,如果再次频繁长时间调用延时函数势必在CPU执行延时期间,按键盘就
									不起作用了)。*/
	{
		count = 0;
		if(mode==0x00)		//模式0:一个灯亮从左到右跑
		{
			LEDShow(0x0001<<index);	
			index = (index+1)%16;	
		}
		else if(mode ==0x01)		//模式1:一个灯亮从右到左跑
		{
			LEDShow(0x8000>>index);	
			index = (index+1)%16;
		}
		else if(mode ==0x02)		//模式2:一个灯亮先从左到右再从右到左跑
		{
			if(direction)
				LEDShow(0x0001<<index);
			else
				LEDShow(0x8000>>index);
			if(index==15)
				direction = !direction;
				index = (index+1)%16;
		}
		else if(mode ==0x03)		//模式3:两个灯灭先从左到右再从右到左跑
		{
			if(direction)
				LEDShow(~(0x0003<<index));
			else
				LEDShow(~(0xC000>>index));
			if(index==15)
				direction = !direction;
			index = (index+1)%16;
		}
		else if(mode ==0x04)	//模式4:全亮后逐个灭,先左右、后右左,然后全灭逐个亮,先右左、后左右
		{
			if(direction)
			{
				if(flag)
					LEDShow(0xFFFE<<index);
	   			else
					LEDShow(~(0x7FFF>>index));
			}
			else
			{
				if(flag)
					LEDShow(0x7FFF>>index);
				else
					LEDShow(~(0xFFFE<<index));
			}
			if(index==15)
			{
				direction = !direction;
				if(direction)
					flag = !flag;
			}
   			index = (index+1)%16;
		}
		else if(mode ==0x05)	//模式5:四个亮左右来回跑
		{
			if(direction)
				LEDShow(0x000F<<index);
			else
				LEDShow(0xF000>>index);
			if(index==15)
				direction = !direction;
			index = (index+1)%16;
		}
		else if(mode ==0x06)	//模式6:四个灭左右来回跑
		{
			if(direction)
				LEDShow(~(0x000F<<index));
			else
				LEDShow(~(0xF000>>index));
			if(index==15)
				direction = !direction;
   			index = (index+1)%16;
		}
		else if(mode ==0x07)	//模式7:六个亮左右来回跑
		{
			if(direction)
				LEDShow(0x003F<<index);
			else
				LEDShow(0xFC00>>index);
			if(index==9)
				direction = !direction;
			index = (index+1)%10;
		}
		else if(mode ==0x08)	//模式8:礼花式点亮,群闪三下
		{
			if(index==0)
				LEDShow(0x0180);
			if(index==1)
				LEDShow(0x0240);
			if(index==2)
				LEDShow(0x0420);
			if(index==3)
				LEDShow(0x0810);
			if(index==4)
				LEDShow(0x1008);
			if(index==5)
				LEDShow(0x2004);
			if(index==6)
				LEDShow(0x4002);
			if(index==7)
				LEDShow(0x8001);
			if(index==8)
				LEDShow(0xFFFF);
			if(index==9)
				LEDShow(0x0000);
			if(index==10)
				LEDShow(0xFFFF);
			if(index==11)
				LEDShow(0x0000);
			if(index==12)
				LEDShow(0xFFFF);
			if(index==13)
				LEDShow(0x0000);
			index=(index+1)%14;
		}
   	}
	TH1 = 0xFC;
	TL1 = 0x18;		//重载初值
}

void main(void)
{
	uchar key;
	/*********************************************************************/
	mode = 0x00;
	count = 0;
	index = 0; 
	direction = 1;
	flag = 1;
	speedNum=12;	//初始速度

	LED1_8 = 0x00;
	LED9_16 = 0x00;
	_7SEG = 0xFF;
	Delay1ms(1000);
	LED1_8 = 0xFF;
	LED9_16 = 0xFF;
	_7SEG = 0x00;
	KEYBOARD = 0xFF;
	systemSpeed = SpeedCode[speedNum];
	Display(mode);
	/*********************************************************************/
	TMOD  = 0x10;			//T1模式
 	TH1 = 0xFC;
	TL1 = 0x18;		//计数1000个脉冲 (使用12MHz晶振,则计时1000 ×1us=1ms)
	ET1=1;					//允许T1中断
	EA=1;					//开总中断
	TR1 = 1;				//开T1中断
	/*********************************************************************/

	while(1)		//死循环不断地读按键的状态,并按键值响应相关状跑马花样
	{
		key = KeyScan();
		if(key!=0x00)
		{
			if(key&0x01)
			{
				direction = 1;
				index = 0;
				flag = 1;
				mode = (mode+1)%9;	//9种模式循环
				Display(mode);
			}
			if(key&0x02)
			{
				if(speedNum>0)
				{
					speedNum--;
					systemSpeed = SpeedCode[speedNum];
				}
			}
			if(key&0x04)
			{
				if(speedNum<30)
				{
					speedNum++;
					systemSpeed = SpeedCode[speedNum];
				}
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -