52单片机16路跑马灯按键无效
时间:10-02
整理:3721RD
点击:
如果能用VR来调节速度就更好了,刚开始学习,望各位前辈多多指教
#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,280,320,360,400,500,600,700,800,900,1000}; //速度码
uchar code LEDDisplayCode[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F}; //7段共阴数码管0-8字码
//uchar code LEDDisplayCode[]={0x40,0x79,0x2B,0x30,0x19,0x12,0x02,0x78,0x00}; //7段共阳数码管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次,使用12M晶振时等同计时1ms,当
//中断次数小于systemSpeed次数时,保持原有跑马运行模式不变,仅当
// 中断次数超过systemSpeed次数时才改变一次跑马运行模式,同时systemSpeed
//置0,这就避免了过多使用延时函数,既造成了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)
{
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;
}
}
}
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个脉冲
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)%4; //9中模式循环
Display(mode);
}
if (key&0x02)
{
if(speedNum>0)
{
speedNum--;
systemSpeed=SpeedCode[speedNum];
}
}
if(key&0x04)
{
if(speedNum<30)
{
speedNum++;
systemSpeed=SpeedCode[speedNum];
}
}
}
}
}
程序逻辑很清晰,这样看不出问题,你检查是不是硬件电路的问题没?
亲,我感觉是驱动能力不够,你是加上驱动看看
啦啦?
定时器中断里面重装初值不是应在中断一开始就重装吗。
按键未能启动。。
上传仿真和编译文件。
还有咋不去Proteus板块提问呢?
以下是板块的链接
http://bbs.elecfans.com/zhuti_proteus_1.html