📄 跑马灯源程序.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 + -