接上一篇博客https://blog.csdn.net/Jinyindao243052/article/details/107822771
除了实现练习题的功能,我自己还写了一些函数,实践证明在考试中用得到!
#include
#include
#include
//数码管的引脚
sbit led0=P0^0;
sbit led1=P0^1;
sbit led2=P0^2;
sbit led3=P0^3;
sbit led4=P0^4;
sbit led5=P0^5;
sbit led6=P0^6;
sbit led7=P0^7;
//定义按键
sbit KEY2 = P2^0; //按键1
sbit KEY3 = P2^1; //按键2
unsigned char key;
unsigned char DispBuf[8];
unsigned char s_led[8]={1,1,1,1,1,1,1,1};//led显示控制:s_led[0]对应最右边的数码管
unsigned char s_dat[8]={1,1,1,0,0,1,1,1};//数码管显示控制:s_dat[0]对应最右边的数码管
unsigned char d[8]={1,1,1,15,14,1,1,1};//数据:d[0]对应最右边的数码管
code unsigned char Tab[] =
{//定义0123456789AbCdEF的数码管字型数据
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
};
/*
函数:KeyScan()
功能:键盘扫描
返回:扫描到的键值
*/
unsigned char KeyScan()
{
unsigned char k = '\0';
if ( KEY2 == 0 ) k = 'A';
if ( KEY3== 0 ) k = 'B';
return k;
}
//定义显示缓冲区(由定时中断程序自动扫描)
unsigned char DispBuf[8];
/*
函数:T1INTSVC()
功能:定时器T1的中断服务函数,扫描数码管
*/
void T1INTSVC() interrupt 3
{
code unsigned char com[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
static unsigned char n = 0;
TR1 = 0;
TH1 = 0xFC;
TL1 = 0x66;
TR1 = 1;
XBYTE[0x7800] = 0xFF; //暂停显示
XBYTE[0x7801] = ~DispBuf[n]; //更新扫描数据
XBYTE[0x7800] = ~com[n]; //重新显示
n++;
n &= 0x07;
}
/*
函数:DispClear()
功能:清除DispBuf
*/
void DispClear()
{
unsigned char i;
for ( i=0; i<8; i++ )
{
DispBuf[i] = 0x00;
}
}
//延时函数
void delay(unsigned int t)
{
do
{
TH0 = 0xFA;
TL0 = 0x24; //设置定时器初值(对应0.001s)
TR0 = 1; //启动定时器
while ( !TF0 ); //等待定时器溢出
TR0 = 0; //停止定时器
TF0 = 0; //清除溢出标志
} while ( --t != 0 ); //循环t次
}
/*
函数:DispInit()
功能:数码管扫描显示初始化
*/
void DispInit()
{
DispClear(); //初始为全灭
EA = 0;
TMOD &= 0x0F;
TMOD |= 0x10;
TH1 = 0xFC;
TL1 = 0x66;
TR1 = 1;
ET1 = 1;
EA = 1;
}
/*系统初始化函数*/
void SysInit()
{
TMOD &= 0xF0;
TMOD |= 0x01; //设置定时器T0为16位定时器
DispInit(); //数码管扫描显示初始化
}
//自己实现的函数
/*
LED全部熄灭
*/
void ledclear()
{
led0=1;
led1=1;
led2=1;
led3=1;
led4=1;
led5=1;
led6=1;
led7=1;
}
/*
led灯控制函数
s[0]对应最右边的LED灯,0为亮,1为不亮
*/
void displed(unsigned char s[8])
{
unsigned char i=0;
ledclear();
if(s[0]==0)
led0=0;
if(s[1]==0)
led1=0;
if(s[2]==0)
led2=0;
if(s[3]==0)
led3=0;
if(s[4]==0)
led4=0;
if(s[5]==0)
led5=0;
if(s[6]==0)
led6=0;
if(s[7]==0)
led7=0;
}
//实现led向左循环移动times次
shift_ledr(unsigned char times)
{
unsigned char i=0;
unsigned char j=0;
unsigned char temp=0;
for(i=0;i<times;i++)
{
temp=s_led[0];
for(j=1;j<=7;j++)
{
s_led[j-1]=s_led[j];
}
s_led[7]=temp;
displed(s_led);
}
}
//实现led向右循环移动times次
shift_ledl(unsigned char times)
{
unsigned char i=0;
unsigned char j=0;
unsigned char temp=0;
for(i=0;i<times;i++)
{
temp=s_led[7];
for(j=7;j>=1;j--)
{
s_led[j]=s_led[j-1];
}
s_led[0]=temp;
displed(s_led);
}
}
/* 数码管显示控制函数
s控制哪个数码管亮,dat控制对应位置显示哪个数
s[0]对应最右边的数码管,DispBuf[0],0为亮,1为灭
dat[0]对应最右边的数码管,DispBuf[0],是几就显示几
*/
void dispdata(unsigned char s[8],unsigned char d[8])
{
DispClear();
if(s[0]==0)
DispBuf[0]=Tab[d[0]];
if(s[1]==0)
DispBuf[1]=Tab[d[1]];
if(s[2]==0)
DispBuf[2]=Tab[d[2]];
if(s[3]==0)
DispBuf[3]=Tab[d[3]];
if(s[4]==0)
DispBuf[4]=Tab[d[4]];
if(s[5]==0)
DispBuf[5]=Tab[d[5]];
if(s[6]==0)
DispBuf[6]=Tab[d[6]];
if(s[7]==0)
DispBuf[7]=Tab[d[7]];
}
void shift_l(unsigned char times)//数码管左移左移times次
{
unsigned char i=0;
unsigned char j=0;
unsigned char temp1=0;
unsigned char temp2=0;
unsigned char temp3=0;
for(j=0;j<times;j++)
{
temp1=s_dat[7];
temp2=d[7];
for(i=7;i>=1;i--)
{
s_dat[i]=s_dat[i-1];
d[i]=d[i-1];
}
s_dat[0]=temp1;
d[0]=temp2;
//控制每次停留的时间
}
dispdata(s_dat,d);
}
/*
更改d的数值
把temp的数值赋给d
*/
void modify_d(unsigned char temp[8])
{
unsigned char i=0;
for(i=0;i<8;i++)
{
d[i]=temp[i];
}
}
/*
修改d的某一位
把第a位改为b
*/
void modify_d_bit(unsigned char a,unsigned char b)
{
d[a]=b;
}
/*判断是否有键按下,按下退出*/
void keyin()
{
for(;;)
{
delay(50);
key=KeyScan();
if(key!='\0')
{
break;
}
}
}
/*
判断按键是否抬起,抬起退出
*/
void keyout()
{
for(;;)
{
delay(50);
key=KeyScan();
if(key=='\0')
{
break;
}
}
}
/*
把num代表的数存储到是s数组中,保存位数的长度是len
*/
void num2str(unsigned char *s,unsigned int num,unsigned char len)
{
unsigned char i=0;
unsigned char temp=0;
for(i=0;i<len;i++)
{
temp=num%10;
num=(num-temp)/10;
*s++=temp;
}
}
/*
改变s_dat,把第a位设置为0或1
*/
void modify_s_dat_bit(unsigned char a,unsigned char b)
{
s_dat[a]=b;
if(b==1)
{
DispBuf[a]=0x00;
}
else
{
DispBuf[a]=Tab[d[a]];
}
}
/*
更改s_dat,控制哪些数码管亮
*/
void modify_s_dat(unsigned char s[8])
{
unsigned char i=0;
for(i=0;i<8;i++)
{
s_dat[i]=s[i];
if(s_dat[i]==1)
{
DispBuf[i]=0x00;
}
else
{
DispBuf[i]=Tab[d[i]];
}
}
}
/*
快速改变灯的第a位的亮灭
b=0亮,b=1灭
*/
void modify_s_led(unsigned char a,unsigned char b)
{
s_led[a]=b;
displed(s_led);
}
/*
对char类型的0和1取反
char a=0
a=0x08
不像sbit类型一样可以直接取反
*/
unsigned char convert(unsigned char a)
{
unsigned char b=0;
if(a==0)
{
b=1;
}
return b;
}
void main()
{
unsigned char temp[8]={1,1,1,0,0,1,1,1};
unsigned char temp1[8]={1,1,0,0,1,1,7,1};
unsigned char temp3;
unsigned char temp4=0;
unsigned char temp5=0;
unsigned char temp6=0;
unsigned char i=0;
unsigned char mode0=0;
unsigned char mode1=0;
unsigned char wait=0;
SysInit();
displed(s_led);
dispdata(s_dat,d);
delay(2000);
d[6]=9;
dispdata(s_dat,d);
for(;;)
{
for(;;)
{
delay(50);
key=KeyScan();
if(key!='\0')
{
break;
}
if(wait==20)
{
if(mode1==1)
{
s_led[0]=convert(s_led[0]);
displed(s_led);
temp4++;
if(temp4==10)
{
shift_l(1);
temp4=0;
}
}
}
wait++;
if(wait==21)
{
wait=0;
}
}
if(key=='A')
{
mode0=convert(mode0);
s_led[7]=convert(s_led[7]);
displed(s_led);
}
if(key=='B')
{
mode1=convert(mode1);
if(mode1==0)
{
temp4=0;
s_led[0]=1;
displed(s_led);
}
}
for(temp5=0;temp5<8;temp5++)
{
if(d[temp5]!=1)
{
for(temp6=temp5+1;temp6<8;temp6++)
{
if(d[temp6]!=1)
{
break;
}
}
break;
}
}
if(mode0==0&mode1==0)
{
if(temp5!=0)
{
d[temp5]=15;
d[temp6]=14;
}
else
{
d[temp6]=15;
d[temp5]=14;
}
}
else
{
if(temp5!=0)
{
d[temp5]=9;
d[temp6]=0;
}
else
{
d[temp6]=9;
d[temp5]=0;
}
}
dispdata(s_dat,d);
for(;;)
{
delay(50);
key=KeyScan();
if(key=='\0')
{
break;
}
}
}
}